Skip to content

Commit e5c6853

Browse files
committed
docs(05): evolve PROJECT.md after phase completion
1 parent 935a161 commit e5c6853

1 file changed

Lines changed: 101 additions & 59 deletions

File tree

.planning/PROJECT.md

Lines changed: 101 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,87 +2,129 @@
22

33
## What This Is
44

5-
`spin` is a Go project scaffold CLI for the charmbracelet v2 ecosystem. It generates ready-to-run Go projects — TUI apps, CLI tools, or both — pre-wired with the right charmbracelet libraries, modern Go tooling (cobra, fang, gum), hot reload (air), and the prism test runner. One command produces a project that builds, tests, and runs without extra setup. Built with cobra + fang + gum so the tool itself demonstrates the charmbracelet experience.
5+
`spin` is a universal, language-agnostic scaffolder and task runner. One CLI for both jobs:
66

7-
## Core Value
7+
- **Scaffolder**`spin new <ecosystem> <name> [flags]` generates ready-to-run projects for any ecosystem (Go+charm, Rust, or anything with a template). `spin new <name> --template <user/repo>` pulls an external template (git repo) that declares its own params and post-hooks.
8+
- **Task runner**`spin run <task>` resolves tasks from `spin.config.toml`, `Taskfile.yml`, `Makefile`, `package.json`, `scripts/`, or a language-aware fallback. `--list` shows the merged list with sources; `--explain <task>` shows origin + raw command.
9+
- **Discovery**`spin search <query>`, `spin add <user/repo>`, `spin list` against a public registry of templates and ecosystems (server ships separately).
810

9-
Generate a perfect, runnable Go project using charmbracelet v2 libraries with a single command — `spin new myapp --tui --bubbletea` produces a project that `go run`s cleanly on first try.
11+
The first two ecosystems are **charm** (Go + charmbracelet v2) and **rust** (cargo). The first-class citizen is the ecosystem; the second-class citizen is the template; the third is the builder (deferred to v2.x). Built with cobra + fang + gum so the tool itself dogfoods the charm stack.
12+
13+
**Core Value:** One tool to scaffold any project and run its tasks, for any language — `spin new rust myapp --bin && spin run build && spin run test` works the same as `spin new charm myapp --tui --bubbletea && spin run build && spin run test`.
1014

1115
## Requirements
1216

1317
### Validated
1418

15-
<!-- Shipped and confirmed valuable. -->
16-
17-
(None yet — ship to validate)
19+
- [x] `spin new <name>` scaffolds a Go+charmbracelet v2 project in `./<name>`
20+
- [x] Top-level project-type flags: `--tui`, `--cli`, `--all`
21+
- [x] Per-library subflags for charmbracelet libs (`--bubbletea`, `--lipgloss`, `--huh`, `--glow`, `--glamour`, `--wish`, `--log`, `--crush`, `--modifiers`, `--ansi`, `--runewidth`)
22+
- [x] `--cobra` (default on) and `--fang` (default on) for CLI projects; `--viper` opt-in for config
23+
- [x] `--template <name>` selects a bundled template variant
24+
- [x] `--template-repo <url>` overrides the embedded template with an external git repo
25+
- [x] `--ai` (or `--agents`) generates an `AGENTS.md` describing the project for AI assistants
26+
- [x] `spin run` — runs the project (uses `air` for hot reload if `.air.toml` present)
27+
- [x] `spin build` — builds binary to `bin/`
28+
- [x] `spin test` — runs `prism` instead of bare `go test`
29+
- [x] `spin vet` — wraps `go vet` (whole module)
30+
- [x] `spin fmt` — wraps `gofumpt` (or `go fmt` if gofumpt unavailable) + `goimports`
31+
- [x] Interactive prompts (gum) when flags are missing, asking project type / libs / template / AI
32+
- [x] Generated project includes `.air.toml`, `Taskfile.yml` or `Makefile`, `go.mod` with pinned charm v2 deps
33+
- [x] Generated project ships a working example (bubbletea "hello" TUI or cobra/fang "hello" CLI)
34+
- [x] `spin doctor`, `spin lint`, `spin update` (post-scaffold health)
35+
- [x] CI dogfooding — spin rebuilds itself in CI
36+
- [x] v2.0 skeleton — ecosystems, templates, runner, registry, builder stub (compiled, all CLI surfaces working)
37+
- [x] **Phase 5 — v2.0 Universal Scaffolder & Task Runner** (validated 2026-06-09, 36/36 must-haves, all 5 success criteria)
38+
39+
Ecosystem model:
40+
- [x] `spin new <ecosystem> <name> [flags]` dispatches to a compiled-in ecosystem (charm, rust)
41+
- [x] `spin ecosystem {list,info}` — discover and inspect ecosystems
42+
- [x] `spin new --list-ecosystems` — quick ecosystem listing
43+
- [x] Charm migrated to the new flow; `spin new <name>` (no ecosystem) keeps working with a deprecation notice
44+
- [x] Rust ecosystem: `cargo new` (binary, lib, example), cargo-aware `spin run` fallbacks
45+
- [x] Each ecosystem declares its own flags and tasks; the runner merges them with the source chain
46+
47+
Template model:
48+
- [x] `spin new <name> --template <user/repo>` clones a template (shallow, `GIT_TERMINAL_PROMPT=0`)
49+
- [x] `spin.toml` declares metadata + params (text/textarea/number/select/multiselect/bool/path/secret) + post-hooks
50+
- [x] huh v2 form from params when TTY; defaults in non-TTY
51+
- [x] `spin.toml` is deleted after render; post-hooks run on success
52+
- [x] Templates are path-traversal-safe
53+
54+
Runner:
55+
- [x] `spin run <task>` resolves from `spin.config.toml` first
56+
- [x] Fallback chain: spin.config → Taskfile → Makefile → package.json → scripts/ → language default
57+
- [x] `--list` shows merged tasks with source labels
58+
- [x] `--explain <task>` shows origin + command
59+
- [x] Language fallbacks for go (build/test/run/vet/fmt) and rust (build/test/run/clippy/fmt)
60+
61+
Registry:
62+
- [x] `spin search <query>` against hosted registry; graceful "not deployed" message when server unreachable
63+
- [x] `spin add <user/repo>` pins to `~/.config/spin/pinned.json`
64+
- [x] `spin list` shows pinned entries with local paths
65+
- [x] `SPIN_REGISTRY_URL` env override
66+
67+
Backward compat:
68+
- [x] All v1.0 commands and flags still work
69+
- [x] `spin new <name>` defaults to charm with a one-time deprecation notice
70+
- [x] `spin build/test/vet/fmt/lint` print deprecation notice suggesting `spin run <task>` but still execute
1871

