Skip to main content

agen

agen (assignment-generator) is a Python 3.12 CLI tool that reads a source-code template file and generates two output files:

  • an assignment file for students (placeholders replace solution blocks)
  • a solution file for instructors (full content with solution markers)

Templates are ordinary source files (.py, .c, etc.) annotated with special comment-tagged blocks that control what appears in each output.


Installation

agen requires Python 3.12+ and is managed with uv.

From package index

uv tool install assignment-generator-sebastian-stigler
agen --help

From source

git clone <repository-url>
cd agen
uv sync

This installs the package and all dependencies into a local virtual environment. The agen command is then available via:

uv run agen --help

To install the tool globally (into a dedicated isolated environment):

uv tool install .
agen --help

Configuration

Configuration is resolved by layered merging:

  1. Built-in defaults (always applied)
  2. Global config — ~/.config/agen/agen-config.json (overrides defaults)
  3. Local config — .agen-config.json in the current working directory (overrides global)

comment_tokens entries are merged key-by-key; all other keys are replaced wholesale by the later layer.

Generating a starter config

agen generate-config > .agen-config.json

Config file format

{
  "comment_tokens": {
    ".py": "#",
    ".c": "//"
  },
  "assignment_marker":      "TODO",
  "solution_marker_begin":  "BEGIN SOLUTION",
  "solution_marker_end":    "END SOLUTION",
  "template_file_prefix":   "template_",
  "assignment_file_prefix": "assignment_",
  "solution_file_prefix":   "solution_",
  "assignment_only_begin":  "BEGIN ASSIGNMENT ONLY",
  "assignment_only_end":    "END ASSIGNMENT ONLY",
  "solution_only_begin":    "BEGIN SOLUTION ONLY",
  "solution_only_end":      "END SOLUTION ONLY",
  "assignment_begin":       "BEGIN ASSIGNMENT",
  "assignment_end":         "END ASSIGNMENT"
}

comment_tokens

A mapping of file extensions (including the leading dot) to the line-comment token for that language. agen uses this token when writing marker lines into the output files. Add an entry for every extension you use in templates, for example ".js": "//" or ".sql": "--".

comment_tokens is the only key that is merged key-by-key across config layers — a later layer can add or override individual extensions without replacing the whole map.

Output markers (assignment_marker, solution_marker_begin, solution_marker_end)

