@skyf0xx/hedgehog 0.1.21 → 2.0.0

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.
Files changed (115) hide show
  1. package/README.md +92 -20
  2. package/bin/cli.mjs +107 -45
  3. package/package.json +2 -2
  4. package/src/agents/bootstrap.md +83 -50
  5. package/src/agents/front-end-eng.md +1 -1
  6. package/src/agents/landing-builder.md +96 -0
  7. package/src/agents/landing-critic.md +107 -0
  8. package/src/agents/landing-sequencer.md +112 -0
  9. package/src/agents/landing-strategist.md +217 -0
  10. package/src/agents/landing-systems.md +206 -0
  11. package/src/agents/planner.md +207 -143
  12. package/src/golden-cores/landing-page/.prettierignore +4 -0
  13. package/src/golden-cores/landing-page/.prettierrc.js +11 -0
  14. package/src/golden-cores/landing-page/.vscode/extensions.json +4 -0
  15. package/src/golden-cores/landing-page/.vscode/launch.json +11 -0
  16. package/src/golden-cores/landing-page/astro.config.mjs +11 -0
  17. package/src/golden-cores/landing-page/eslint.config.mjs +23 -0
  18. package/src/golden-cores/landing-page/gitignore.template +9 -0
  19. package/src/golden-cores/landing-page/package.json +40 -0
  20. package/src/golden-cores/landing-page/pnpm-lock.yaml +4587 -0
  21. package/src/golden-cores/landing-page/public/favicon.ico +0 -0
  22. package/src/golden-cores/landing-page/public/favicon.svg +9 -0
  23. package/src/golden-cores/landing-page/src/motifs/.gitkeep +0 -0
  24. package/src/golden-cores/landing-page/src/pages/index.astro +24 -0
  25. package/src/golden-cores/landing-page/src/sections/.gitkeep +0 -0
  26. package/src/golden-cores/landing-page/src/styles/global.css +18 -0
  27. package/src/golden-cores/landing-page/tsconfig.json +5 -0
  28. package/src/skills/hedgehog-bootstrap/SKILL.md +19 -19
  29. package/src/skills/{hedgehog-bootstrap-core → hedgehog-bootstrap-full-stack-app-core}/SKILL.md +19 -18
  30. package/src/skills/hedgehog-bootstrap-landing-page-core/SKILL.md +160 -0
  31. package/src/skills/hedgehog-landing-loop/SKILL.md +188 -0
  32. package/src/skills/hedgehog-planning-intake/SKILL.md +30 -17
  33. package/src/templates/CLAUDE.core.full-stack-app.md +131 -0
  34. package/src/templates/CLAUDE.core.landing-page.md +133 -0
  35. package/src/templates/CLAUDE.md +54 -183
  36. package/src/templates/TODO.core.full-stack-app.md +46 -0
  37. package/src/templates/TODO.core.landing-page.md +24 -0
  38. package/src/templates/TODO.md +6 -50
  39. /package/src/{golden-core → golden-cores/full-stack-app}/.env.example +0 -0
  40. /package/src/{golden-core → golden-cores/full-stack-app}/.github/workflows/phase-gate.yml +0 -0
  41. /package/src/{golden-core → golden-cores/full-stack-app}/.prettierignore +0 -0
  42. /package/src/{golden-core → golden-cores/full-stack-app}/.prettierrc +0 -0
  43. /package/src/{golden-core → golden-cores/full-stack-app}/.vscode/extensions.json +0 -0
  44. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api/eslint.config.mjs +0 -0
  45. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api/package.json +0 -0
  46. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api/src/app/app.module.ts +0 -0
  47. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api/src/app/health.controller.ts +0 -0
  48. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api/src/assets/.gitkeep +0 -0
  49. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api/src/main.ts +0 -0
  50. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api/tsconfig.app.json +0 -0
  51. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api/tsconfig.json +0 -0
  52. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api/webpack.config.cjs +0 -0
  53. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api-e2e/eslint.config.mjs +0 -0
  54. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api-e2e/package.json +0 -0
  55. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api-e2e/src/api/api.spec.ts +0 -0
  56. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api-e2e/src/support/global-setup.ts +0 -0
  57. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api-e2e/src/support/test-setup.ts +0 -0
  58. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api-e2e/tsconfig.json +0 -0
  59. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api-e2e/tsconfig.spec.json +0 -0
  60. /package/src/{golden-core → golden-cores/full-stack-app}/apps/api-e2e/vitest.config.mts +0 -0
  61. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/.prettierrc.js +0 -0
  62. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/.swcrc +0 -0
  63. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/components.json +0 -0
  64. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/eslint.config.mjs +0 -0
  65. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/index.d.ts +0 -0
  66. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/next-env.d.ts +0 -0
  67. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/next.config.js +0 -0
  68. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/package.json +0 -0
  69. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/postcss.config.mjs +0 -0
  70. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/public/.gitkeep +0 -0
  71. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/public/favicon.ico +0 -0
  72. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/src/app/global.css +0 -0
  73. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/src/app/layout.tsx +0 -0
  74. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/src/app/page.tsx +0 -0
  75. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/src/app/providers.tsx +0 -0
  76. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/src/components/theme-toggle.tsx +0 -0
  77. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/src/components/ui/button.tsx +0 -0
  78. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/src/lib/utils.ts +0 -0
  79. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web/tsconfig.json +0 -0
  80. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web-e2e/eslint.config.mjs +0 -0
  81. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web-e2e/package.json +0 -0
  82. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web-e2e/playwright.config.mts +0 -0
  83. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web-e2e/src/example.spec.ts +0 -0
  84. /package/src/{golden-core → golden-cores/full-stack-app}/apps/web-e2e/tsconfig.json +0 -0
  85. /package/src/{golden-core → golden-cores/full-stack-app}/commitlint.config.cjs +0 -0
  86. /package/src/{golden-core → golden-cores/full-stack-app}/docker-compose.yml +0 -0
  87. /package/src/{golden-core → golden-cores/full-stack-app}/eslint.config.mjs +0 -0
  88. /package/src/{golden-core → golden-cores/full-stack-app}/gitignore.template +0 -0
  89. /package/src/{golden-core → golden-cores/full-stack-app}/lefthook.yml +0 -0
  90. /package/src/{golden-core → golden-cores/full-stack-app}/nx.json +0 -0
  91. /package/src/{golden-core → golden-cores/full-stack-app}/package.json +0 -0
  92. /package/src/{golden-core → golden-cores/full-stack-app}/packages/config/eslint-base.js +0 -0
  93. /package/src/{golden-core → golden-cores/full-stack-app}/packages/config/package.json +0 -0
  94. /package/src/{golden-core → golden-cores/full-stack-app}/packages/config/prettier.js +0 -0
  95. /package/src/{golden-core → golden-cores/full-stack-app}/packages/config/src/env.schema.spec.ts +0 -0
  96. /package/src/{golden-core → golden-cores/full-stack-app}/packages/config/src/env.schema.ts +0 -0
  97. /package/src/{golden-core → golden-cores/full-stack-app}/packages/config/src/index.ts +0 -0
  98. /package/src/{golden-core → golden-cores/full-stack-app}/packages/config/tsconfig.json +0 -0
  99. /package/src/{golden-core → golden-cores/full-stack-app}/packages/config/tsconfig.lib.json +0 -0
  100. /package/src/{golden-core → golden-cores/full-stack-app}/packages/config/tsconfig.spec.json +0 -0
  101. /package/src/{golden-core → golden-cores/full-stack-app}/packages/config/vitest.config.mts +0 -0
  102. /package/src/{golden-core → golden-cores/full-stack-app}/packages/db/package.json +0 -0
  103. /package/src/{golden-core → golden-cores/full-stack-app}/packages/db/src/index.ts +0 -0
  104. /package/src/{golden-core → golden-cores/full-stack-app}/packages/db/src/lib/db.spec.ts +0 -0
  105. /package/src/{golden-core → golden-cores/full-stack-app}/packages/db/src/lib/db.ts +0 -0
  106. /package/src/{golden-core → golden-cores/full-stack-app}/packages/db/tsconfig.json +0 -0
  107. /package/src/{golden-core → golden-cores/full-stack-app}/packages/db/tsconfig.lib.json +0 -0
  108. /package/src/{golden-core → golden-cores/full-stack-app}/packages/db/tsconfig.spec.json +0 -0
  109. /package/src/{golden-core → golden-cores/full-stack-app}/packages/db/vitest.config.mts +0 -0
  110. /package/src/{golden-core → golden-cores/full-stack-app}/pnpm-lock.yaml +0 -0
  111. /package/src/{golden-core → golden-cores/full-stack-app}/pnpm-workspace.yaml +0 -0
  112. /package/src/{golden-core → golden-cores/full-stack-app}/tools/phase-gate.cjs +0 -0
  113. /package/src/{golden-core → golden-cores/full-stack-app}/tsconfig.base.json +0 -0
  114. /package/src/{golden-core → golden-cores/full-stack-app}/tsconfig.json +0 -0
  115. /package/src/{golden-core → golden-cores/full-stack-app}/vitest.workspace.ts +0 -0