1972
### Active
2073

21-
<!-- Current scope. Building toward these. -->
22-
23-
- [ ] `spin new <name>` scaffolds a new Go project in `./<name>`
24-
- [ ] Top-level project-type flags: `--tui`, `--cli`, `--all`
25-
- [ ] Per-library subflags for charmbracelet libs (e.g. `--bubbletea`, `--lipgloss`, `--huh`, `--glow`, `--glamour`, `--wish`, `--log`, `--crush`, `--modifiers`, `--ansi`, `--runewidth`)
26-
- [ ] `--cobra` (default on) and `--fang` (default on) for CLI projects; `--viper` opt-in for config
27-
- [ ] `--template <name>` selects a bundled template variant
28-
- [ ] `--template-repo <url>` overrides the embedded template with an external git repo
29-
- [ ] `--ai` (or `--agents`) generates an `AGENTS.md` describing the project for AI assistants
30-
- [ ] `spin run` — runs the project (uses `air` for hot reload if `.air.toml` present)
31-
- [ ] `spin build` — builds binary to `bin/`
32-
- [ ] `spin test` — runs `prism` instead of bare `go test`
33-
- [ ] `spin vet` — wraps `go vet` (whole module)
34-
- [ ] `spin fmt` — wraps `gofumpt` (or `go fmt` if gofumpt unavailable) + `goimports`
35-
- [ ] Interactive prompts (gum) when flags are missing, asking project type / libs / template / AI
36-
- [ ] Generated project includes `.air.toml`, `Taskfile.yml` or `Makefile`, `go.mod` with pinned charm v2 deps
37-
- [ ] Generated project ships a working example (bubbletea "hello" TUI or cobra/fang "hello" CLI)
74+
*All v2.0 milestone requirements are now validated. The next milestone is v2.x, focused on the deferred items below.*
3875

3976
### Out of Scope
4077

