Skip to main content

Task automation from markdown specs via Claude CLI

Project description

spec-runner

Task automation from markdown specs via Claude CLI. Execute tasks from a structured tasks.md file with automatic retries, 5-role code review, Git integration, compliance verification, traceability reporting, and live TUI dashboard.

Installation

uv add spec-runner

Or for development:

uv sync

Requirements:

  • Python 3.10+
  • Claude CLI (claude command available)
  • Git (for branch management)
  • gh CLI (optional, for GitHub Issues sync)

Quick Start

# Install Claude Code skills (creates .claude/skills in current project)
spec-runner-init

# Execute next ready task
spec-runner run

# Execute specific task
spec-runner run --task=TASK-001

# Execute all ready tasks
spec-runner run --all

# Execute with live TUI dashboard
spec-runner run --all --tui

# Create tasks interactively
spec-runner plan "add user authentication"

# Watch mode — continuously execute ready tasks
spec-runner watch

Features

  • Task-based execution — reads tasks from spec/tasks.md with priorities, checklists, and dependencies
  • Specification traceability — links tasks to requirements (REQ-XXX) and design (DESIGN-XXX)
  • Automatic retries — configurable retry policy with exponential backoff and error context forwarding
  • Code review — multi-agent review after task completion with enriched diff context
  • Git integration — automatic branch creation, commits, and merges
  • TUI dashboard — live Textual-based terminal UI with progress bars and log panel
  • Cost tracking — per-task token usage and cost breakdown
  • Watch mode — continuously poll and execute ready tasks
  • Plugin system — extend with custom hooks via spec/plugins/*/plugin.yaml
  • MCP server — Model Context Protocol server for Claude Code integration (read + write operations)
  • GitHub Issues sync — bidirectional sync between tasks.md and GitHub Issues
  • Interactive planning — generate specs (requirements + design + tasks) through dialogue with Claude
  • Structured logging — JSON/console output via structlog
  • SQLite state — persistent execution state with WAL mode, auto-migration from legacy JSON
  • HITL review — optional human-in-the-loop approval gate after code review
  • Parallel review — 5 specialized review agents (quality, implementation, testing, simplification, docs) running concurrently
  • Agent personas — role-specific prompt templates and model selection (architect, implementer, reviewer)
  • Constitution guardrails — inviolable project rules from spec/constitution.md injected into every prompt
  • Telegram / webhook notifications — alerts on task failure, run completion, and degraded-mode persistence failures (Telegram Bot API + generic webhook)
  • Degraded-mode resilience — SQLite write failures (disk-full, DB corruption) are caught, the run continues in memory, and operators are notified once
  • Compliance audit trail — opt-in JSON-Lines log of every task lifecycle event (started, attempt, completed/failed, state_degraded, run start/end) with operator + run-id attribution
  • Pause/resume — pause mid-run with Ctrl+, edit tasks, resume; TUI keybinding p
  • Streaming events — live stdout streaming from Claude CLI to TUI via EventBus
  • Session/idle timeouts — automatic stop after configurable session or idle duration

Task File Format

Tasks are defined in spec/tasks.md:

## Milestone 1: MVP

### TASK-001: Implement user login
🔴 P0 | ⬜ TODO | Est: 2d

**Checklist:**
- [ ] Create login endpoint
- [ ] Add JWT token generation
- [ ] Write unit tests

**Traces to:** [REQ-001], [DESIGN-001]
**Depends on:****Blocks:** [TASK-002], [TASK-003]

CLI Commands

spec-runner

# Execution
spec-runner run                            # Execute next ready task
spec-runner run --task=TASK-001            # Execute specific task
spec-runner run --all                      # Execute all ready tasks (resets failed→pending by default)
spec-runner run --all --no-reset-failed    # Keep failed tasks sticky (skip the default reset)
spec-runner run --all --hitl-review        # Interactive HITL approval gate
spec-runner run --force                    # Skip lock check (stale lock)
spec-runner run --tui                      # Execute with live TUI dashboard
spec-runner run --dry-run                  # Show what would execute (JSON)
spec-runner run --json-result              # Structured JSON output (Maestro interop)
spec-runner run --budget=10.0              # Set global budget in USD
spec-runner run --log-level=DEBUG          # Set log verbosity
spec-runner run --log-json                 # Output logs as JSON

# Monitoring
spec-runner status                         # Show execution status
spec-runner status --json                  # JSON status output
spec-runner costs                          # Cost breakdown per task
spec-runner costs --json                   # JSON output for automation
spec-runner costs --sort=cost              # Sort by cost descending
spec-runner logs TASK-001                  # View task logs

# Operations
spec-runner retry TASK-001                 # Retry failed task
spec-runner reset                          # Reset state
spec-runner watch                          # Continuously execute ready tasks
spec-runner watch --tui                    # Watch with live TUI dashboard
spec-runner tui                            # Launch TUI status dashboard
spec-runner validate                       # Validate config and tasks

# Verification & Reporting (v2.0)
spec-runner audit                          # Static pre-execution spec check
spec-runner audit --strict                 # Fail on warnings (orphans, uncovered)
spec-runner audit --json                   # JSON findings output (for CI)
spec-runner audit --csv                    # CSV for spreadsheet review
spec-runner verify                         # Verify post-execution compliance
spec-runner verify --task=TASK-001         # Verify specific task
spec-runner verify --json                  # JSON compliance output
spec-runner verify --strict                # Fail on warnings too
spec-runner report                         # Generate traceability matrix
spec-runner report --milestone=mvp         # Filter by milestone
spec-runner report --uncovered-only        # Show only uncovered requirements
spec-runner report --json                  # JSON matrix output

# Planning
spec-runner plan "description"             # Interactive task planning
spec-runner plan --full "description"      # Generate full spec (requirements + design + tasks)
spec-runner plan --full --from-file spec.md  # Read the description from a file instead of an arg
spec-runner plan --gated --profile lite    # Select the gated stage profile (default: lite)

# Diagnostics
spec-runner doctor                              # Probe the configured CLI/model (real mini-task)
spec-runner doctor --cli=codex --model=gpt-5.4  # Probe an ad-hoc CLI+model
spec-runner doctor --with-review                # Also probe the review stage
spec-runner doctor --json --yes                 # Machine-readable, no confirmation (CI)
spec-runner doctor --strict                     # Exit non-zero on DEGRADED too

# Integration
spec-runner mcp                            # Launch MCP server (stdio)

Task Management (unified in v2.0)

# Task commands (use `spec-runner task` instead of deprecated `spec-task`)
spec-runner task list                      # List all tasks
spec-runner task list --status=todo        # Filter by status
spec-runner task list --priority=p0        # Filter by priority
spec-runner task list --milestone=mvp      # Filter by milestone
spec-runner task show TASK-001             # Task details
spec-runner task start TASK-001            # Mark as in_progress
spec-runner task done TASK-001             # Mark as done
spec-runner task block TASK-001            # Mark as blocked
spec-runner task check TASK-001 2          # Mark checklist item
spec-runner task stats                     # Statistics
spec-runner task next                      # Show next ready tasks
spec-runner task graph                     # ASCII dependency graph

# GitHub Issues
spec-runner task export-gh                 # Export to GitHub Issues format
spec-runner task sync-to-gh                # Sync tasks -> GitHub Issues
spec-runner task sync-to-gh --dry-run      # Preview without making changes
spec-runner task sync-from-gh              # Sync GitHub Issues -> tasks.md

spec-runner-init

spec-runner-init                           # Install skills to ./.claude/skills
spec-runner-init --force                   # Overwrite existing skills
spec-runner-init /path/to/project          # Install to specific project

Multi-phase Options

--spec-prefix namespaces tasks, state, logs, and history for phase-based workflows:

spec-runner run --spec-prefix=phase5-          # Uses spec/phase5-tasks.md
spec-runner task list --spec-prefix=phase5-    # List phase 5 tasks

Phase-scoped paths: spec/phase5-{tasks,requirements,design}.md, spec/.executor-phase5-state.db, spec/.executor-phase5-logs/, spec/.phase5-task-history.log. Multiple phases coexist without state bleed.

Spec Governance (gated generation)

An opt-in workflow for generating and approving requirements.md / design.md / tasks.md one stage at a time instead of all at once, with a human checkpoint between stages:

spec-runner plan --gated "description"     # Generate the next stage as DRAFT (auto-resolved)
spec-runner plan --gated --stage design    # ...or a specific stage (upstream must be approved)
spec-runner spec status                    # Show each stage's status + the recommended next action
# edit the generated file if needed, then:
spec-runner spec approve requirements      # Re-validates the body, then approves (bumps version)
spec-runner plan --gated --stage design    # Repeat per stage: requirements -> design -> tasks
spec-runner spec approve tasks
spec-runner run                            # Or `spec-runner run --strict` to enforce the gate below

Each managed spec file carries a small YAML frontmatter block tracking one of three statuses:

  • draft — generated (or edited) but not yet approved.
  • approved — validated and signed off; bumps the file's version.
  • stale — an upstream stage was re-approved after this one was generated, so this stage may be out of sync and should be regenerated or re-reviewed.

Other useful commands: spec-runner spec reject <stage> reopens an approved/stale stage as draft; spec-runner spec adopt <stage> stamps frontmatter onto an existing unmanaged file (validates first — a failing file is adopted as draft unless you pass --force); spec-runner spec check <stage> refreshes the cached validation verdict without approving.

Set spec_governance: strict in spec-runner.config.yaml (default: off) to make run/watch refuse to execute a managed tasks.md that isn't approved; --strict/--no-strict override this per invocation.

Stage profiles

The stage chain is data, loaded from a bundled profile. The default lite profile is requirements → design → tasks (the historical chain). Select a profile with spec_profile: in spec-runner.config.yaml or the --profile flag on plan --gated and the spec command family; an unknown profile name fails with a clear error listing the available profiles. Profiles live in src/spec_runner/profiles/*.yaml, each stage declaring its template, marker prefix, validator, and upstream stages.

Guardrail, not an enforcement boundary. strict mode only blocks tasks.md files that carry gated-spec frontmatter. Deleting the frontmatter (or never adopting it) makes the file "unmanaged," which always passes the gate for backward compatibility with unmanaged and Maestro-produced specs. Treat this as a workflow guardrail against accidental unapproved runs, not a security control.

Usage as Library

from spec_runner import Task, ExecutorConfig, parse_tasks, get_next_tasks
from pathlib import Path

tasks = parse_tasks(Path("spec/tasks.md"))
ready = get_next_tasks(tasks)

for task in ready:
    print(f"{task.id}: {task.name} ({task.priority})")

MCP Server (Claude Code Integration)

spec-runner includes an MCP server for querying status and executing tasks from Claude Code.

Add to .mcp.json:

{
  "mcpServers": {
    "spec-runner": {
      "command": "spec-runner",
      "args": ["mcp"]
    }
  }
}

Available tools:

Tool Kind Effect
spec_runner_status read Returns aggregate status (completed/failed/running, cost, tokens)
spec_runner_tasks read Lists tasks with id/name/priority/status/deps
spec_runner_next_tasks read Lists ready-to-run tasks
spec_runner_task_detail read Returns per-task checklist, attempts, last review, cost
spec_runner_costs read Per-task cost/token breakdown
spec_runner_logs read Tail of a task's execution log
spec_runner_run_task write Spawns a subprocess that runs Claude CLI against the workspace. Can modify files, create git branches, run hooks (tests/lint/commit)
spec_runner_stop write Writes a stop-file that asks a running executor to shut down gracefully

Security model

Authentication. The MCP server has no built-in authentication. It uses stdio transport and inherits the trust boundary of whatever started it (typically your terminal or Claude Code). Whoever can run the server can call any of its tools.

Safe deployment patterns:

  • Local stdio only (default). Run via spec-runner mcp from .mcp.json on a single developer machine. Same trust boundary as your shell.
  • Claude Code inside your own workspace. The MCP server operates on the workspace it's invoked in; tools like spec_runner_run_task will modify files in that workspace.
  • Do NOT expose over TCP, HTTP, or a shared socket without adding authentication and audit logging — the write tools execute subprocesses that run Claude CLI with full filesystem access.
  • Do NOT run under a shared service account that multiple users or agents share. There is no per-caller identity, so audit logs cannot attribute actions.

Write-tool blast radius. spec_runner_run_task does not sandbox execution: the spawned spec-runner run --task TASK-XXX can:

  • edit any file in the project root
  • create git branches and auto-commit (if hooks.post_done.auto_commit: true)
  • run tests, linters, and any configured hook command
  • spend budget (Claude API cost) up to budget_usd / task_budget_usd

Treat the MCP server as equivalent to giving the caller shell access to the workspace.

Hardening options (if you need tighter limits):

  • Run in a disposable container or Maestro worktree so writes are isolated
  • Set budget_usd low to cap accidental cost spend
  • Disable hooks.post_done.auto_commit if you want manual review before commits
  • Restrict commands.test/commands.lint to safe allow-listed shell commands — they run verbatim

See also: docs/state-schema.md for the read contract, and src/spec_runner/mcp_server.py for tool implementations.

Configuration

Configuration file: spec-runner.config.yaml (project root, v2.0)

Legacy location spec/executor.config.yaml is still supported with a deprecation warning.

v2.0 flat format (no executor: wrapper):

max_retries: 3
task_timeout_minutes: 30
claude_command: "claude"
claude_model: "sonnet"
spec_prefix: ""                # e.g. "phase5-" for phase5-tasks.md
budget_usd: 50.0               # Total budget cap (whole run)
task_budget_usd: 10.0          # Per-task cap incl. first attempt
max_retry_cost_usd: 2.0        # Cap on retry cost only (attempts 2+)

# Telegram notifications (optional)
telegram_bot_token: ""         # Bot token from @BotFather
telegram_chat_id: ""           # Chat ID to send notifications to
notify_on: [run_complete, task_failed, state_degraded]

# Generic webhook (optional — works with Slack, Discord, ntfy.sh, etc.)
webhook_url: ""                # Webhook URL (empty = disabled)
webhook_template: '{"text": "{{event}}: {{message}}"}'

# Compliance audit trail (optional — JSON Lines, opt-in)
audit_log_path: ""             # e.g. "spec/.executor-audit.jsonl"; empty = disabled
audit_log_operator: ""         # Override the auto-detected "user@host" tag

# Agent personas (optional)
personas:
  implementer:
    system_prompt: "You are a focused Python developer"
    model: "sonnet"
  reviewer:
    system_prompt: "You are a senior code reviewer"
    model: "haiku"

hooks:
  pre_start:
    create_git_branch: true
  post_done:
    run_tests: true
    run_lint: true
    auto_commit: true
    run_review: true
    review_parallel: false     # Run 5 review agents in parallel
    review_roles: [quality, implementation, testing]

commands:
  test: "uv run pytest tests/ -v"
  lint: "uv run ruff check ."

paths:
  root: "."
  logs: "spec/.executor-logs"

Git Branch Workflow

  1. Branch detection: Auto-detects main or master, or use main_branch config
  2. Task branches: Creates task/TASK-001-short-name branches for each task
  3. Auto-merge: Merges task branch to main after completion

Supported CLIs

CLI Auto-detected Example template
Claude Yes {cmd} -p {prompt} --model {model}
Codex Yes {cmd} exec -m {model} {prompt} (codex's -p is --profile, not the prompt)
OpenCode (sst/opencode) Yes {cmd} run --model {model} {prompt}
Pi Agent (pi.dev) Yes (basename match) {cmd} -p --model {model} {prompt}
Ollama Yes {cmd} run {model} {prompt}
llama-cli Yes {cmd} -m {model} -p {prompt} --no-display-prompt
Custom Use template {cmd} --prompt {prompt}

Full pi-driven loop: pi can run the entire dev → review → test cycle (with native skills, per-stage tool control and a read-only review gate) using only config and a small script — no core code. See docs/pi-workflow.md and the runnable examples/pi-loop/.

Switching CLI (claude / codex / pi / ...)

Apply a preset instead of hand-editing spec-runner.config.yaml:

spec-runner config --preset codex                 # everything on codex
spec-runner config --exec claude --review codex    # claude codes, codex reviews
spec-runner config --list-presets                  # claude codex opencode pi ollama llama-cli qwen copilot
spec-runner config --preset pi --apply             # update an existing config

Tests stay on your test_command (e.g. pytest); presets only set the exec and review CLIs. Run spec-runner doctor afterwards to verify the profile.

Using Qwen

Qwen works two cheap ways, both already supported:

  • Cloud (cheap), via OpenCode: spec-runner config --preset opencode --model "openrouter/qwen/qwen3-coder" (any OpenCode-supported Qwen provider/model string).
  • Local, via Ollama: ollama pull qwen2.5-coder:32b then spec-runner config --preset ollama --model "qwen2.5-coder:32b".

Or use the official agents directly:

  • Qwen Code CLI: spec-runner config --preset qwen --model qwen-coder-plus (or set the model in ~/.qwen/settings.json).
  • GitHub Copilot CLI: spec-runner config --preset copilot --model claude-haiku-4.5 (needs Copilot access; set the model via COPILOT_MODEL).

Run spec-runner doctor afterwards to confirm the chosen CLI is READY.

Checking CLI/model compatibility

spec-runner doctor runs a real one-task probe through the actual execution path and reports, per capability, whether your CLI/model works:

  • invocation — the command runs and authenticates
  • completion_marker — the model prints TASK_COMPLETE (not all models do)
  • task_action — the model actually performs the work
  • cost_tracking — token/cost parsing works (needed for costs/--budget)
  • error_classification — failures are classified (diagnostic)
  • review (with --with-review) — the reviewer prints REVIEW_PASSED/FAILED

Verdict: READY / DEGRADED (works, but something like cost tracking is unavailable) / BROKEN. It makes real, billable model calls (capped by --budget, default $0.50) and asks for confirmation unless --yes.

Project Structure

project/
├── pyproject.toml
├── spec-runner.config.yaml      # v2.0 config location
├── Makefile
├── .pre-commit-config.yaml
├── src/
│   └── spec_runner/
│       ├── __init__.py
│       ├── executor.py          # Re-exports (backward compat)
│       ├── cli.py               # Main CLI dispatcher, cmd_run, cmd_watch
│       ├── cli_info.py          # Status, costs, logs, validate, verify, report, TUI, MCP
│       ├── cli_plan.py          # Interactive planning command
│       ├── execution.py         # Task execution + retry logic
│       ├── errors.py            # CLI stderr → human-readable failure reasons
│       ├── stages.py            # Per-task sub-stage tracking (StageReporter)
│       ├── config.py            # ExecutorConfig + YAML loading
│       ├── state.py             # SQLite state persistence + degraded-mode fallback
│       ├── prompt.py            # Prompt building + templates
│       ├── hooks.py             # Pre/post hook orchestration
│       ├── git_ops.py           # Git branch/commit/merge operations
│       ├── review.py            # 5-role code review + HITL gate
│       ├── runner.py            # Subprocess execution + event streaming
│       ├── task.py              # Task parsing + dependency resolution
│       ├── task_commands.py     # Task CLI commands (list, show, start, etc.)
│       ├── github_sync.py       # GitHub Issues sync (to/from)
│       ├── audit.py             # Pre-execution static audit (LABS-37)
│       ├── audit_log.py         # JSON Lines compliance audit trail (LABS-40)
│       ├── verify.py            # Post-execution compliance verification
│       ├── report.py            # Traceability matrix generation
│       ├── validate.py          # Config + task validation
│       ├── plugins.py           # Plugin discovery + hooks
│       ├── logging.py           # Structured logging (structlog back-compat shim)
│       ├── obs.py               # OTel JSONL observability emitter (shared contract)
│       ├── events.py            # EventBus for streaming to TUI
│       ├── notifications.py     # Telegram + webhook notifications
│       ├── tui.py               # Textual TUI dashboard
│       ├── mcp_server.py        # MCP server (FastMCP, stdio)
│       ├── init_cmd.py          # Skill installer
│       ├── profiles/            # Bundled gated-spec stage profiles (lite.yaml)
│       └── skills/
│           └── spec-generator-skill/
├── docs/
│   └── state-schema.md          # Maestro interop contract (SQLite + --json-result)
├── schemas/
│   ├── executor-state.schema.json   # JSON Schema for .executor-state.db contents
│   └── json-result.schema.json      # JSON Schema for `run --json-result` stdout
├── tests/
│   └── fixtures/maestro-interop/    # Golden fixtures copied by Maestro contract tests
└── spec/
    ├── tasks.md
    ├── requirements.md
    ├── design.md
    ├── FORMAT.md                # Task format specification
    └── plugins/                 # Optional: per-plugin subdirectories with plugin.yaml

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spec_runner-2.10.0.tar.gz (301.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

spec_runner-2.10.0-py3-none-any.whl (210.2 kB view details)

Uploaded Python 3

File details

Details for the file spec_runner-2.10.0.tar.gz.

File metadata

  • Download URL: spec_runner-2.10.0.tar.gz
  • Upload date:
  • Size: 301.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for spec_runner-2.10.0.tar.gz
Algorithm Hash digest
SHA256 f75055d6cd238108e4c4277b9ff42e371179e9d349588ad96335cead8922c062
MD5 586a5dd2ea5c91e2d0e7e218a47fa004
BLAKE2b-256 dba9637704f532386f326d0da821ffe28b97aa1e41b947ce818a45054f14dd2c

See more details on using hashes here.

Provenance

The following attestation bundles were made for spec_runner-2.10.0.tar.gz:

Publisher: publish.yml on andrei-shtanakov/spec-runner

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file spec_runner-2.10.0-py3-none-any.whl.

File metadata

  • Download URL: spec_runner-2.10.0-py3-none-any.whl
  • Upload date:
  • Size: 210.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for spec_runner-2.10.0-py3-none-any.whl
Algorithm Hash digest
SHA256 94a070d9d282c92c2f9f649f33e45997ccee38ac781e24b64c0cff7e82620ef0
MD5 7c1ca58620f9b8b8cb94a725e5df9860
BLAKE2b-256 fba718866b3b26bfcaa8adb4d075e094341a2cc26f75f243c18dcee20513876e

See more details on using hashes here.

Provenance

The following attestation bundles were made for spec_runner-2.10.0-py3-none-any.whl:

Publisher: publish.yml on andrei-shtanakov/spec-runner

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page