These strings control the text that agen writes into the output files:

  • assignment_marker — the placeholder comment text inserted into the assignment file wherever an ASSIGNMENT block appears.
  • solution_marker_begin / solution_marker_end — comments wrapped around the original block content in the solution file (e.g. # BEGIN SOLUTION … # END SOLUTION).

assignment_marker can be a single line (for example TODO) or multiline text.

assignment_marker supports multiline text. Each non-empty line becomes a commented placeholder line using the configured comment token; empty lines stay empty.

Example config value:

{
  "assignment_marker": "YOUR CODE STARTS HERE >>>\n\n<<<< YOUR CODE ENDS HERE"
}

Example assignment output snippet (for a Python template):

def add(a, b):
    # YOUR CODE STARTS HERE >>>

    # <<<< YOUR CODE ENDS HERE

File prefixes (template_file_prefix, assignment_file_prefix, solution_file_prefix)

These prefixes control automatic output file naming. When agen derives an output path from the template filename it:

  1. Strips template_file_prefix from the start of the template basename (if present).
  2. Prepends assignment_file_prefix or solution_file_prefix to the remainder.

For example, with the defaults a template named template_exercise.py produces assignment_exercise.py and solution_exercise.py. You can override the output path entirely with -a / -s on the command line.

Template block tags (assignment_only_begin/end, solution_only_begin/end, assignment_begin/end)

These are the tag strings that agen looks for inside the template file to delimit the three special block types. Each pair marks where a block starts and ends. They must appear as the sole content of a comment line (after the comment token). Change them only if the defaults conflict with existing comments in your codebase.

Environment variables

Variable Default Description
AGEN_CONFIG_BASENAME agen-config.json Config file basename (both global and local)
AGEN_GLOBAL_CONFIG_PATH ~/.config/agen Directory for the global config file

Template format

Template files are normal source files with specially tagged comment blocks. The file extension determines which line-comment token is used.

Block types

Block tag Assignment output Solution output
ASSIGNMENT_ONLY written as-is omitted
SOLUTION_ONLY omitted written as-is
ASSIGNMENT replaced by a placeholder comment (TODO) wrapped in begin/end solution markers + original content
(unmarked) written as-is written as-is

Example template (template_exercise.py)

def add(a, b):
    # BEGIN ASSIGNMENT
    return a + b
    # END ASSIGNMENT

# BEGIN ASSIGNMENT ONLY
# Implement the add() function above.
# END ASSIGNMENT ONLY

# BEGIN SOLUTION ONLY
# Reference implementation — do not distribute.
# END SOLUTION ONLY

Running agen create both template_exercise.py produces:

assignment_exercise.py

def add(a, b):
    # TODO

# Implement the add() function above.

solution_exercise.py

def add(a, b):
    # BEGIN SOLUTION
    return a + b
    # END SOLUTION

# Reference implementation — do not distribute.

File naming

By default, agen strips a template_ prefix from the template basename and adds assignment_ or solution_ prefixes to the output files. This is configurable — see Configuration.


Usage

agen [COMMAND] [OPTIONS] [ARGS]

Global options

agen --version

Print the installed agen version.

agen check <templatefile>

Validate and summarise a template file without writing any output.

agen check template_exercise.py

Prints block statistics and any warnings.


agen create assignment <templatefile>

Generate the assignment output file only.

agen create assignment template_exercise.py
agen create assignment template_exercise.py -a custom_assignment.py   # custom output path
agen create assignment template_exercise.py -f                        # overwrite existing file
agen create assignment template_exercise.py --dry-run                 # preview without writing
agen create assignment template_exercise.py --anyway                  # skip the no-ASSIGNMENT-block guard
agen create assignment template_exercise.py -v                        # show template stats

agen create solution <templatefile>

Generate the solution output file only.

agen create solution template_exercise.py
agen create solution template_exercise.py -s custom_solution.py       # custom output path
agen create solution template_exercise.py -f                          # overwrite existing file
agen create solution template_exercise.py --dry-run                   # preview without writing
agen create solution template_exercise.py -v                          # show template stats

agen create both <templatefile>

Generate both assignment and solution output files in one command.

agen create both template_exercise.py
agen create both template_exercise.py -f
agen create both template_exercise.py -a out_a.py -s out_s.py
agen create both template_exercise.py --dry-run
agen create both template_exercise.py -v                              # show template stats

agen current-config

Print the effective merged configuration, colour-coded by origin (default / global / local).

agen current-config

agen generate-config

Print a complete default config JSON document, suitable for redirecting into a config file.

agen generate-config > .agen-config.json

Development

uv sync                  # install dependencies
uv run pytest            # run the test suite

Metadata

Release files for assignment-generator-sebastian-stigler 0.3.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for assignment-generator-sebastian-stigler 0.3.1
File Size Uploaded Provenance Actions
assignment_generator_sebastian_stigler-0.3.1.tar.gz 44.2 kB Without provenance Details for assignment_generator_sebastian_stigler-0.3.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for assignment-generator-sebastian-stigler 0.3.1
File Interpreter ABI Platform Actions
assignment_generator_sebastian_stigler-0.3.1-py3-none-any.whl Python 3 none any Details for assignment_generator_sebastian_stigler-0.3.1-py3-none-any.whl

Total release size: 64.2 kB

Release files / assignment_generator_sebastian_stigler-0.3.1.tar.gz

Download URL assignment_generator_sebastian_stigler-0.3.1.tar.gz
Size 44.2 kB
Tags Source
SHA-256 checksum
How to use checksums
8edee6dba35709c9df7de58e2ee82bfa5e078122db43613b62e1699f87a3282c
BLAKE2b-256 checksum
How to use checksums
a0ddcbaa33b415e94e24f86404662020b50b1d6badb375d9422001a550e0f11f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"11","id":"bullseye","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / assignment_generator_sebastian_stigler-0.3.1-py3-none-any.whl

Download URL assignment_generator_sebastian_stigler-0.3.1-py3-none-any.whl
Size 20.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
013b62e2497adda8a1c06785f3d4aeaa18d669bc8462fe5dd8d1f0a0e2bd590c
BLAKE2b-256 checksum
How to use checksums
9c8509bfe08212a715c604e9e5804da77cb05471399444bca180f29adb592d08
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.11.7 {"installer":{"name":"uv","version":"0.11.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"11","id":"bullseye","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for assignment-generator-sebastian-stigler 0.3.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page