Skip to main content

Adding or changing a command

Every command is a command_<name> function in src/skillgen/cli.py, registered in HANDLERS. In the same pull request:

  1. Add command_<name> and its parser in cli.py, and register it in HANDLERS.
  2. Add src/skillgen/schema/cli/<name>.schema.json for its --json output.
  3. Add tests.
  4. Document it for users in the README's Command reference, every flag included.
  5. Document it for maintainers in CONTRIBUTING's "Commands: where each one lives" table.

tests/test_docs.py fails when a command or flag is missing from either document, and tests/test_cli.py fails when a command has no schema. Please update this site's command reference and JSON output pages too.

Rules a command follows​

  • It never prompts or waits for input. An agent runs it. If it needs the developer, it does all it can, then reports a next step (exit code 3). See The agent handoff.
  • Replacing existing output is the one decision that stops before any work, and it takes a flag for the answer (like --overwrite).
  • It returns a Reply: data for --json, lines for text, is_ok, needs_action. Only cli.py prints.
  • It raises SkillgenError subclasses for expected failures (exit code 2).
  • Its --json output matches its schema, or emit replaces it with an internal error.

Where each command lives​

CommandMain codeTests
initworkspace.py, config.pytest_cli.py, test_workspace.py, test_config.py
routespipeline.discover_routes, routes/, graph/hubs.py, pipeline.ask_claude_for_routestest_folders.py, test_astgrep.py, test_hintpacks.py, test_hubs.py, test_cli.py
preparepipeline.prepare_route, analyze/prompt.pytest_cli.py, test_prompt.py
generatepipeline.analyze_route / finish_route, compile/, generate/, validate/; --overwrite in cli.hold_existing_skills; --xy in cli._layout_measurer → probe.runner.measure_page_layout; --open in cli._with_open_steps → pipeline.apply_open_steps; next in cli.describe_next_step → handoff.build_next_steptest_fixtures.py, test_merge.py, test_pipeline.py, test_handoff.py, test_cli.py
questions, answercli.py, compile/assess.pytest_cli.py, test_assess.py
add-rulegenerate/user_rules.pytest_user_rules.py, test_fixtures.py
validatevalidate/spec.py, validate/scan.pytest_spec.py, test_scan.py
indexgenerate/index_page.py, pipeline.write_indextest_index_page.py, test_cli.py
checkdrift/check.py, drift/diff.pytest_check.py, test_diff.py, test_cli.py
exportexport.pytest_export.py, test_cli.py
export-chatgptexport.export_chatgpt_plugintest_export.py, test_cli.py
probe, loginprobe/runner.py (Playwright, lazily imported)test_probe_runner.py (-m browser)
logslogs.pytest_logs.py
installclaude/ (shipped as package data); Chromium in cli.install_chromiumtest_cli.py (never downloads)
doctorcli.pytest_cli.py