package/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # The Antidote to AI Spaghetti Code ⭐
2
2
 
3
- [![GitHub stars](https://img.shields.io/github/stars/skyf0xx/hedgehog?style=social)](https://github.com/skyf0xx/hedgehog/stargazers)
3
+ [![Weekly downloads](https://img.shields.io/npm/dw/%40skyf0xx%2Fhedgehog?style=for-the-badge)](https://www.npmjs.com/package/@skyf0xx/hedgehog)
4
+
4
5
 
5
6
  AI writes code faster than humans ever could, but **speed without discipline creates chaos**.
6
7
 
@@ -10,8 +11,8 @@ AI writes code faster than humans ever could, but **speed without discipline cre
10
11
 
11
12
  Hedgehog pairs **BMAD's planning** with **disciplined execution**, in one workflow.
12
13
 
13
- - Plan: BMAD workflow
14
14
  - Build: Hedgehog execution discipline
15
+ - Plan: BMAD workflow
15
16
  - Ship: Quality gates and incremental loops
16
17
 
17
18
  ![Hedgehog - build software the right way, one step at a time](https://raw.githubusercontent.com/skyf0xx/hedgehog/master/docs/images/hero.png)
@@ -22,9 +23,18 @@ Hedgehog pairs **BMAD's planning** with **disciplined execution**, in one workfl
22
23
  2. An enforced build order
23
24
  3. Agents and skills that make good engineering the default
24
25
 
26
+ Hedgehog ships more than one **core** — a fixed stack, agent set, and
27
+ build order for one project shape. `full-stack-app` is the original: Nx,
28
+ NestJS, Drizzle, ts-rest, Next.js, backend-first (see **The Hedgehog
29
+ Loop**, below). A second core, `landing-page`, applies the same
30
+ discipline to a different shape — Astro, GSAP, a fixed pipeline for
31
+ turning a brief into a traceable, non-templated page instead of a
32
+ domain-module build order (see **The Chain Method**, below). Which core
33
+ applies is decided once, at planning intake, from what you describe.
34
+
25
35
  ## Hedgehog's secret to great outcomes
26
36
 
27
- - **Progressive layering:** types → schema → backend → UI, each layer built on a stable one beneath it
37
+ - **Progressive layering:** each core builds one stable layer at a time — types → schema → backend → UI on `full-stack-app`; brief feeling tokens sequence → artifact on `landing-page`
28
38
  - **Small context loops:** decompose work into atomic, verifiable changes
29
39
  - **Self-documenting architecture:** the codebase carries the context, not the AI
30
40
  - **Traceable evolution:** decisions are preserved through conventional commits
@@ -45,17 +55,17 @@ Hedgehog doesn't ask the AI to remember a plan. It makes the plan visible in the
45
55
 
46
56
  ### The AI should never wonder what to do next
47
57
 
48
- Instead of asking AI to hold an entire application in context, Hedgehog turns the build into a sequence of small, deterministic steps.
58
+ Instead of asking AI to hold an entire application in context, Hedgehog turns the build into a sequence of small, deterministic steps. The exact sequence depends on the project's core — a stateful app and a landing page don't share a build order, so they don't share an enforcement mechanism either. On the `full-stack-app` core:
49
59
 
50
60
  Each module is built progressively: schema → contract → repository → service → controller. Every step is gated by tests and committed before the next begins.
51
61
 
52
62
  Backend comes first. Every module gets a working, typed API before any screen is built. The frontend becomes a consumer of stable capabilities, not a parallel source of complexity.
53
63
 
54
- The build order is not something you negotiate with the AI. It is encoded into the process.
64
+ The build order is not something you negotiate with the AI. It is encoded into the process — the same is true on the `landing-page` core, just for a different sequence (see **The Chain Method**, below).
55
65
 
56
66
  ![Small steps, big leverage: small context loops, continuous verification, traceable evolution, sustainable velocity](https://raw.githubusercontent.com/skyf0xx/hedgehog/master/docs/images/small-steps.png)
57
67
 
58
- ## The Hedgehog Loop
68
+ ## The Hedgehog Loop (full-stack-app core)
59
69
 
60
70
  ``` text
61
71
  Planning intake - BMAD-METHOD's brief/PRD/UX spec, mined into scope
@@ -75,6 +85,36 @@ Repeat for the next module or the next step
75
85
 
76
86
  ![Why Hedgehog works: a different way to build with AI, comparing traditional AI workflow to Hedgehog](https://raw.githubusercontent.com/skyf0xx/hedgehog/master/docs/images/why.png)
77
87
 
88
+ ## The Chain Method (landing-page core)
89
+
90
+ A different shape gets a different loop, not a variant of this one —
91
+ there's no domain module to build, so the enforced order is a pipeline
92
+ instead of a layer sequence:
93
+
94
+ ``` text
95
+ Planning intake - BMAD-METHOD's brief/PR-FAQ/PRD/UX spec, mined into a
96
+ subject/audience/single-job statement (planner agent)
97
+
98
+ Bootstrap (once per project - Astro + Tailwind workspace)
99
+
100
+ Strategy - subject statement → adjective pairs → visceral/behavioral/
101
+ reflective sort → top/heart/base note timing (landing-strategist)
102
+
103
+ Systems - ingredient dials + copy voice (parallel) → token system →
104
+ signature motif (landing-systems)
105
+
106
+ Sequence - per-section transitions, weight, pacing (landing-sequencer)
107
+
108
+ Audit - traceability/distinctiveness + usability, reconciled to a pass
109
+ (landing-critic) - redlines route back to the phase that owns them
110
+
111
+ Build - the artifact, in Astro (landing-builder)
112
+ ```
113
+
114
+ Every choice traces back to a sentence in the subject statement, or it
115
+ gets cut — that traceability is what keeps the output from converging on
116
+ the same templated look every AI-generated page defaults to.
117
+
78
118
  ## Installation
79
119
 
80
120
  From an empty project folder:
@@ -83,16 +123,28 @@ From an empty project folder:
83
123
  npx @skyf0xx/hedgehog init
84
124
  ```
85
125
 
86
- Then open Claude Code and describe what you want to build. The
87
- `planner` agent runs planning intake first - BMAD-METHOD's brainstorming,
88
- brief, PRD, and UX spec - then mines that into what's in scope and which
89
- add-ons (Auth, Queue, Mobile) you need; once you confirm, it scaffolds
90
- the project itself.
126
+ This installs the `full-stack-app` core by default. For the landing-page
127
+ core instead:
91
128
 
92
- The core workspace - Nx, `packages/config`, `packages/db`, `apps/api`,
93
- `apps/web`, and every enforcement file - lands instantly from a
94
- pre-verified template rather than being generated live; bootstrap then
95
- only runs whichever add-ons planning intake determined your project needs.
129
+ ``` bash
130
+ npx @skyf0xx/hedgehog init --core=landing-page
131
+ ```
132
+
133
+ Then open Claude Code and describe what you want to build. The
134
+ `planner` agent decides which core actually applies (overriding the
135
+ installer's default if what you describe doesn't match it), then runs
136
+ that core's own planning intake — both cores run BMAD-METHOD's
137
+ brainstorming, brief, PR-FAQ, PRD, UX spec, and deep-recon in full;
138
+ `full-stack-app` mines that output into scope boundary and domain
139
+ vocabulary, `landing-page` mines it into a subject/audience/job
140
+ statement. Once you confirm, it scaffolds the project itself.
141
+
142
+ The chosen core's workspace - for `full-stack-app`: Nx, `packages/config`,
143
+ `packages/db`, `apps/api`, `apps/web`, and every enforcement file; for
144
+ `landing-page`: the Astro + Tailwind workspace and its animation library
145
+ set - lands instantly from a pre-verified template rather than being
146
+ generated live; bootstrap then verifies it (and, on `full-stack-app`,
147
+ runs whichever add-ons planning intake determined your project needs).
96
148
 
97
149
  Or paste the repo URL to your Agent and have it install for you.
98
150
 
@@ -104,7 +156,7 @@ npx @skyf0xx/hedgehog update
104
156
  ```
105
157
 
106
158
  This refreshes `.claude/agents/` and `.claude/skills/` only — it never
107
- touches `CLAUDE.md`, `TODO.md`, the golden-core workspace, or
159
+ touches `CLAUDE.md`, `TODO.md`, the core workspace, or
108
160
  `skills/BMAD`, since those carry project-specific or write-once content.
109
161
 
110
162
  ## For Builders
@@ -127,7 +179,9 @@ AI becomes the builder operating inside those constraints - turning ideas into s
127
179
 
128
180
  ## Architecture
129
181
 
130
- Hedgehog is a package of agents and skills, built on an opinionated stack so the build order above is mechanical and enforced by the tooling itself:
182
+ Hedgehog is a package of agents and skills, built on an opinionated stack per core so the build order above is mechanical and enforced by the tooling itself.
183
+
184
+ ### `full-stack-app` core
131
185
 
132
186
  | Layer | Choice | Why |
133
187
  | --- | --- | --- |
@@ -151,11 +205,29 @@ Hedgehog is a package of agents and skills, built on an opinionated stack so the
151
205
  | Commits | Conventional Commits | Architectural decisions become permanent history. |
152
206
  | Observability | Sentry | Failures map cleanly back to module boundaries. |
153
207
 
208
+ ### `landing-page` core
209
+
210
+ Every choice below maps to a specific dial or phase in the Chain
211
+ Method — nothing here is a default reached for out of habit:
212
+
213
+ | Layer | Choice | Why |
214
+ | --- | --- | --- |
215
+ | Framework | Astro | Zero-JS-by-default shell; islands only where interaction is actually needed. |
216
+ | Styling | Tailwind (v4, CSS-first) | Config as token layer only — no component library pre-deciding how things look. |
217
+ | Animation | GSAP + ScrollTrigger | Owns per-section pacing and top/heart/base fade timing with real control. |
218
+ | Scroll feel | Lenis | The "weight and suspension" dial, instead of default browser scroll physics. |
219
+ | Copy reveal | SplitType | Line/word/char splitting — makes copy rhythm visible in motion, not just static text. |
220
+ | Motif | SVG-first + Paper.js | Hand-authored graphics; Paper.js for a motif that evolves (augmentation/inversion) across sections. |
221
+ | Motif transforms | GSAP MorphSVGPlugin | Ships free inside the `gsap` package — for a motif that physically transforms across sections. |
222
+ | Texture | Custom SVG noise/grain filter | Cheap materiality layer nothing else in the stack owns. |
223
+ | Design handoff | Figma MCP / Stitch MCP | Input only, at the Strategist/Builder boundaries — never allowed to set spacing/style defaults directly. |
224
+ | 3D (rare) | React Three Fiber | Only when the subject is genuinely spatial; skipped by default. |
225
+
154
226
  ## How Hedgehog Compares
155
227
 
156
228
  Superpowers and BMAD both improve on raw prompting: one gives the AI good habits, the other a planning process. Alone, either can still be broken by convention.
157
229
 
158
- Hedgehog runs BMAD for planning, then enforces the build that follows with tooling, not convention: Nx boundaries, commit hooks, phase gates.
230
+ Hedgehog runs BMAD for planning on both cores — the same full shelf either way, mined differently per core's own shape — then enforces the build that follows with tooling, not convention Nx boundaries, commit hooks, and phase gates on `full-stack-app`; a redline-gated pipeline on `landing-page`.
159
231
 
160
232
  | | Superpowers | BMAD | Hedgehog + BMAD |
161
233
  | --- | --- | --- | --- |
@@ -163,7 +235,7 @@ Hedgehog runs BMAD for planning, then enforces the build that follows with tooli
163
235
  | **Order comes from** | Skill instructions the agent is told to follow | Sequenced documents (brief → PRD → architecture → stories) | Tooling (Nx, lefthook, phase gate) |
164
236
  | **Enforcement mechanism** | None. Prompted convention | None. One optional checklist between phases | Execution mechanically enforced |
165
237
  | **Unit of work** | A task, planned in worktree-isolated steps | A story, derived from PRD and architecture docs | A module layer (schema → contract → repo → service → controller → UI) |
166
- | **Stack** | Whatever the project already uses | No stack opinion | One locked stack (Nx, NestJS, Drizzle, ts-rest, Next.js) |
238
+ | **Stack** | Whatever the project already uses | No stack opinion | One locked stack per core (Nx/NestJS/Drizzle/ts-rest/Next.js for `full-stack-app`; Astro/Tailwind/GSAP for `landing-page`), chosen once at planning intake |
167
239
  | **Context per step** | As much as the task pulls in | A full brief, PRD, and architecture doc per story | One module layer at a time - BMAD's docs are mined once, up front |
168
240
  | **Finding a bug** | Search wherever the task touched | Search wherever the story touched | Search one layer, in one module, in a fixed order |
169
241
  | **Real cost** | No safety net if the model shortcuts its own process | Documentation overhead most solo projects don't need | Stack and order aren't negotiable |
@@ -183,4 +255,4 @@ The `nx-generate`, `nx-run-tasks`, `nx-workspace`, and
183
255
 
184
256
  If Hedgehog helps you build better AI software, consider giving it a ⭐ on GitHub.
185
257
 
186
- [![GitHub stars](https://img.shields.io/github/stars/skyf0xx/hedgehog?style=social)](https://github.com/skyf0xx/hedgehog/stargazers)
258
+ [![GitHub stars](https://img.shields.io/github/stars/skyf0xx/hedgehog?style=social)](https://github.com/skyf0xx/hedgehog/stargazers)
package/bin/cli.mjs CHANGED
@@ -3,12 +3,13 @@
3
3
  // into the current repo, so the discipline travels with the project.
4
4
  //
5
5
  // Usage:
6
- // npx @skyf0xx/hedgehog init scaffold into the current directory
7
- // npx @skyf0xx/hedgehog init --force overwrite files that already exist
8
- // npx @skyf0xx/hedgehog update refresh .claude/agents + .claude/skills
6
+ // npx @skyf0xx/hedgehog init scaffold, full-stack-app core (default)
7
+ // npx @skyf0xx/hedgehog init --core=landing-page scaffold with a named core instead
8
+ // npx @skyf0xx/hedgehog init --force overwrite files that already exist
9
+ // npx @skyf0xx/hedgehog update refresh .claude/agents + .claude/skills
9
10
  // npx @skyf0xx/hedgehog --help
10
11
 
11
- import { cp, mkdir, access, readdir, stat, rm } from 'node:fs/promises';
12
+ import { cp, mkdir, access, readdir, stat, rm, readFile, writeFile } from 'node:fs/promises';
12
13
  import { constants } from 'node:fs';
13
14
  import { fileURLToPath } from 'node:url';
14
15
  import { dirname, join, relative, resolve } from 'node:path';
@@ -16,6 +17,8 @@ import { dirname, join, relative, resolve } from 'node:path';
16
17
  const __dirname = dirname(fileURLToPath(import.meta.url));
17
18
  const PKG_ROOT = resolve(__dirname, '..');
18
19
  const DEST_ROOT = process.cwd();
20
+ const CORES_ROOT = join(PKG_ROOT, 'src/golden-cores');
21
+ const DEFAULT_CORE = 'full-stack-app';
19
22
 
20
23
  // ── tiny ANSI helpers (no deps) ─────────────────────────────────────────
21
24
  const useColor = process.stdout.isTTY && !process.env.NO_COLOR;
@@ -31,35 +34,61 @@ const dim = (s) => paint('2', s);
31
34
  // this name in the package, renamed back on copy.
32
35
  const DOTFILE_RENAMES = { 'gitignore.template': '.gitignore' };
33
36
 
37
+ // Every subdirectory of src/golden-cores/ is a valid --core value —
38
+ // discovered from disk so a new core added under golden-cores/ doesn't
39
+ // need this list touched separately.
40
+ async function availableCores() {
41
+ return (await readdir(CORES_ROOT, { withFileTypes: true }))
42
+ .filter((e) => e.isDirectory())
43
+ .map((e) => e.name)
44
+ .sort();
45
+ }
46
+
34
47
  // ── the payload: what gets copied, and to where under the target repo ───
35
48
  // `dir` entries copy a whole tree; `file` entries copy a single file and
36
- // may rename (templates lose their src/templates/ prefix at the root).
37
- const PLAN = [
38
- { type: 'dir', from: 'src/agents', to: '.claude/agents' },
39
- { type: 'dir', from: 'src/skills', to: '.claude/skills' },
40
- // The vendored BMAD-METHOD planning shelf that hedgehog-planning-intake
41
- // runs referenced by repo-root-relative path (skills/BMAD/...), so it
42
- // lands there rather than under .claude/.
43
- { type: 'dir', from: 'skills/BMAD', to: 'skills/BMAD' },
44
- { type: 'file', from: 'src/templates/CLAUDE.md', to: 'CLAUDE.md' },
45
- { type: 'file', from: 'src/templates/TODO.md', to: 'TODO.md' },
46
- // The pre-built, pre-verified core Nx workspace — packages/config,
47
- // packages/db, apps/api, apps/web, and every enforcement file
48
- // (lefthook, commitlint, phase gate, module boundaries). Lands the
49
- // root package.json too, so there's no separate placeholder for it.
50
- // `hedgehog-bootstrap-core` verifies this on first run rather than
51
- // generating it live — see that skill for what's in here and why.
52
- { type: 'dir', from: 'src/golden-core', to: '.' },
53
- ];
49
+ // may rename (templates lose their src/templates/ prefix at the root);
50
+ // `merge` entries concatenate a shared shell with a core-specific include
51
+ // at {{CORE_SECTION}} (see CLAUDE.md template plumbing below).
52
+ // Agents and skills for every core install regardless of which one is
53
+ // chosen planner needs the full toolset to run core selection at all,
54
+ // and a project can only switch cores before it's bootstrapped anyway.
55
+ function plan(core) {
56
+ return [
57
+ { type: 'dir', from: 'src/agents', to: '.claude/agents' },
58
+ { type: 'dir', from: 'src/skills', to: '.claude/skills' },
59
+ // The vendored BMAD-METHOD planning shelf that hedgehog-planning-intake
60
+ // runs referenced by repo-root-relative path (skills/BMAD/...), so it
61
+ // lands there rather than under .claude/.
62
+ { type: 'dir', from: 'skills/BMAD', to: 'skills/BMAD' },
63
+ {
64
+ type: 'merge',
65
+ shell: 'src/templates/CLAUDE.md',
66
+ include: `src/templates/CLAUDE.core.${core}.md`,
67
+ to: 'CLAUDE.md',
68
+ },
69
+ {
70
+ type: 'merge',
71
+ shell: 'src/templates/TODO.md',
72
+ include: `src/templates/TODO.core.${core}.md`,
73
+ to: 'TODO.md',
74
+ },
75
+ // The pre-built, pre-verified workspace for the chosen core —
76
+ // everything a fresh project of that shape needs at repo root
77
+ // (lands the root package.json too, so there's no separate
78
+ // placeholder for it). The relevant bootstrap-core skill verifies
79
+ // this on first run rather than generating it live.
80
+ { type: 'dir', from: `src/golden-cores/${core}`, to: '.' },
81
+ ];
82
+ }
54
83
 
55
- // The subset of PLAN that's the discipline's payload rather than
84
+ // The subset of plan() that's the discipline's payload rather than
56
85
  // project-specific or write-once content: `update` re-copies exactly
57
86
  // this, always overwriting, since a consuming project's own
58
87
  // .claude/agents and .claude/skills are supposed to match upstream
59
- // verbatim. CLAUDE.md/TODO.md carry project-filled content, golden-core
60
- // is verified once by hedgehog-bootstrap-core, and skills/BMAD is
61
- // re-vendored only deliberately (bmad-revendor) — none of those belong
62
- // in an update.
88
+ // verbatim. CLAUDE.md/TODO.md carry project-filled content, the core
89
+ // workspace is verified once by its bootstrap-core skill, and
90
+ // skills/BMAD is re-vendored only deliberately (bmad-revendor) — none
91
+ // of those belong in an update.
63
92
  const UPDATE_PLAN = [
64
93
  { type: 'dir', from: 'src/agents', to: '.claude/agents' },
65
94
  { type: 'dir', from: 'src/skills', to: '.claude/skills' },
@@ -71,8 +100,25 @@ const exists = (p) =>
71
100
  () => false,
72
101
  );
73
102
 
103
+ // Writes one planned file to disk — a straight copy, or for a `merge`
104
+ // entry, the shell template with {{CORE_SECTION}} replaced by the
105
+ // chosen core's include.
106
+ async function writePlannedFile(f) {
107
+ await mkdir(dirname(f.dest), { recursive: true });
108
+ if (f.merge) {
109
+ const shell = await readFile(join(PKG_ROOT, f.merge.shell), 'utf8');
110
+ const section = await readFile(join(PKG_ROOT, f.merge.include), 'utf8');
111
+ await writeFile(f.dest, shell.replaceAll('{{CORE_SECTION}}', section.trimEnd()));
112
+ return;
113
+ }
114
+ await cp(f.src, f.dest);
115
+ }
116
+
74
117
  // Every destination file this plan would write, resolved absolute.
75
118
  async function plannedFiles(entry) {
119
+ if (entry.type === 'merge') {
120
+ return [{ dest: join(DEST_ROOT, entry.to), merge: entry }];
121
+ }
76
122
  const src = join(PKG_ROOT, entry.from);
77
123
  if (entry.type === 'file') {
78
124
  return [{ src, dest: join(DEST_ROOT, entry.to) }];
@@ -92,7 +138,8 @@ async function plannedFiles(entry) {
92
138
  return out;
93
139
  }
94
140
 
95
- function help() {
141
+ async function help() {
142
+ const cores = await availableCores();
96
143
  console.log(`
97
144
  ${bold('Hedgehog installer')}
98
145
 
@@ -101,28 +148,40 @@ CLAUDE.md / TODO.md templates into the repo root, so the discipline is
101
148
  committed alongside your code.
102
149
 
103
150
  ${bold('Usage')}
104
- npx @skyf0xx/hedgehog init scaffold into the current directory
105
- npx @skyf0xx/hedgehog init --force overwrite existing files
106
- npx @skyf0xx/hedgehog update refresh .claude/agents + .claude/skills
151
+ npx @skyf0xx/hedgehog init scaffold, ${DEFAULT_CORE} core (default)
152
+ npx @skyf0xx/hedgehog init --core=<name> scaffold with a named core instead
153
+ npx @skyf0xx/hedgehog init --force overwrite existing files
154
+ npx @skyf0xx/hedgehog update refresh .claude/agents + .claude/skills
107
155
  npx @skyf0xx/hedgehog --help
108
156
 
109
- After it runs, commit the .claude/ payload, open Claude Code, and say
110
- "bootstrap this project" to trigger the hedgehog-bootstrap skill.
157
+ Available cores: ${cores.join(', ')}
158
+
159
+ After it runs, commit the payload, open Claude Code, and say
160
+ "bootstrap this project" to trigger the matching bootstrap-core skill.
111
161
 
112
162
  ${bold('update')} re-copies only .claude/agents and .claude/skills from the
113
163
  installed Hedgehog version, so an already-bootstrapped project can pick up
114
164
  agent/skill changes from a newer release. It always overwrites those two
115
- directories and never touches CLAUDE.md, TODO.md, golden-core, or
165
+ directories and never touches CLAUDE.md, TODO.md, the core workspace, or
116
166
  skills/BMAD — those are project-specific or updated deliberately, not by
117
167
  this command.
118
168
  `);
119
169
  }
120
170
 
121
- async function init({ force }) {
171
+ async function init({ force, core }) {
172
+ const cores = await availableCores();
173
+ if (!cores.includes(core)) {
174
+ console.error(
175
+ `${red('Unknown core:')} ${core}\n\nAvailable cores: ${cores.join(', ')}\n`,
176
+ );
177
+ process.exitCode = 1;
178
+ return;
179
+ }
180
+
122
181
  // Resolve the full list of writes up front so we can detect conflicts
123
182
  // before touching anything.
124
183
  const groups = [];
125
- for (const entry of PLAN) {
184
+ for (const entry of plan(core)) {
126
185
  const files = await plannedFiles(entry);
127
186
  groups.push({ entry, files });
128
187
  }
@@ -151,8 +210,7 @@ async function init({ force }) {
151
210
  for (const { files } of groups) {
152
211
  for (const f of files) {
153
212
  const already = await exists(f.dest);
154
- await mkdir(dirname(f.dest), { recursive: true });
155
- await cp(f.src, f.dest);
213
+ await writePlannedFile(f);
156
214
  if (already) overwritten++;
157
215
  else written++;
158
216
  const label = already ? yellow('overwrite') : green('create');
@@ -169,11 +227,13 @@ async function init({ force }) {
169
227
  console.log(` 1. ${bold('git add -A && git commit -m "chore: install Hedgehog"')}`);
170
228
  console.log(` 2. ${bold('pnpm install')}`);
171
229
  console.log(` 3. Open Claude Code and say: ${bold('"bootstrap this project"')}\n`);
230
+ console.log(dim(`Core: ${bold(core)} — already scaffolded and verified.`));
172
231
  console.log(
173
232
  dim(
174
- 'The core workspace (Nx, packages/config, packages/db, apps/api,\n' +
175
- 'apps/web) is already scaffolded and verified — bootstrap now only\n' +
176
- 'runs whichever add-ons (Auth, Queue, Mobile) Intake calls for.',
233
+ core === DEFAULT_CORE
234
+ ? '(Nx, packages/config, packages/db, apps/api, apps/web) — bootstrap\n' +
235
+ 'now only runs whichever add-ons (Auth, Queue, Mobile) Intake calls for.'
236
+ : 'bootstrap now only runs whichever add-on steps this core defines, if any.',
177
237
  ),
178
238
  );
179
239
  }
@@ -205,7 +265,7 @@ async function update() {
205
265
  console.log(` 2. ${bold('git add -A && git commit -m "chore: update hedgehog"')}\n`);
206
266
  console.log(
207
267
  dim(
208
- 'CLAUDE.md, TODO.md, the golden-core workspace, and skills/BMAD are\n' +
268
+ 'CLAUDE.md, TODO.md, the core workspace, and skills/BMAD are\n' +
209
269
  'untouched — those carry project-specific or write-once content.',
210
270
  ),
211
271
  );
@@ -214,14 +274,16 @@ async function update() {
214
274
  async function main() {
215
275
  const args = process.argv.slice(2);
216
276
  if (args.includes('--help') || args.includes('-h') || args.length === 0) {
217
- help();
277
+ await help();
218
278
  return;
219
279
  }
220
280
  const cmd = args[0];
221
281
  const force = args.includes('--force') || args.includes('-f');
282
+ const coreArg = args.find((a) => a.startsWith('--core='));
283
+ const core = coreArg ? coreArg.slice('--core='.length) : DEFAULT_CORE;
222
284
 
223
285
  if (cmd === 'init') {
224
- await init({ force });
286
+ await init({ force, core });
225
287
  return;
226
288
  }
227
289
 
@@ -231,7 +293,7 @@ async function main() {
231
293
  }
232
294
 
233
295
  console.error(`${red('Unknown command:')} ${cmd}\n`);
234
- help();
296
+ await help();
235
297
  process.exitCode = 1;
236
298
  }
237
299
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyf0xx/hedgehog",
3
- "version": "0.1.21",
3
+ "version": "2.0.0",
4
4
  "description": "Install the Hedgehog build discipline (agents + skills) into a repo.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -21,7 +21,7 @@
21
21
  "src/agents",
22
22
  "src/skills",
23
23
  "src/templates",
24
- "src/golden-core",
24
+ "src/golden-cores",
25
25
  "skills/BMAD"
26
26
  ],
27
27
  "engines": {