41-
- Non-charmbracelet UI frameworks (tview, ratatui, urfave/cli) — `spin` is opinionated about charm — explicit user request
42-
- Non-Go languages (Rust/TS scaffolds) — wrong tool for the job
43-
- Online template registry / marketplace — local + override is enough for v1
44-
- Plugin system for custom scaffolders — defer to v2
45-
- Auto-updating generated projects after scaffold — out of scope, regenerate instead
46-
- CI/CD pipeline generation — out of scope, project authors configure their own
47-
- Dockerfile/compose generation — out of scope for v1
48-
- Remote execution / cloud scaffolds — local-only
49-
- GUI/TUI mode for the scaffolder itself (TUI for the generated project is fine; the scaffolder is a CLI)
78+
- Non-charm Go TUI frameworks (tview, ratatui) — `spin` is opinionated about charm (for the charm ecosystem)
79+
- `Builder` concept (question tree with custom renderers) — v2.x; skeleton ships the interface
80+
- Tauri/Next/Nuxt/Vue/React/Flutter/Dart/C#/Java ecosystems — v2.x
81+
- External ecosystem loading (Go plugins) — v2.x; v2.0 is compiled-in
82+
- `spin workspace` / `go.work` management — v2.x
83+
- GUI/TUI mode for the scaffolder itself (TUI is for the generated project, not the scaffolder)
84+
- `spin release` wrapping goreleaser — defer
85+
- Dockerfile/compose generation — out of scope
5086

5187
## Context
5288

53-
- charmbracelet published v2 of most libraries in 2024–2025; v1 paths/APIs differ and v2 must be used to get current style and stability
54-
- Charm ecosystem pieces: bubbletea (TUI framework), lipgloss (styling), huh (forms), bubbles (components), glamour (markdown), glow (markdown reader), wish (SSH), log (logging), crush (codec), modifiers, ansi, runewidth, cobra + fang (CLI framework + styled help), gum (interactivity), viper (config)
55-
- `gofumpt` is stricter than `gofmt` and is the de facto standard in modern Go projects
56-
- `prism` is a `go test` replacement that runs tests in parallel workers with better output
57-
- `air` is the de facto Go hot-reload tool; configured via `.air.toml`
58-
- `fang` is the styled, accessible help renderer for cobra — it gives cobra CLIs a polished feel
59-
- The scaffolder should be a showcase for the charm stack — running `spin --help` should feel like using a charm product
60-
- Target user: a Go developer who has heard of charmbracelet and wants a zero-friction on-ramp
89+
- The charmbracelet v2 ecosystem (bubbletea, lipgloss, huh, bubbles, glamour, wish, log, fang) uses `charm.land/<lib>/v2` import paths as of 2024–2025
90+
- `gum` is a binary (no Go library) — `spin` shells out to it for interactive prompts
91+
- `huh` v2 is the in-process form backend — used as the fallback when `gum` is not on `$PATH` and the in-process form for the runner's update/dep picker
92+
- The charm ecosystem is the first citizen; rust is the second; everything else is a template
93+
- The user wants a "global and universal language- and ecosystem-agnostic scaffolder and task runner" — competing with `npx create-*` (per-template scaffolders) and `cargo`/`make`/`task` (per-tool task runners), with one CLI to do both
94+
- Rust is a critical second ecosystem: it's the most-Go-like language, has a strong task model (`cargo run/build/test/clippy/fmt`), and proves the universal claim
95+
- The registry server is a separate project (`spin-registry`) — `spin` ships the client, not the server
96+
- The runner's source-precedence chain mirrors Task's and Just's: explicit project config wins; language defaults are the floor
97+
- Template params (text/number/select/multiselect/bool/path/secret) cover the 80% case; huh v2 supports all of them; for the 20% case, templates can do their own prompting in a post-hook
98+
- The v2.0 skeleton (built 2026-06-08) defines the package layout: `internal/params/`, `internal/ecosystem/`, `internal/ecosystems/{charm,rust,...}`, `internal/runner/`, `internal/runner/sources/`, `internal/template/`, `internal/registry/`, `internal/builder/`. This phase fills in the implementations.
6199

62100
## Constraints
63101

