|
0cb4a5e…
|
anonymous
|
1 |
# Claude — Boilerworks CLI |
|
0cb4a5e…
|
anonymous
|
2 |
|
|
0cb4a5e…
|
anonymous
|
3 |
Primary conventions doc: read this file, then the source code. |
|
0cb4a5e…
|
anonymous
|
4 |
|
|
0cb4a5e…
|
anonymous
|
5 |
This repo is the **Boilerworks CLI** — a Python package published to PyPI as `boilerworks`. |
|
0cb4a5e…
|
anonymous
|
6 |
It is NOT a web application. It is a command-line tool built with Click, Questionary, and Rich. |
|
0cb4a5e…
|
anonymous
|
7 |
|
|
0cb4a5e…
|
anonymous
|
8 |
--- |
|
0cb4a5e…
|
anonymous
|
9 |
|
|
0cb4a5e…
|
anonymous
|
10 |
## Stack |
|
0cb4a5e…
|
anonymous
|
11 |
|
|
0cb4a5e…
|
anonymous
|
12 |
- **Language**: Python 3.12+ |
|
0cb4a5e…
|
anonymous
|
13 |
- **CLI framework**: Click 8+ |
|
0cb4a5e…
|
anonymous
|
14 |
- **Interactive prompts**: Questionary 2+ |
|
0cb4a5e…
|
anonymous
|
15 |
- **Output**: Rich 13+ (tables, panels, progress bars) |
|
0cb4a5e…
|
anonymous
|
16 |
- **Manifest validation**: Pydantic v2 |
|
0cb4a5e…
|
anonymous
|
17 |
- **Template rendering**: string replacement (not Jinja2) |
|
0cb4a5e…
|
anonymous
|
18 |
- **Git operations**: subprocess (git CLI) + GitPython |
|
0cb4a5e…
|
anonymous
|
19 |
- **Config**: PyYAML 6+ |
|
0cb4a5e…
|
anonymous
|
20 |
- **Package manager**: uv (not pip) |
|
0cb4a5e…
|
anonymous
|
21 |
- **Lint + format**: Ruff (not flake8/black/isort) |
|
0cb4a5e…
|
anonymous
|
22 |
- **Tests**: pytest with coverage |
|
0cb4a5e…
|
anonymous
|
23 |
|
|
0cb4a5e…
|
anonymous
|
24 |
## Package layout |
|
0cb4a5e…
|
anonymous
|
25 |
|
|
0cb4a5e…
|
anonymous
|
26 |
``` |
|
0cb4a5e…
|
anonymous
|
27 |
boilerworks/ # Python package |
|
0cb4a5e…
|
anonymous
|
28 |
__init__.py # __version__ = "0.1.0" |
|
0cb4a5e…
|
anonymous
|
29 |
cli.py # Click group: setup, init, bootstrap, list |
|
0cb4a5e…
|
anonymous
|
30 |
wizard.py # Questionary prompts → boilerworks.yaml |
|
0cb4a5e…
|
anonymous
|
31 |
generator.py # Clone → render → wire → git init |
|
0cb4a5e…
|
anonymous
|
32 |
bootstrap.py # Terraform stub (v2) |
|
0cb4a5e…
|
anonymous
|
33 |
manifest.py # Pydantic models for boilerworks.yaml |
|
0cb4a5e…
|
anonymous
|
34 |
registry.py # Load + query templates.yaml |
|
0cb4a5e…
|
anonymous
|
35 |
renderer.py # String replacement in cloned files |
|
0cb4a5e…
|
anonymous
|
36 |
console.py # Rich output helpers |
|
0cb4a5e…
|
anonymous
|
37 |
data/ |
|
0cb4a5e…
|
anonymous
|
38 |
templates.yaml # All 26 templates with metadata |
|
0cb4a5e…
|
anonymous
|
39 |
tests/ |
|
0cb4a5e…
|
anonymous
|
40 |
conftest.py |
|
0cb4a5e…
|
anonymous
|
41 |
test_cli.py |
|
0cb4a5e…
|
anonymous
|
42 |
test_manifest.py |
|
0cb4a5e…
|
anonymous
|
43 |
test_registry.py |
|
0cb4a5e…
|
anonymous
|
44 |
test_renderer.py |
|
0cb4a5e…
|
anonymous
|
45 |
test_generator.py |
|
0cb4a5e…
|
anonymous
|
46 |
test_console.py |
|
0cb4a5e…
|
anonymous
|
47 |
test_wizard.py |
|
0cb4a5e…
|
anonymous
|
48 |
``` |
|
0cb4a5e…
|
anonymous
|
49 |
|
|
0cb4a5e…
|
anonymous
|
50 |
## Running locally |
|
0cb4a5e…
|
anonymous
|
51 |
|
|
0cb4a5e…
|
anonymous
|
52 |
```bash |
|
0cb4a5e…
|
anonymous
|
53 |
uv sync # install deps |
|
0cb4a5e…
|
anonymous
|
54 |
uv run boilerworks --help # verify install |
|
0cb4a5e…
|
anonymous
|
55 |
make lint # ruff check + format --check |
|
0cb4a5e…
|
anonymous
|
56 |
make test # pytest with coverage |
|
0cb4a5e…
|
anonymous
|
57 |
make format # ruff fix + format |
|
0cb4a5e…
|
anonymous
|
58 |
``` |
|
0cb4a5e…
|
anonymous
|
59 |
|
|
0cb4a5e…
|
anonymous
|
60 |
## Adding a template |
|
0cb4a5e…
|
anonymous
|
61 |
|
|
0cb4a5e…
|
anonymous
|
62 |
Edit `data/templates.yaml`. Add an entry following the existing schema. |
|
0cb4a5e…
|
anonymous
|
63 |
Run `make test` — `test_registry.py` will catch count mismatches. |
|
0cb4a5e…
|
anonymous
|
64 |
|
|
0cb4a5e…
|
anonymous
|
65 |
## Coding standards |
|
0cb4a5e…
|
anonymous
|
66 |
|
|
0cb4a5e…
|
anonymous
|
67 |
- Fully typed: all function signatures have type hints |
|
0cb4a5e…
|
anonymous
|
68 |
- Line length: 120 (ruff config in pyproject.toml) |
|
0cb4a5e…
|
anonymous
|
69 |
- `ruff check . && ruff format .` after every change |
|
0cb4a5e…
|
anonymous
|
70 |
- pytest coverage ≥ 80% |
|
0cb4a5e…
|
anonymous
|
71 |
- No TODOs, no stubs (bootstrap is intentionally a v2 stub — document it clearly) |
|
0cb4a5e…
|
anonymous
|
72 |
- No co-authorship messages in commits |
|
0cb4a5e…
|
anonymous
|
73 |
|
|
0cb4a5e…
|
anonymous
|
74 |
## Common patterns |
|
0cb4a5e…
|
anonymous
|
75 |
|
|
0cb4a5e…
|
anonymous
|
76 |
**Adding a CLI option**: edit `boilerworks/cli.py`, add `@click.option(...)` decorator |
|
0cb4a5e…
|
anonymous
|
77 |
|
|
0cb4a5e…
|
anonymous
|
78 |
**Adding a manifest field**: edit `boilerworks/manifest.py` (BoilerworksManifest model) |
|
0cb4a5e…
|
anonymous
|
79 |
|
|
0cb4a5e…
|
anonymous
|
80 |
**Adding a renderer rule**: edit `boilerworks/renderer.py` (`build_replacements` or `_SKIP_*`) |
|
0cb4a5e…
|
anonymous
|
81 |
|
|
0cb4a5e…
|
anonymous
|
82 |
**Adding a template to the catalogue**: edit `data/templates.yaml` |