claude-code-generator 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- claude_code_generator-0.1.0.dist-info/METADATA +176 -0
- claude_code_generator-0.1.0.dist-info/RECORD +49 -0
- claude_code_generator-0.1.0.dist-info/WHEEL +5 -0
- claude_code_generator-0.1.0.dist-info/entry_points.txt +2 -0
- claude_code_generator-0.1.0.dist-info/licenses/LICENSE +21 -0
- claude_code_generator-0.1.0.dist-info/top_level.txt +1 -0
- code_generator/__init__.py +3 -0
- code_generator/agents.py +177 -0
- code_generator/cli.py +49 -0
- code_generator/commands/__init__.py +1 -0
- code_generator/commands/generate.py +252 -0
- code_generator/commands/init.py +72 -0
- code_generator/commands/review.py +117 -0
- code_generator/commands/status.py +83 -0
- code_generator/env.py +55 -0
- code_generator/gh.py +331 -0
- code_generator/logging_setup.py +73 -0
- code_generator/orchestrator/__init__.py +4 -0
- code_generator/orchestrator/cycle_loop.py +371 -0
- code_generator/orchestrator/phase0_complexity.py +159 -0
- code_generator/orchestrator/phase1_plan.py +170 -0
- code_generator/orchestrator/phase2_review.py +126 -0
- code_generator/orchestrator/phase3_4_implement.py +164 -0
- code_generator/orchestrator/phase5_closure.py +154 -0
- code_generator/orchestrator/phase6_test.py +98 -0
- code_generator/orchestrator/phase7_commit.py +167 -0
- code_generator/prompts/__init__.py +86 -0
- code_generator/prompts/prompt-phase-0-complexity.md +85 -0
- code_generator/prompts/prompt-phase-1-planning.md +209 -0
- code_generator/prompts/prompt-phase-2-issue-review.md +84 -0
- code_generator/prompts/prompt-phase-3-implementation.md +191 -0
- code_generator/prompts/prompt-phase-5-final-review.md +135 -0
- code_generator/prompts/prompt-phase-6-test.md +102 -0
- code_generator/prompts/prompt-phase-7-commit.md +103 -0
- code_generator/prompts/prompt-review.md +124 -0
- code_generator/runner/__init__.py +26 -0
- code_generator/runner/rate_limit.py +113 -0
- code_generator/runner/retry.py +165 -0
- code_generator/runner/sdk_runner.py +267 -0
- code_generator/runner/subprocess_runner.py +200 -0
- code_generator/state.py +178 -0
- code_generator/templates/__init__.py +1 -0
- code_generator/templates/angular.md +12 -0
- code_generator/templates/base.md +28 -0
- code_generator/templates/fastapi.md +12 -0
- code_generator/templates/finance.md +9 -0
- code_generator/templates/fullstack.md +24 -0
- code_generator/templates/nestjs.md +9 -0
- code_generator/templates/python-cli.md +9 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: claude-code-generator
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Orchestrator CLI that drives Claude Code end-to-end to generate whole projects from a requirements.md file.
|
|
5
|
+
Author: Silvio Baratto
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/SilvioBaratto/code-generator
|
|
8
|
+
Project-URL: Repository, https://github.com/SilvioBaratto/code-generator
|
|
9
|
+
Project-URL: Issues, https://github.com/SilvioBaratto/code-generator/issues
|
|
10
|
+
Keywords: claude,claude-code,code-generation,llm,cli,orchestrator
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Topic :: Software Development :: Code Generators
|
|
20
|
+
Requires-Python: >=3.11
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: claude-agent-sdk
|
|
24
|
+
Requires-Dist: typer
|
|
25
|
+
Requires-Dist: rich
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest; extra == "dev"
|
|
28
|
+
Requires-Dist: pytest-asyncio; extra == "dev"
|
|
29
|
+
Requires-Dist: ruff; extra == "dev"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# code-generator
|
|
33
|
+
|
|
34
|
+
A Python CLI that orchestrates Claude Code end-to-end to generate a whole project from a `requirements.md` file. Three commands — `init`, `generate`, `review` — plus `status`. Works for any project type: Python CLI, FastAPI, Angular, NestJS, full-stack, finance, BAML/LLM.
|
|
35
|
+
|
|
36
|
+
> **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](#safety-constraints) below.
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pipx install code-generator # recommended
|
|
42
|
+
# or
|
|
43
|
+
pip install code-generator # user-site
|
|
44
|
+
# or, from source
|
|
45
|
+
git clone git@github.com:SilvioBaratto/code-generator.git
|
|
46
|
+
cd code-generator && pip install -e ".[dev]"
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Authentication
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# Claude Code (Max subscription)
|
|
53
|
+
claude auth login
|
|
54
|
+
|
|
55
|
+
# GitHub (SSH protocol)
|
|
56
|
+
gh auth login -h github.com -p ssh
|
|
57
|
+
gh config set git_protocol ssh
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Commands
|
|
61
|
+
|
|
62
|
+
### `code-generator init [--template TYPE] [--force]`
|
|
63
|
+
|
|
64
|
+
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`.
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
code-generator init --template fastapi
|
|
68
|
+
$EDITOR .code-generator/requirements.md
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### `code-generator generate [flags]`
|
|
72
|
+
|
|
73
|
+
Read `.code-generator/requirements.md` and orchestrate Claude Code through the 0→7 phase pipeline:
|
|
74
|
+
|
|
75
|
+
| Phase | Action | Model |
|
|
76
|
+
|---|---|---|
|
|
77
|
+
| 0 | Complexity analysis (single vs multi-cycle) | Opus 4.6 |
|
|
78
|
+
| 1 | Planning — creates GitHub issues + milestone | Opus 4.6 |
|
|
79
|
+
| 2 | Per-issue review | Opus 4.6 |
|
|
80
|
+
| 3-4 | Implementation, fresh SDK session per issue (TDD) | Sonnet 4.6 |
|
|
81
|
+
| 5 | Closure + cross-module review | Opus 4.6 |
|
|
82
|
+
| 6 | Test suite, max 3 retries on failure | Sonnet 4.6 |
|
|
83
|
+
| 7 | Commit message + git add/commit/push | Haiku 4.5 |
|
|
84
|
+
|
|
85
|
+
Flags:
|
|
86
|
+
|
|
87
|
+
| Flag | Description | Default |
|
|
88
|
+
|---|---|---|
|
|
89
|
+
| `--dry-run` | Run only Phase 0 + Phase 1 (planning) | false |
|
|
90
|
+
| `--phase N` | Resume from phase N | — |
|
|
91
|
+
| `--continue` | Resume from the last completed phase (reads `state.json`) | false |
|
|
92
|
+
| `--mode auto\|single\|multi-cycle` | Force a mode (default `auto` runs Phase 0 first) | auto |
|
|
93
|
+
| `--cycle N` | Resume from cycle N (multi-cycle only) | — |
|
|
94
|
+
|
|
95
|
+
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.
|
|
96
|
+
|
|
97
|
+
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.
|
|
98
|
+
|
|
99
|
+
### `code-generator review [--create-issues] [--severity LEVEL]`
|
|
100
|
+
|
|
101
|
+
Run a standalone Opus 4.6 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.
|
|
102
|
+
|
|
103
|
+
### `code-generator status`
|
|
104
|
+
|
|
105
|
+
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), and the last error.
|
|
106
|
+
|
|
107
|
+
## Safety constraints
|
|
108
|
+
|
|
109
|
+
The tool enforces eight non-negotiables (see `CLAUDE.md` for the full list):
|
|
110
|
+
|
|
111
|
+
1. **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_VERTEX` from the environment. A startup check refuses to run if any are present.
|
|
112
|
+
2. **Never `--bare`.** The CLI flag `--bare` skips OAuth and forces API credits — it is **never** passed by this tool. If Anthropic ever makes `--bare` the default for `claude -p`, pin the CLI version or pass the opposite flag explicitly.
|
|
113
|
+
3. **YOLO mode always.** Every SDK call uses `permission_mode="bypassPermissions"`; the subprocess fallback uses `--dangerously-skip-permissions`.
|
|
114
|
+
4. **Overage protection.** On every `RateLimitEvent`, the tool checks `info.overage_status` and aborts immediately if it is anything other than `None` or `"disabled"`. Reference incident: [anthropics/claude-code#37686](https://github.com/anthropics/claude-code/issues/37686) — a user burned $1,800 in two days because billing overage was silently enabled.
|
|
115
|
+
5. **Wait-and-resume rate-limit handling.** Rate limits are not retried with exponential backoff — the tool sleeps until `resets_at + 60s` and resumes the same session. Backoff (10→20→40→80→120s) only applies to non-rate-limit transient errors.
|
|
116
|
+
6. **Fresh SDK session per issue.** The implementation phase never reuses conversational context across issues — each issue is a `/clear`-equivalent fresh session.
|
|
117
|
+
7. **Atomic state writes.** `.code-generator/state.json` is updated via `tmp → os.replace(tmp, STATE)` so a crash mid-write cannot corrupt it.
|
|
118
|
+
8. **Fixed model per phase.** Opus 4.6 for phases 0/1/2/5; Sonnet 4.6 for phases 3/4/6; Haiku 4.5 for phase 7's commit message.
|
|
119
|
+
|
|
120
|
+
## Troubleshooting
|
|
121
|
+
|
|
122
|
+
**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.
|
|
123
|
+
|
|
124
|
+
**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.
|
|
125
|
+
|
|
126
|
+
**`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.
|
|
127
|
+
|
|
128
|
+
**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.
|
|
129
|
+
|
|
130
|
+
## Project layout
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
src/code_generator/
|
|
134
|
+
├── cli.py # Typer entry point: init, generate, review, status
|
|
135
|
+
├── env.py # DANGEROUS_VARS, build_agent_env, assert_safe_environment
|
|
136
|
+
├── state.py # State dataclasses + atomic load/save
|
|
137
|
+
├── prompts/ # Packaged prompt-phase-*.md files + load_prompt
|
|
138
|
+
├── templates/ # Project templates for `init`
|
|
139
|
+
├── logging_setup.py # Per-phase log files under .code-generator/logs/
|
|
140
|
+
├── gh.py # Subprocess wrapper for issues, milestones, labels
|
|
141
|
+
├── agents.py # Tech-stack detector + agent selection matrix
|
|
142
|
+
├── runner/
|
|
143
|
+
│ ├── sdk_runner.py # claude-agent-sdk wrapper, RateLimitEvent handling
|
|
144
|
+
│ ├── subprocess_runner.py # CLI fallback, stream-json parser
|
|
145
|
+
│ ├── rate_limit.py # Wait-and-resume main loop
|
|
146
|
+
│ └── retry.py # Backoff + circuit breaker
|
|
147
|
+
├── orchestrator/
|
|
148
|
+
│ ├── phase0_complexity.py # single vs multi-cycle decision
|
|
149
|
+
│ ├── phase1_plan.py # milestone + issues
|
|
150
|
+
│ ├── phase2_review.py # per-issue review
|
|
151
|
+
│ ├── phase3_4_implement.py # TDD loop, fresh session per issue
|
|
152
|
+
│ ├── phase5_closure.py # closure + fix-issue feedback loop
|
|
153
|
+
│ ├── phase6_test.py # test runner, max 3 retries
|
|
154
|
+
│ ├── phase7_commit.py # Haiku commit message + push with rebase retry
|
|
155
|
+
│ └── cycle_loop.py # multi-cycle driver
|
|
156
|
+
└── commands/ # init, status, generate, review (Typer commands)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Development
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
git clone git@github.com:SilvioBaratto/code-generator.git
|
|
163
|
+
cd code-generator
|
|
164
|
+
python -m venv .venv && source .venv/bin/activate
|
|
165
|
+
pip install -e ".[dev]"
|
|
166
|
+
pytest -q
|
|
167
|
+
ruff check src tests
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Reference
|
|
171
|
+
|
|
172
|
+
The full specification lives in [`requirements.md`](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.
|
|
173
|
+
|
|
174
|
+
## License
|
|
175
|
+
|
|
176
|
+
MIT.
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
claude_code_generator-0.1.0.dist-info/licenses/LICENSE,sha256=Pmk91Ef-CmCxp3mvYU1DWeLRGKEC3HFitMjivm45BIY,1071
|
|
2
|
+
code_generator/__init__.py,sha256=_ZMXTePzmM8wjXWqBXJ1w9EezQ3zEOZhdbwAC1qiCfc,97
|
|
3
|
+
code_generator/agents.py,sha256=6D-BORzWkHYs2V4O0Z4RK8Hwsgkn5zqD-ZyWBKuOjX0,5251
|
|
4
|
+
code_generator/cli.py,sha256=JMU7wVpztnavkTkoGXrvEmMqOuEuwaxa-WH-wuWrANk,1244
|
|
5
|
+
code_generator/env.py,sha256=e-wsII0H7IB0rwJB4SlqmpfSG6asqBLA7rpjCU2fpBQ,1760
|
|
6
|
+
code_generator/gh.py,sha256=Iw3mIPNZ6l8gqLUMjwbAcR9bD_EKLz7im1ajpAniYsY,8951
|
|
7
|
+
code_generator/logging_setup.py,sha256=pu5c8I4BrFlSU80QMDVUVKf67q_UwGtQRe8hYI975fc,2295
|
|
8
|
+
code_generator/state.py,sha256=O_qd7eSMpd2J9KtkHobDC6VICCjyViSW5K32DGSwYHU,5220
|
|
9
|
+
code_generator/commands/__init__.py,sha256=UgM_pau4ln3VOxO6p3ElNrFF_kGxpNNYGlw04FHt1ho,64
|
|
10
|
+
code_generator/commands/generate.py,sha256=2TP6X94gmBNrZURzDwIftA6PoGq2PDfgYCyGgl9ax7c,7611
|
|
11
|
+
code_generator/commands/init.py,sha256=9faehMIm_5F4MytOcej0JjFzduVhz-oVc3bb1_-1_Nk,2110
|
|
12
|
+
code_generator/commands/review.py,sha256=U0c_xiMLHYgfVwiPTOGXgyvNDWj7m0y1xO5JImuI7UY,3434
|
|
13
|
+
code_generator/commands/status.py,sha256=T7-kf9EsrP9zOOGrR_9BqnE036J9px3mRabZ6LJxzr0,2566
|
|
14
|
+
code_generator/orchestrator/__init__.py,sha256=B_bjMB96SZPeNAJ07DSNY25c8UDMz_eqqsel-QtU_C4,129
|
|
15
|
+
code_generator/orchestrator/cycle_loop.py,sha256=LbM7mrRWAL2OWLe0WbaFa2c4tsAWs2uNaVONj9Tws7s,12971
|
|
16
|
+
code_generator/orchestrator/phase0_complexity.py,sha256=D0reZQMQJqGg1V7kNEA52TUZ497gcOMh0FCVAWYyd5o,4983
|
|
17
|
+
code_generator/orchestrator/phase1_plan.py,sha256=ZwqwlHf10Ay6wvAnwRTI6lqQAhkSF2biBoKVDLvGMWs,5433
|
|
18
|
+
code_generator/orchestrator/phase2_review.py,sha256=_OGWi11pzt9AHSvYk0uBjeWt52C3KRyZI0eUI3-S1Pw,3937
|
|
19
|
+
code_generator/orchestrator/phase3_4_implement.py,sha256=iLoOdq9bMbRe9st2BZnk6LESsyGJKTeYpcmB6vW9mC8,5523
|
|
20
|
+
code_generator/orchestrator/phase5_closure.py,sha256=Ak6RSVRop5b4D8NWqeBZ06y5DZRQHAOMYtax9kMC2fE,4841
|
|
21
|
+
code_generator/orchestrator/phase6_test.py,sha256=3leV1K3vGP9arfretKPZg4d-ApWIDR5s_TNMvR5f-1U,2924
|
|
22
|
+
code_generator/orchestrator/phase7_commit.py,sha256=HzZt40s-W9vbaolmpo7mAXWE624ei1tByM_7bnKNQ3k,5052
|
|
23
|
+
code_generator/prompts/__init__.py,sha256=uME1HtGcZQuGahcCRdoN2CmVBk7SIfS6U1PdIYJN_ZY,3118
|
|
24
|
+
code_generator/prompts/prompt-phase-0-complexity.md,sha256=ffZMcqJMeXPUjKVTfLVM_Pj_NF7ofEVf6fa9SWAJp2A,4290
|
|
25
|
+
code_generator/prompts/prompt-phase-1-planning.md,sha256=aRILIz162x10TXsk2Zk4-apbbJBgdkizibvI2iX41OE,11523
|
|
26
|
+
code_generator/prompts/prompt-phase-2-issue-review.md,sha256=xvn1VSzV19mgEZrZG5D2V-1HUfDv9ZTjFf_BOiQCqcE,3400
|
|
27
|
+
code_generator/prompts/prompt-phase-3-implementation.md,sha256=FEqH6b5k-jZblYt2ydAIdigoipsBxX63ExkgrxC_moE,10955
|
|
28
|
+
code_generator/prompts/prompt-phase-5-final-review.md,sha256=kU8Mb3YfiK5c07G5MEoHfNZu68C9697Uv5lqZZMAs7A,6047
|
|
29
|
+
code_generator/prompts/prompt-phase-6-test.md,sha256=8St1Z_b5A38oZkd2Zq8OZRmHZ_tFyW1AgCbRbd3ciC8,4799
|
|
30
|
+
code_generator/prompts/prompt-phase-7-commit.md,sha256=yx7d-DaJgoyYYcpf3gnUIvcXoZQBch-BMdyHY_zB9-c,3057
|
|
31
|
+
code_generator/prompts/prompt-review.md,sha256=KP3c2QpLNpv4RvIuMVJAL-YU-JZkJ9MvcY3C1HHCuLM,4441
|
|
32
|
+
code_generator/runner/__init__.py,sha256=kZ5vJ0DfHOVufBgni7_bxKfHOeu6npx7XGDTOpP1-Nc,662
|
|
33
|
+
code_generator/runner/rate_limit.py,sha256=7oKuRMEkRrjp-rXFxxn7Fj5hNqdv9tHkMPOHElDYCZ8,3882
|
|
34
|
+
code_generator/runner/retry.py,sha256=j4O9uRhm_DMsd1O0eyJyuWqOIc-_uFL0HyV1-_qkIZo,5621
|
|
35
|
+
code_generator/runner/sdk_runner.py,sha256=5pgmiENy_nee2VMivGnRlEBUUsSjndVJuTmXWfFw6NU,9353
|
|
36
|
+
code_generator/runner/subprocess_runner.py,sha256=E3LK_jLT50qwBVh5NDWubqN_neA13zphBTB2HNjYxJU,6571
|
|
37
|
+
code_generator/templates/__init__.py,sha256=HbGi1Gw9KI0QWKlYT-PGPVcQF4YfQzE35V07F7BIOlM,48
|
|
38
|
+
code_generator/templates/angular.md,sha256=ey8aQJSaWPKNhue-ZOIzZygpOw3udRVFTThxE21doG4,306
|
|
39
|
+
code_generator/templates/base.md,sha256=CsliWXVVHGg_HfK0Ls2F6zocYAsHQPt4uVPRPkzekF4,792
|
|
40
|
+
code_generator/templates/fastapi.md,sha256=N1loHS9IWGOmvMA2Op-EY1Ys4Igpt2sxsIei0YV3qa0,304
|
|
41
|
+
code_generator/templates/finance.md,sha256=sqfS0HQJB05sSsWACtj5JPDm2GGNxd3yEOw9G3y7faE,222
|
|
42
|
+
code_generator/templates/fullstack.md,sha256=ub6pfQU2Cz9x29BJExgxMKb_c-9ev4briEzI0fYON8g,610
|
|
43
|
+
code_generator/templates/nestjs.md,sha256=-ENYbwCOScFJ-9Tvl8R0QEfLDe9bj7YLgoW_HIHVKhc,182
|
|
44
|
+
code_generator/templates/python-cli.md,sha256=g6pcznCbc1f11LeKuEnGu74YHM-qCgtYlza9j5QuukU,200
|
|
45
|
+
claude_code_generator-0.1.0.dist-info/METADATA,sha256=1Dzr76VnIWs9C0tbnGQ8BTvexodWdFhI_GLidoDBTJ8,9673
|
|
46
|
+
claude_code_generator-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
|
|
47
|
+
claude_code_generator-0.1.0.dist-info/entry_points.txt,sha256=Tg2EXnr2LvXDTR5_9ArK5HUyUCzLIycIjNbx3I2lmw4,58
|
|
48
|
+
claude_code_generator-0.1.0.dist-info/top_level.txt,sha256=FYLzn8l0Cgl2tARhLjBAQNS3manGG-zM_rd_1v7C8HQ,15
|
|
49
|
+
claude_code_generator-0.1.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Silvio Baratto
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
code_generator
|
code_generator/agents.py
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"""Tech-stack detector and agent selection matrix (requirements.md §7).
|
|
2
|
+
|
|
3
|
+
Parses the ``## Tech Stack`` section of a requirements file and returns
|
|
4
|
+
an :class:`AgentSelection` dataclass describing which agents and skills
|
|
5
|
+
to activate for the project.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
from typing import TYPE_CHECKING
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class AgentSelection:
|
|
19
|
+
"""Immutable record of chosen agents and skills for a project.
|
|
20
|
+
|
|
21
|
+
Attributes:
|
|
22
|
+
primary: Tuple of primary agent names to assign as implementers.
|
|
23
|
+
support: Tuple of support/advisory agent names.
|
|
24
|
+
skills: Tuple of skill names to auto-load.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
primary: tuple[str, ...]
|
|
28
|
+
support: tuple[str, ...]
|
|
29
|
+
skills: tuple[str, ...]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# ---------------------------------------------------------------------------
|
|
33
|
+
# Fallback / defaults
|
|
34
|
+
# ---------------------------------------------------------------------------
|
|
35
|
+
|
|
36
|
+
_GENERIC_FALLBACK = AgentSelection(
|
|
37
|
+
primary=("python-pro",),
|
|
38
|
+
support=(),
|
|
39
|
+
skills=("solid-principles",),
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# ---------------------------------------------------------------------------
|
|
43
|
+
# Matrix definitions — ordered from most-specific to least-specific
|
|
44
|
+
# ---------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
_ANGULAR_FASTAPI = AgentSelection(
|
|
47
|
+
primary=("frontend-developer", "python-pro", "fastapi-expert-agent"),
|
|
48
|
+
support=("typescript-pro", "tailwind-patterns", "ui-ux-designer", "supabase-connection-expert"),
|
|
49
|
+
skills=("solid-principles", "python-expert"),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
_ANGULAR_NESTJS = AgentSelection(
|
|
53
|
+
primary=("frontend-developer", "nestjs-expert"),
|
|
54
|
+
support=("typescript-pro", "tailwind-patterns", "ui-ux-designer", "supabase-connection-expert"),
|
|
55
|
+
skills=("solid-principles",),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
_ANGULAR_ONLY = AgentSelection(
|
|
59
|
+
primary=("frontend-developer",),
|
|
60
|
+
support=("typescript-pro", "tailwind-patterns", "ui-ux-designer"),
|
|
61
|
+
skills=("solid-principles",),
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
_FASTAPI = AgentSelection(
|
|
65
|
+
primary=("python-pro", "fastapi-expert-agent"),
|
|
66
|
+
support=("supabase-connection-expert",),
|
|
67
|
+
skills=("solid-principles", "python-expert"),
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
_NESTJS = AgentSelection(
|
|
71
|
+
primary=("nestjs-expert",),
|
|
72
|
+
support=("supabase-connection-expert",),
|
|
73
|
+
skills=("solid-principles",),
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
_PORTFOLIO = AgentSelection(
|
|
77
|
+
primary=("riskfolio-expert", "python-pro"),
|
|
78
|
+
support=(),
|
|
79
|
+
skills=("skfolio", "yfinance"),
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
_BAML = AgentSelection(
|
|
83
|
+
primary=("baml-expert-agent", "python-pro"),
|
|
84
|
+
support=(),
|
|
85
|
+
skills=("solid-principles",),
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
_PYTHON_CLI = AgentSelection(
|
|
89
|
+
primary=("python-pro",),
|
|
90
|
+
support=(),
|
|
91
|
+
skills=("solid-principles", "python-expert"),
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# ---------------------------------------------------------------------------
|
|
96
|
+
# Public API
|
|
97
|
+
# ---------------------------------------------------------------------------
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def _extract_tech_stack_block(text: str) -> str:
|
|
101
|
+
"""Return the text between ``## Tech Stack`` and the next ``## `` heading.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
text: Full content of a requirements file.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
Lowercased content of the Tech Stack section, or an empty string
|
|
108
|
+
when the section is absent.
|
|
109
|
+
"""
|
|
110
|
+
marker = "## tech stack"
|
|
111
|
+
lower = text.lower()
|
|
112
|
+
start = lower.find(marker)
|
|
113
|
+
if start == -1:
|
|
114
|
+
return ""
|
|
115
|
+
|
|
116
|
+
block_start = start + len(marker)
|
|
117
|
+
# Find the next level-2 heading after the marker.
|
|
118
|
+
next_heading = lower.find("\n## ", block_start)
|
|
119
|
+
block = lower[block_start:] if next_heading == -1 else lower[block_start:next_heading]
|
|
120
|
+
|
|
121
|
+
return block
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def detect(requirements_path: Path) -> AgentSelection:
|
|
125
|
+
"""Parse a requirements file and return the matching AgentSelection.
|
|
126
|
+
|
|
127
|
+
Detection follows the §7 matrix in requirements.md. Full-stack
|
|
128
|
+
combos are checked before single-stack patterns. Falls back to the
|
|
129
|
+
generic ``python-pro`` + ``solid-principles`` selection when the file
|
|
130
|
+
is missing or no keyword matches.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
requirements_path: Path to a ``requirements.md`` file (need not exist).
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
The most-specific :class:`AgentSelection` that matches the stack,
|
|
137
|
+
or the generic fallback when no match is found.
|
|
138
|
+
"""
|
|
139
|
+
if not requirements_path.exists():
|
|
140
|
+
return _GENERIC_FALLBACK
|
|
141
|
+
|
|
142
|
+
text = requirements_path.read_text(encoding="utf-8")
|
|
143
|
+
block = _extract_tech_stack_block(text)
|
|
144
|
+
|
|
145
|
+
if not block:
|
|
146
|
+
return _GENERIC_FALLBACK
|
|
147
|
+
|
|
148
|
+
has_angular = "angular" in block or " ng " in block or " ng," in block
|
|
149
|
+
has_fastapi = "fastapi" in block or "python api" in block
|
|
150
|
+
has_nestjs = "nestjs" in block or "nest" in block
|
|
151
|
+
|
|
152
|
+
# Full-stack combos checked first (most specific).
|
|
153
|
+
if has_angular and has_fastapi:
|
|
154
|
+
return _ANGULAR_FASTAPI
|
|
155
|
+
|
|
156
|
+
if has_angular and has_nestjs:
|
|
157
|
+
return _ANGULAR_NESTJS
|
|
158
|
+
|
|
159
|
+
if has_angular:
|
|
160
|
+
return _ANGULAR_ONLY
|
|
161
|
+
|
|
162
|
+
if has_fastapi:
|
|
163
|
+
return _FASTAPI
|
|
164
|
+
|
|
165
|
+
if has_nestjs:
|
|
166
|
+
return _NESTJS
|
|
167
|
+
|
|
168
|
+
if "portfolio" in block or "riskfolio" in block or "skfolio" in block:
|
|
169
|
+
return _PORTFOLIO
|
|
170
|
+
|
|
171
|
+
if "baml" in block or "llm function" in block:
|
|
172
|
+
return _BAML
|
|
173
|
+
|
|
174
|
+
if "typer" in block or "click" in block or "python cli" in block:
|
|
175
|
+
return _PYTHON_CLI
|
|
176
|
+
|
|
177
|
+
return _GENERIC_FALLBACK
|
code_generator/cli.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"""Entry-point CLI for code-generator.
|
|
2
|
+
|
|
3
|
+
Exposes a Typer application with --version and subcommands:
|
|
4
|
+
init, status, generate, review.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import Annotated
|
|
8
|
+
|
|
9
|
+
import typer
|
|
10
|
+
|
|
11
|
+
import code_generator
|
|
12
|
+
from code_generator.commands.generate import generate_command
|
|
13
|
+
from code_generator.commands.init import init_command
|
|
14
|
+
from code_generator.commands.review import review_command
|
|
15
|
+
from code_generator.commands.status import status_command
|
|
16
|
+
|
|
17
|
+
app = typer.Typer(
|
|
18
|
+
name="code-generator",
|
|
19
|
+
help="Orchestrate Claude Code to generate whole projects from a requirements.md.",
|
|
20
|
+
no_args_is_help=True,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _version_callback(value: bool) -> None:
|
|
25
|
+
if value:
|
|
26
|
+
typer.echo(f"code-generator {code_generator.__version__}")
|
|
27
|
+
raise typer.Exit()
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@app.callback()
|
|
31
|
+
def root(
|
|
32
|
+
version: Annotated[
|
|
33
|
+
bool | None,
|
|
34
|
+
typer.Option(
|
|
35
|
+
"--version",
|
|
36
|
+
"-V",
|
|
37
|
+
help="Show version and exit.",
|
|
38
|
+
callback=_version_callback,
|
|
39
|
+
is_eager=True,
|
|
40
|
+
),
|
|
41
|
+
] = None,
|
|
42
|
+
) -> None:
|
|
43
|
+
"""code-generator CLI root."""
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
app.command(name="init")(init_command)
|
|
47
|
+
app.command(name="status")(status_command)
|
|
48
|
+
app.command(name="generate")(generate_command)
|
|
49
|
+
app.command(name="review")(review_command)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Typer command implementations, one module per subcommand."""
|