64-
- **Tech stack**: Go 1.22+ (use 1.23 if available); built with cobra + fang + gum; consumes charmbracelet v2 libs only — Why: user specified charm-only, modern Go
65-
- **Distribution**: single static binary; install via `go install github.com/<org>/spin@latest` — Why: standard Go CLI distribution, no runtime deps
66-
- **Templates**: embedded via `go:embed` (default) + `--template-repo` for external override — Why: works offline by default, flexible for advanced users
67-
- **Test runner**: `prism` (https://github.com/DaltonSW/prism), not `go test` directly — Why: user requested, better DX for parallel/colored output
68-
- **Formatter**: `gofumpt` (primary) with `goimports`; fall back to `gofmt` if gofumpt not installed — Why: stricter formatting is the modern Go default
69-
- **Hot reload**: `air` with a sensible `.air.toml` — Why: user requested, industry standard
70-
- **No CGO**: scaffolded projects should build with `CGO_ENABLED=0` — Why: cross-compile and minimal container sizes
71-
- **Charm v2 only**: do not import v1 paths or APIs — Why: v1 deprecated, v2 is current; researched via context7
102+
- **Tech stack**: Go 1.23+ (use 1.25 for scaffolded projects that need bubbles v2); cobra + fang + gum; charm v2 only for spin itself — Why: dogfooding, modern Go
103+
- **Distribution**: single static binary; `go install github.com/<org>/spin@latest` — Why: standard Go CLI
104+
- **No CGO**: spin itself builds with `CGO_ENABLED=0`; scaffolded Go projects also CGO=0 — Why: cross-compile, minimal containers
105+
- **Compiled-in ecosystems (v2.0)**: charm + rust are Go packages in `internal/ecosystems/` — Why: simpler ABI, no plugin contract to maintain
106+
- **External templates via git**: shallow clone, `GIT_TERMINAL_PROMPT=0` — Why: works without auth for public repos; depth-1 keeps it fast
107+
- **Graceful degradation**: registry server not deployed → friendly message, not a stack trace — Why: don't block users on the registry MVP
108+
- **Charm v2 only**: never import `github.com/charmbracelet/...` v1 paths in spin or in scaffolded projects — Why: v1 deprecated
72109

73110
## Key Decisions
74111

75112
| Decision | Rationale | Outcome |
76-
|----------|-----------|---------|
77-
| Binary name = `spin` | User-selected; short verb, evokes "spinning up" a project | — Pending |
78-
| Templates embedded + override | Offline default, flexibility for power users | — Pending |
79-
| Interactive gum prompts (default) | Friendly for new users; flag-only via `--no-interactive` | — Pending |
80-
| Scaffolder wraps `go run`/`prism`/`go vet`/`gofumpt` | One tool to learn; consistent commands across projects | — Pending |
81-
| Charm v2 only | v1 deprecated; user explicitly wants v2 | — Pending |
82-
| Cobra + fang + gum for the scaffolder itself | Dogfooding; showcase the charm stack | — Pending |
83-
| Viper as opt-in (`--viper`) | Not every CLI needs config; don't force it | — Pending |
84-
| `AGENTS.md` opt-in via `--ai` | Some users want AI-assistant context, some don't | — Pending |
85-
| Project root = working dir at scaffold time, project in subdir `name/` | Matches `cargo new`, `npm init` conventions | — Pending |
113+
|----------|-----------|--------|
114+
| Binary name = `spin` | User-selected; short verb, evokes "spinning up" a project | — Validated |
115+
| Templates embedded + override (`--template-repo`) | Offline default; flexibility for power users | — Validated v1 |
116+
| Three concepts: Ecosystem / Template / Builder | Ecosystem = compiled-in language; Template = external git; Builder = question tree | — Locked v2 |
117+
| Charm is the first ecosystem | Dogfoods the charm stack; mature v2 libs | — Locked v2 |
118+
| Rust is the second ecosystem | Proves universality; most-Go-like; strong task model | — Locked v2 |
119+
| `spin.config.toml` for project tasks | User-owned; overrides language defaults | — Locked v2 |
120+
| Runner source precedence: spin.config → Taskfile → Makefile → package.json → scripts/ → lang default | Explicit > auto-detected; per-project wins | — Locked v2 |
121+
| `spin.toml` for template params; deleted after use | Templates self-describe; project never carries scaffolder config | — Locked v2 |
122+
| 7 param types: text, textarea, number, select, multiselect, bool, path, secret | Covers 80% of template questions; huh v2 supports all of them | — Locked v2 |
123+
| Registry client + server are separate | Server is its own project; client degrades gracefully | — Locked v2 |
124+
| Builder concept is interface-only in v2.0 | Avoid premature design; ship the slot | — Deferred v2.x |
125+
| `spin new <name>` defaults to charm | Backward compat with v1; one-time deprecation notice | — Locked v2 |
126+
| Deprecation warnings on `spin build/test/vet/fmt/lint` | Backward compat for v1 users; suggest `spin run <task>` | — Locked v2 |
127+
| v1 Go+charm project tree is unchanged | The legacy v2.0 charm ecosystem wraps the existing `scaffold.Project` | — Locked v2 |
86128

87129
## Evolution
88130

@@ -102,4 +144,4 @@ This document evolves at phase transitions and milestone boundaries.
102144
4. Update Context with current state
103145

104146
---
105-
*Last updated: 2026-06-02 after initialization*
147+
*Last updated: 2026-06-09 after Phase 5 execution (v2.0 milestone complete)*

0 commit comments

Comments
 (0)