Orchestrator CLI that drives Claude Code end-to-end to generate whole projects from a requirements.md file.
Project description
code-generator
A Python CLI that orchestrates Claude Code end-to-end to generate a whole project from a requirements.md file. Five commands — init, optimize, generate, review, status. Works for any project type: Python CLI, FastAPI, Angular, NestJS, full-stack, finance, BAML/LLM.
Max subscription only. This tool uses exclusively the Claude Max subscription. It strips every environment variable that could route a call through the API and aborts on startup if any are still present. There is no path to API credit billing — see Safety constraints below.
Install
pipx install code-generator # recommended
# or
pip install code-generator # user-site
# or, from source
git clone git@github.com:SilvioBaratto/code-generator.git
cd code-generator && pip install -e ".[dev]"
Authentication
# Claude Code (Max subscription)
claude auth login
# GitHub (SSH protocol)
gh auth login -h github.com -p ssh
gh config set git_protocol ssh
Commands
code-generator init [--template TYPE] [--force]
Scaffold .code-generator/ in the current directory with a ready-to-fill requirements.md. Templates: fastapi, angular, nestjs, fullstack, python-cli, finance. Refuses to clobber an existing .code-generator/ without --force.
code-generator init --template fastapi
$EDITOR .code-generator/requirements.md
code-generator optimize [--dry-run] [--force]
Pre-flight rewrite of .code-generator/requirements.md into the canonical structure the orchestrator expects: # Title → ## Description → ## Tech Stack → ## Goals → ## Scope (numbered ### N. subsections with per-section Acceptance criteria checklists) → ## Non-goals → ## Constraints → ## Global acceptance criteria.
Runs a single Opus 4.7 session with a dedicated prompt, preserves the original intent verbatim when ambiguous (never invents new scope), and writes the rewrite back to disk atomically. The pre-optimize original is saved to .code-generator/requirements.backup-<UTC-timestamp>.md so you can always diff and recover. The command is stateless — it never reads or writes state.json and never calls gh.
Short-circuits and exits 0 if the file is already canonical. Use --force to re-optimize anyway. Use --dry-run to print the proposed rewrite to stdout without touching the file or creating a backup.
code-generator optimize --dry-run # preview
code-generator optimize # commit the rewrite
code-generator generate # then run the pipeline
code-generator generate [flags]
Read .code-generator/requirements.md and orchestrate Claude Code through the 0→7 phase pipeline:
| Phase | Action | Model |
|---|---|---|
| 0 | Complexity analysis (single vs multi-cycle) | Opus 4.7 |
| 1 | Planning — creates GitHub issues + milestone | Opus 4.7 |
| 2 | Per-issue review | Opus 4.7 |
| 3-4 | Implementation, fresh SDK session per issue (TDD) | Sonnet 4.6 |
| 5 | Closure + cross-module review | Opus 4.7 |
| 6 | Test suite, max 3 retries on failure | Sonnet 4.6 |
| 7 | Commit message + git add/commit/push | Opus 4.7 |
Every phase logs a completion summary with token counts (in, cache_read, cache_write, out) and persists them to state.json.
Flags:
| Flag | Description | Default |
|---|---|---|
--dry-run |
Run only Phase 0 + Phase 1 (planning) | false |
--phase N |
Resume from phase N | — |
--continue |
Resume from the last completed phase (reads state.json) |
false |
--mode auto|single|multi-cycle |
Force a mode (default auto runs Phase 0 first) |
auto |
--cycle N |
Resume from cycle N (multi-cycle only) | — |
--max-turns N |
Opt-in per-session turn cap for debugging or strict cost control (positive integer); omit for no cap | — |
Turn budgets
No per-session turn budget is set by default. Sessions terminate via end_turn on the model side; the real safety nets are rate-limit handling, overage abort (non-negotiable #4), and task budgets — not a guessed integer. --max-turns N exists on generate, optimize, and review as an opt-in for debugging or strict cost control; it is not for production.
In multi-cycle mode each cycle is a GitHub Milestone and produces a committable, working increment. Each cycle starts a fresh SDK session and re-reads the committed codebase, so the model never relies on stale conversational context.
If the Max subscription hits a rate limit, the tool pauses — it persists the session id and paused_until timestamp atomically to .code-generator/state.json, sleeps until the window resets, and resumes with --resume <session_id>. A killed process will resume on its own when re-run.
code-generator review [--create-issues] [--severity LEVEL]
Run a standalone Opus 4.7 review of the current codebase against the design principles in requirements.md §4 (SOLID, Clean Code, TDD, YAGNI/KISS/DRY). With --create-issues, every finding becomes a GitHub Issue.
code-generator status
Print a Rich table with the current mode, current cycle, current phase, open/closed issue counts, the rate-limit pause state (with minutes remaining if paused), per-cycle token consumption columns (in | cache_read | cache_write | out), wall-clock elapsed time, and any last_error highlighted in red.
Running against Ollama Pro
An opt-in subcommand, code-generator generate ollama, runs the full 0→7 pipeline against one Ollama-hosted model instead of the Anthropic Max subscription. This is the only supported way to bypass the Max-subscription invariant and is gated by provider == "ollama" inside env.py.
One-time setup
-
Install the Ollama daemon (≥ 0.14.0) and start it on the default endpoint
http://localhost:11434. -
Sign the daemon into your Ollama Pro account — required for any
:cloudmodel:ollama signin -
Export your existing
OLLAMA_API_KEY(the same secret you already use elsewhere — no new secret is introduced):export OLLAMA_API_KEY=... # typically set once in ~/.zshrc
Preflight refuses to run if the daemon is unreachable, not signed in, or OLLAMA_API_KEY is empty — fix the message it prints and re-run.
Worked examples
# Plan + implement a whole repo on a cloud-hosted 480B coding model
code-generator generate ollama --model "qwen3-coder:480b:cloud"
# Same pipeline on a different cloud model
code-generator generate ollama --model "gpt-oss:120b-cloud"
The --model tag you pass drives every phase (0 through 7). There is no per-phase override on this codepath: single-model is the whole point. The tag is persisted to state.json as CycleState.ollama_model so code-generator generate ollama --continue resumes with the same model without re-typing it.
What is overridden vs. preserved
- Overridden under
provider == "ollama": non-negotiable #1 (Max-only env strip is narrowed toANTHROPIC_AUTH_TOKEN/ANTHROPIC_BASE_URLpassthrough), #4 (no Anthropic overage telemetry — replaced by turn-count + wall-clock budgets), #8 (fixed-model-per-phase — replaced by single-model routing). - Preserved on every path: #2 (never
--bare), #3 (YOLO permissions), #5 (wait-and-resume on 429), #6 (fresh context per issue), #7 (atomic state writes), #9 (no defaultmax_turns).
Safety constraints
The tool enforces nine non-negotiables (see CLAUDE.md for the full list):
- Max subscription only, zero API credits. Before any SDK or subprocess call, the tool strips
ANTHROPIC_API_KEY,ANTHROPIC_AUTH_TOKEN,ANTHROPIC_BEDROCK_API_KEY,ANTHROPIC_VERTEX_PROJECT_ID,CLAUDE_CODE_USE_BEDROCK,CLAUDE_CODE_USE_VERTEXfrom the environment. A startup check refuses to run if any are present. - Never
--bare. The CLI flag--bareskips OAuth and forces API credits — it is never passed by this tool. If Anthropic ever makes--barethe default forclaude -p, pin the CLI version or pass the opposite flag explicitly. - YOLO mode always. Every SDK call uses
permission_mode="bypassPermissions"; the subprocess fallback uses--dangerously-skip-permissions. - Overage protection. On every
RateLimitEvent, the tool checksinfo.overage_statusand aborts immediately if it is anything other thanNoneor"disabled". Reference incident: anthropics/claude-code#37686 — a user burned $1,800 in two days because billing overage was silently enabled. - Wait-and-resume rate-limit handling. Rate limits are not retried with exponential backoff — the tool sleeps until
resets_at + 60sand resumes the same session. Backoff (10→20→40→80→120s) only applies to non-rate-limit transient errors. - Fresh SDK session per issue. The implementation phase never reuses conversational context across issues — each issue is a
/clear-equivalent fresh session. - Atomic state writes.
.code-generator/state.jsonis updated viatmp → os.replace(tmp, STATE)so a crash mid-write cannot corrupt it. - Fixed model per phase. Opus 4.7 for phases 0/1/2/5/7; Sonnet 4.6 for phases 3/4/6.
Troubleshooting
Startup fails with "dangerous environment variables present". A previous shell session exported ANTHROPIC_API_KEY (or another billing-routing variable). unset it and try again — the tool is intentionally strict so a stray export never costs you money.
Rate limit reached. Run code-generator status to see how many minutes remain on the current pause. The next code-generator generate --continue will wait out the rest of the window and resume the same session automatically.
gh issue create fails. Confirm gh auth status reports an authenticated SSH session for github.com, and that the current directory is inside a repo with a default remote configured.
Tests don't pass after Phase 6. The orchestrator skips Phase 7 (commit) when the test runner reports persistent failures. Fix the failing tests manually, then run code-generator generate --continue to re-enter from where it stopped.
Project layout
src/code_generator/
├── cli.py # Typer entry point: init, generate, review, status
├── env.py # DANGEROUS_VARS, build_agent_env, assert_safe_environment
├── state.py # State dataclasses + atomic load/save
├── prompts/ # Packaged prompt-phase-*.md files + load_prompt
├── templates/ # Project templates for `init`
├── logging_setup.py # Per-phase log files under .code-generator/logs/
├── gh.py # Subprocess wrapper for issues, milestones, labels
├── agents.py # Tech-stack detector + agent selection matrix
├── runner/
│ ├── sdk_runner.py # claude-agent-sdk wrapper, RateLimitEvent handling
│ ├── subprocess_runner.py # CLI fallback, stream-json parser
│ ├── rate_limit.py # Wait-and-resume main loop
│ └── retry.py # Backoff + circuit breaker
├── orchestrator/
│ ├── phase0_complexity.py # single vs multi-cycle decision
│ ├── phase1_plan.py # milestone + issues
│ ├── phase2_review.py # per-issue review
│ ├── phase3_4_implement.py # TDD loop, fresh session per issue
│ ├── phase5_closure.py # closure + fix-issue feedback loop
│ ├── phase6_test.py # test runner, max 3 retries
│ ├── phase7_commit.py # Opus commit message + push with rebase retry
│ └── cycle_loop.py # multi-cycle driver
└── commands/ # init, optimize, status, generate, review (Typer commands)
Development
git clone git@github.com:SilvioBaratto/code-generator.git
cd code-generator
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest -q
ruff check src tests
Benchmarking
code-generator bench --fake --cycles 3 --output bench.json
Reference
The full specification lives in requirements.md. Each prompt file (prompt-phase-*.md, prompt-review.md) is loaded verbatim by the orchestrator with {NAME} placeholders substituted at runtime — edit the prompts there, not inline in Python.
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file claude_code_generator-0.4.8.tar.gz.
File metadata
- Download URL: claude_code_generator-0.4.8.tar.gz
- Upload date:
- Size: 380.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bb2119dd5d590212c32a897f5582022a779ae3c4fbd41adfec4408a456ceeaee
|
|
| MD5 |
87f34c051e813aacf543b7436243af2b
|
|
| BLAKE2b-256 |
2f42341bc73c85e8bad80dc26bd9ca1bf63588cf92fd3afff629071bb6b3938f
|
File details
Details for the file claude_code_generator-0.4.8-py3-none-any.whl.
File metadata
- Download URL: claude_code_generator-0.4.8-py3-none-any.whl
- Upload date:
- Size: 206.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
91d155e7e1a8b820996f75e407b6db7a68978d748441688611fd1c613f629e79
|
|
| MD5 |
b73c419c45731cfd31b1c9d50e068923
|
|
| BLAKE2b-256 |
974e5cc57583a7d88c12fad1d2a2f339a149139d4f1ebcb8302f48a9a53e3f09
|