@rashidee/co2 1.2.5
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.
- package/dist/index.js +25449 -0
- package/drizzle/0000_remarkable_charles_xavier.sql +210 -0
- package/drizzle/0001_wise_wolf_cub.sql +13 -0
- package/drizzle/0002_secret_spyke.sql +16 -0
- package/drizzle/0003_workspace_config_singleton.sql +16 -0
- package/drizzle/0004_terminal_claim_v120.sql +11 -0
- package/drizzle/0005_brainstorm_v124.sql +10 -0
- package/drizzle/0006_project_v140.sql +6 -0
- package/drizzle/0007_prd_wizard_v124.sql +14 -0
- package/drizzle/0008_workflow_artifact_v126.sql +24 -0
- package/drizzle/0009_project_import_v150.sql +7 -0
- package/drizzle/0010_quality_v151.sql +3 -0
- package/drizzle/meta/0000_snapshot.json +1335 -0
- package/drizzle/meta/0001_snapshot.json +1416 -0
- package/drizzle/meta/0002_snapshot.json +1510 -0
- package/drizzle/meta/_journal.json +83 -0
- package/package.json +41 -0
- package/plugin/.claude-plugin/marketplace.json +36 -0
- package/plugin/.claude-plugin/plugin.json +22 -0
- package/plugin/README.md +625 -0
- package/plugin/SKILLS.md +350 -0
- package/plugin/co2.svg +5 -0
- package/plugin/commands/brainstorm-loop.md +129 -0
- package/plugin/skills/conductor-defect/SKILL.md +898 -0
- package/plugin/skills/conductor-feature-develop/SKILL.md +1383 -0
- package/plugin/skills/conductor-feature-develop/references/implementation-domain-template.md +131 -0
- package/plugin/skills/conductor-feature-develop/references/implementation-master-template.md +89 -0
- package/plugin/skills/conductor-feature-develop/references/playwright-setup.md +224 -0
- package/plugin/skills/conductor-feature-prepare/SKILL.md +604 -0
- package/plugin/skills/depgen-k8s/SKILL.md +468 -0
- package/plugin/skills/depgen-k8s/references/dockerfile-laravel.md +197 -0
- package/plugin/skills/depgen-k8s/references/dockerfile-nodejs.md +163 -0
- package/plugin/skills/depgen-k8s/references/dockerfile-spring-boot.md +174 -0
- package/plugin/skills/depgen-k8s/references/k8s-patterns.md +869 -0
- package/plugin/skills/mockgen-shadcn/SKILL.md +1067 -0
- package/plugin/skills/mockgen-shadcn/references/admin-layout-template.md +1467 -0
- package/plugin/skills/mockgen-shadcn/references/mockup-hub-template.md +498 -0
- package/plugin/skills/mockgen-shadcn/references/mockup-index-template.md +216 -0
- package/plugin/skills/mockgen-tailwind/SKILL.md +904 -0
- package/plugin/skills/mockgen-tailwind/references/admin-layout-template.md +720 -0
- package/plugin/skills/mockgen-tailwind/references/mockup-hub-template.md +498 -0
- package/plugin/skills/mockgen-tailwind/references/mockup-index-template.md +190 -0
- package/plugin/skills/modelgen-nosql/SKILL.md +617 -0
- package/plugin/skills/modelgen-nosql/references/model-extraction-methodology.md +497 -0
- package/plugin/skills/modelgen-nosql/references/nosql-design-guide.md +258 -0
- package/plugin/skills/modelgen-relational/SKILL.md +707 -0
- package/plugin/skills/modelgen-relational/references/model-extraction-methodology.md +499 -0
- package/plugin/skills/specgen-flutter-riverpod/SKILL.md +898 -0
- package/plugin/skills/specgen-flutter-riverpod/references/component-patterns.md +971 -0
- package/plugin/skills/specgen-flutter-riverpod/references/notification-patterns.md +457 -0
- package/plugin/skills/specgen-flutter-riverpod/references/routing-patterns.md +362 -0
- package/plugin/skills/specgen-flutter-riverpod/references/security-patterns.md +709 -0
- package/plugin/skills/specgen-flutter-riverpod/references/spec-template.md +1566 -0
- package/plugin/skills/specgen-flutter-riverpod/references/state-patterns.md +518 -0
- package/plugin/skills/specgen-flutter-riverpod/references/storage-patterns.md +370 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/SKILL.md +984 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/batch-patterns.md +359 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/messaging-patterns.md +468 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/modulith-patterns.md +461 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/reporting-patterns.md +803 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/security-patterns.md +501 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/spec-template.md +1268 -0
- package/plugin/skills/specgen-laravel-eloquent-bladehtmx/references/web-patterns.md +301 -0
- package/plugin/skills/specgen-node-cli-web/SKILL.md +561 -0
- package/plugin/skills/specgen-node-cli-web/references/auth-patterns.md +293 -0
- package/plugin/skills/specgen-node-cli-web/references/cli-packaging-patterns.md +250 -0
- package/plugin/skills/specgen-node-cli-web/references/server-patterns.md +247 -0
- package/plugin/skills/specgen-node-cli-web/references/spec-template.md +401 -0
- package/plugin/skills/specgen-node-cli-web/references/testing-patterns.md +174 -0
- package/plugin/skills/specgen-react-mui/SKILL.md +789 -0
- package/plugin/skills/specgen-react-mui/references/component-patterns.md +1077 -0
- package/plugin/skills/specgen-react-mui/references/reporting-patterns.md +1998 -0
- package/plugin/skills/specgen-react-mui/references/routing-patterns.md +461 -0
- package/plugin/skills/specgen-react-mui/references/security-patterns.md +599 -0
- package/plugin/skills/specgen-react-mui/references/spec-template.md +1030 -0
- package/plugin/skills/specgen-react-mui/references/state-patterns.md +327 -0
- package/plugin/skills/specgen-react-tailwind/SKILL.md +859 -0
- package/plugin/skills/specgen-react-tailwind/references/component-patterns.md +1212 -0
- package/plugin/skills/specgen-react-tailwind/references/reporting-patterns.md +1529 -0
- package/plugin/skills/specgen-react-tailwind/references/routing-patterns.md +669 -0
- package/plugin/skills/specgen-react-tailwind/references/security-patterns.md +656 -0
- package/plugin/skills/specgen-react-tailwind/references/spec-template.md +1237 -0
- package/plugin/skills/specgen-react-tailwind/references/state-patterns.md +327 -0
- package/plugin/skills/specgen-sdk-java/SKILL.md +933 -0
- package/plugin/skills/specgen-sdk-java/references/api-extraction-patterns.md +247 -0
- package/plugin/skills/specgen-sdk-java/references/http-client-patterns.md +495 -0
- package/plugin/skills/specgen-sdk-java/references/packaging-patterns.md +366 -0
- package/plugin/skills/specgen-sdk-java/references/spec-template.md +956 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/SKILL.md +1284 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/batch-patterns.md +1224 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/jasper-patterns.md +1638 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/messaging-patterns.md +512 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/modulith-patterns.md +354 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/security-patterns.md +551 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/spec-template.md +2502 -0
- package/plugin/skills/specgen-spring-jpa-jtehtmx/references/web-patterns.md +503 -0
- package/plugin/skills/specgen-spring-jpa-restapi/SKILL.md +990 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/batch-patterns.md +1224 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/messaging-patterns.md +512 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/modulith-patterns.md +279 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/reporting-patterns.md +1536 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/restapi-patterns.md +722 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/security-patterns.md +351 -0
- package/plugin/skills/specgen-spring-jpa-restapi/references/spec-template.md +553 -0
- package/plugin/skills/specgen-ts-cli/SKILL.md +861 -0
- package/plugin/skills/specgen-ts-cli/references/async-patterns.md +1101 -0
- package/plugin/skills/specgen-ts-cli/references/command-patterns.md +383 -0
- package/plugin/skills/specgen-ts-cli/references/config-patterns.md +430 -0
- package/plugin/skills/specgen-ts-cli/references/database-patterns.md +750 -0
- package/plugin/skills/specgen-ts-cli/references/packaging-patterns.md +426 -0
- package/plugin/skills/specgen-ts-cli/references/spec-template.md +1391 -0
- package/plugin/skills/specgen-ts-cli/references/testing-patterns.md +909 -0
- package/plugin/skills/testgen-functional/SKILL.md +1381 -0
- package/plugin/skills/tracegen-matrix/SKILL.md +243 -0
- package/plugin/skills/util-preparek8senv/SKILL.md +422 -0
- package/plugin/skills/util-projectinit/SKILL.md +307 -0
- package/plugin/skills/util-projectinit/reference/brainstorm-loop.md +129 -0
- package/plugin/skills/util-projectinit/reference/brainstorm-protocol.md +144 -0
- package/plugin/skills/util-projectinit/reference/brainstorm-setup-guide.md +153 -0
- package/plugin/skills/util-projectinit/reference/brainstorm-template-appdev.md +87 -0
- package/plugin/skills/util-projectinit/reference/co2-context-generation-guide.md +761 -0
- package/plugin/skills/util-projectsync/SKILL.md +501 -0
- package/plugin/skills/util-updprd/SKILL.md +324 -0
- package/plugin/skills/util-usanalyzer/SKILL.md +307 -0
- package/plugin/skills/util-ustagger/SKILL.md +154 -0
- package/static/assets/abnfDiagram-VRR7QNED-DvPuwyCV.js +1 -0
- package/static/assets/arc-DRKw7sjs.js +1 -0
- package/static/assets/architectureDiagram-ZJ3FMSHR-CaNcxUbC.js +36 -0
- package/static/assets/blockDiagram-677ZJIJ3-Demd4AOK.js +132 -0
- package/static/assets/c4Diagram-LMCZKHZV-PVKUfc2x.js +10 -0
- package/static/assets/channel-C2nVbuwv.js +1 -0
- package/static/assets/chunk-2Q5K7J3B-CExf8ww_.js +1 -0
- package/static/assets/chunk-32BRIVSS-CFPaoONF.js +1 -0
- package/static/assets/chunk-5VM5RSS4-DE2esM67.js +15 -0
- package/static/assets/chunk-EX3LRPZG-SON_YdDG.js +231 -0
- package/static/assets/chunk-JWPE2WC7-Qxah8LNr.js +1 -0
- package/static/assets/chunk-MOJQB5TN-BcWGQV3j.js +88 -0
- package/static/assets/chunk-RYQCIY6F-DkDj-OR5.js +1 -0
- package/static/assets/chunk-V7JOEXUC-BlI1Mrah.js +206 -0
- package/static/assets/chunk-VR4S4FIN-Agf__duj.js +1 -0
- package/static/assets/chunk-XXDRQBXY-B5CfAh85.js +1 -0
- package/static/assets/classDiagram-OUVF2IWQ-DXJIljsR.js +1 -0
- package/static/assets/classDiagram-v2-EOCWNBFH-DXJIljsR.js +1 -0
- package/static/assets/cose-bilkent-JH36ORCC-DO0cQkcy.js +1 -0
- package/static/assets/cynefin-VYW2F7L2-CfOnsnXc.js +178 -0
- package/static/assets/cynefinDiagram-TSTJHNR4-BJ8tULAv.js +62 -0
- package/static/assets/cytoscape.esm-DTSO7Bv0.js +331 -0
- package/static/assets/dagre-VKFMJZFB-DfjwzHqP.js +4 -0
- package/static/assets/defaultLocale-DX6XiGOO.js +1 -0
- package/static/assets/diagram-FQU43EPY-CndSOIIM.js +3 -0
- package/static/assets/diagram-G47NLZAW-Czf5hN0Z.js +24 -0
- package/static/assets/diagram-NH7WQ7WH-COAyojGh.js +24 -0
- package/static/assets/diagram-OA4YK3LP-H8PoiN2m.js +30 -0
- package/static/assets/diagram-WEI45ONY-DzcaVzjp.js +41 -0
- package/static/assets/ebnfDiagram-CCIWWBDH-DPazGYLJ.js +1 -0
- package/static/assets/erDiagram-Q63AITRT-Bo-fubgF.js +85 -0
- package/static/assets/flowDiagram-23GEKE2U-CSvxUDwh.js +156 -0
- package/static/assets/ganttDiagram-NO4QXBWP-DnBveWX6.js +292 -0
- package/static/assets/gitGraphDiagram-IHSO6WYX-B3rVL8c-.js +106 -0
- package/static/assets/graph-C9eacEi8.js +1 -0
- package/static/assets/index-LZSQkLE2.css +41 -0
- package/static/assets/index-y7XDSgMG.js +495 -0
- package/static/assets/infoDiagram-FWYZ7A6U-CvWV9yy2.js +2 -0
- package/static/assets/init-Gi6I4Gst.js +1 -0
- package/static/assets/ishikawaDiagram-FXEZZL3T-DF28a1N6.js +70 -0
- package/static/assets/journeyDiagram-5HDEW3XC-CB6CugYk.js +139 -0
- package/static/assets/kanban-definition-HUTT4EX6-ResSLF6d.js +89 -0
- package/static/assets/katex-C5jXJg4s.js +257 -0
- package/static/assets/layout-DEXfKzaS.js +1 -0
- package/static/assets/linear-CLO--ryk.js +1 -0
- package/static/assets/map-Czzmt4hB.js +1 -0
- package/static/assets/mindmap-definition-LN4V7U3C-BvW3EbxX.js +96 -0
- package/static/assets/ordinal-Cboi1Yqb.js +1 -0
- package/static/assets/pegDiagram-2B236MQR-BHCgqrrM.js +1 -0
- package/static/assets/pieDiagram-ENE6RG2P-DVmCQ5FA.js +39 -0
- package/static/assets/quadrantDiagram-ABIIQ3AL-B3e5KR52.js +7 -0
- package/static/assets/railroadDiagram-RFXS5EU6-Csv5ysLc.js +1 -0
- package/static/assets/requirementDiagram-TGXJPOKE-DOMVzvnB.js +84 -0
- package/static/assets/sankeyDiagram-HTMAVEWB-B1dcTOvy.js +40 -0
- package/static/assets/sequenceDiagram-DBY2YBRQ-BY414yeO.js +162 -0
- package/static/assets/sizeCapture-X5ZJPWSS-CuJfrfBN.js +1 -0
- package/static/assets/stateDiagram-2N3HPSRC-FX4rJkzV.js +1 -0
- package/static/assets/stateDiagram-v2-6OUMAXLB-BVufbO_H.js +1 -0
- package/static/assets/swimlanes-5IMT3BWC-Sfy58mmv.js +2 -0
- package/static/assets/swimlanesDiagram-G3AALYLV-wDCDw08H.js +8 -0
- package/static/assets/timeline-definition-FHXFAJF6-CmV7by8p.js +120 -0
- package/static/assets/vennDiagram-L72KCM5P-FqIyFZFt.js +34 -0
- package/static/assets/wardleyDiagram-EHGQE667-BZ06O45i.js +78 -0
- package/static/assets/xychartDiagram-FW5EYKEG-BOkffR06.js +7 -0
- package/static/index.html +24 -0
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: specgen-node-cli-web
|
|
3
|
+
model: claude-opus-4-8
|
|
4
|
+
effort: high
|
|
5
|
+
description: >
|
|
6
|
+
Generate a detailed specification document for building a self-hosted Node.js web
|
|
7
|
+
application distributed as a global npm CLI — installed via `npm install -g <app-name>`,
|
|
8
|
+
started via `<app-name> start`, and accessed at `http://IP:PORT`. Single-process,
|
|
9
|
+
local-first architecture: one Node 22 process serves both the REST API (Hono 4) and an
|
|
10
|
+
embedded pre-built React 19 + Vite 6 SPA styled with Tailwind CSS v4 and vendored
|
|
11
|
+
shadcn/ui. Data lives in per-user SQLite (better-sqlite3 + Drizzle ORM with shipped
|
|
12
|
+
migrations, auto-migrated on start). Authentication is hand-rolled scrypt sessions with
|
|
13
|
+
a first-run auto-generated admin, forced password change, and admin-managed users — no
|
|
14
|
+
OAuth, no JWT, no email flows. CLI parsing via commander 12, bundling via tsup 8,
|
|
15
|
+
monorepo via pnpm workspaces, Biome lint/format, Vitest + Playwright tests, mandatory
|
|
16
|
+
built-binary smoke test. Standardized input: application name (mandatory), version
|
|
17
|
+
(mandatory), module (optional).
|
|
18
|
+
Use this skill whenever the user asks to create a spec, specification, blueprint, or
|
|
19
|
+
technical design document for a self-hosted web app installed as a global CLI, a
|
|
20
|
+
"local-first web tool", an "npm-installable web dashboard", a "CLI that serves a web
|
|
21
|
+
UI", or a single-binary-style Node web application with an embedded frontend. Also
|
|
22
|
+
trigger when the user says things like "spec out a self-hosted Node web app",
|
|
23
|
+
"design an npm global CLI with a web interface", "write a spec for a local web tool
|
|
24
|
+
installed with npm -g", or any request describing a web application that end users
|
|
25
|
+
install on their own machine and open at an IP:PORT. Even if the user only mentions a
|
|
26
|
+
subset (e.g., "Hono + SQLite app started from the terminal" or "CLI-launched
|
|
27
|
+
dashboard"), this skill likely applies — ask and confirm.
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
# Self-Hosted Node.js CLI Web Application Specification Generator
|
|
31
|
+
|
|
32
|
+
This skill generates a comprehensive specification document (Markdown) that serves as a
|
|
33
|
+
blueprint for building a lightweight Node.js web application that is **installed via
|
|
34
|
+
`npm install -g <app-name>`**, started via **`<app-name> start`**, and accessed at
|
|
35
|
+
**`http://IP:PORT`**. The spec is intended to be followed by a developer or coding agent
|
|
36
|
+
to produce a fully functional, publishable package.
|
|
37
|
+
|
|
38
|
+
The specification does NOT generate code. It produces a detailed, opinionated technical
|
|
39
|
+
document describing every layer of the application — from the pnpm workspace layout to
|
|
40
|
+
the publish pipeline to the forced-password-change middleware — so that implementation
|
|
41
|
+
becomes a mechanical exercise.
|
|
42
|
+
|
|
43
|
+
**Architecture model (non-negotiable):** Single-process, local-first. One Node process
|
|
44
|
+
serves both the REST API and the embedded pre-built web UI. All state lives on the user's
|
|
45
|
+
machine. There is no hosted backend. The web app is compiled to static assets at publish
|
|
46
|
+
time; end users never run a build.
|
|
47
|
+
|
|
48
|
+
## Technology Stack
|
|
49
|
+
|
|
50
|
+
### Core Stack (Always Included)
|
|
51
|
+
|
|
52
|
+
These are the fixed versions the spec targets. Do not deviate unless the user explicitly
|
|
53
|
+
requests different versions.
|
|
54
|
+
|
|
55
|
+
| Layer | Technology | Version Constraint |
|
|
56
|
+
|---|---|---|
|
|
57
|
+
| Runtime | Node.js | 22 LTS (`engines.node: ">=22"`) |
|
|
58
|
+
| Package manager (dev) | pnpm workspaces | `>=9` |
|
|
59
|
+
| Language | TypeScript | `^5.6`, strict mode mandatory |
|
|
60
|
+
| CLI framework | commander | `^12` |
|
|
61
|
+
| Web framework | Hono (`@hono/node-server`) | `^4` |
|
|
62
|
+
| Frontend | React + Vite (built SPA, embedded) | React `^19`, Vite `^6` |
|
|
63
|
+
| Styling | Tailwind CSS | `^4` |
|
|
64
|
+
| Components | shadcn/ui (vendored) | latest |
|
|
65
|
+
| Validation | Zod | `^3` |
|
|
66
|
+
| ORM | Drizzle ORM + drizzle-kit | `^0.36` / `^0.28` |
|
|
67
|
+
| Database | SQLite via better-sqlite3 | `^11` |
|
|
68
|
+
| Auth | Hand-rolled sessions — `node:crypto` only | n/a |
|
|
69
|
+
| CLI/package build | tsup | `^8` |
|
|
70
|
+
| Lint + format | Biome | `^1.9` |
|
|
71
|
+
| Tests | Vitest + Playwright | `^2` / `^1.48` |
|
|
72
|
+
| Terminal output | picocolors | `^1` |
|
|
73
|
+
|
|
74
|
+
> **Why Hono:** framework-agnostic single-process embedding, ~14 kB core, first-class
|
|
75
|
+
> TypeScript inference, and `serve-static` for shipping the built SPA from inside the
|
|
76
|
+
> installed package.
|
|
77
|
+
|
|
78
|
+
### Explicitly Excluded
|
|
79
|
+
|
|
80
|
+
The generated spec must NOT include any of the following — where the coding agent's
|
|
81
|
+
general habits conflict with this list, this list wins:
|
|
82
|
+
|
|
83
|
+
- **Next.js** — cannot be packaged as a global binary
|
|
84
|
+
- **Express** — Hono supersedes it
|
|
85
|
+
- **Better Auth or any auth framework** — no self-serve signup exists in this model
|
|
86
|
+
- **Any database server** (PostgreSQL, MySQL, MongoDB, Redis, ...)
|
|
87
|
+
- **Docker** — distribution is npm; daemonization is the OS's job
|
|
88
|
+
- **Email flows, self-serve registration, OAuth/social login, JWTs** — see auth rules
|
|
89
|
+
- **CORS middleware** — the UI is same-origin by construction
|
|
90
|
+
|
|
91
|
+
### Optional Integration Versions
|
|
92
|
+
|
|
93
|
+
Include in the version table only when the corresponding integration is selected
|
|
94
|
+
(see Determining Optional Components).
|
|
95
|
+
|
|
96
|
+
| Component | Version | When Selected |
|
|
97
|
+
|---|---|---|
|
|
98
|
+
| @tanstack/react-table | 8.x | DataGrid = yes |
|
|
99
|
+
| recharts | 2.x | Charts = yes |
|
|
100
|
+
| react-day-picker + date-fns | 9.x / 4.x | DatePickers = yes |
|
|
101
|
+
| @tiptap/react + @tiptap/starter-kit | 2.x | RichText = yes |
|
|
102
|
+
| env-paths | 3.x | Optional helper for the data directory (may resolve manually instead) |
|
|
103
|
+
|
|
104
|
+
New runtime dependencies beyond these require explicit human approval — the published
|
|
105
|
+
tarball SHOULD stay under 5 MB excluding `better-sqlite3`.
|
|
106
|
+
|
|
107
|
+
## Monorepo Structure (development)
|
|
108
|
+
|
|
109
|
+
The spec targets this fixed pnpm workspace layout. Package responsibilities are strict:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
project-root/
|
|
113
|
+
├── pnpm-workspace.yaml
|
|
114
|
+
├── CLAUDE.md
|
|
115
|
+
├── biome.json
|
|
116
|
+
├── packages/
|
|
117
|
+
│ ├── core/ # shared: Zod schemas, types, constants
|
|
118
|
+
│ │ └── src/
|
|
119
|
+
│ │ ├── schemas/ # one file per domain (user.ts, session.ts, ...)
|
|
120
|
+
│ │ └── index.ts
|
|
121
|
+
│ ├── server/ # Hono app + Drizzle + auth
|
|
122
|
+
│ │ ├── drizzle/ # generated SQL migrations (committed, shipped)
|
|
123
|
+
│ │ ├── src/
|
|
124
|
+
│ │ │ ├── app.ts # Hono app factory (routes + middleware)
|
|
125
|
+
│ │ │ ├── db/
|
|
126
|
+
│ │ │ │ ├── schema.ts
|
|
127
|
+
│ │ │ │ ├── index.ts # connection factory (takes data dir path)
|
|
128
|
+
│ │ │ │ └── bootstrap.ts # first-run: migrate + create default admin
|
|
129
|
+
│ │ │ ├── auth/ # sessions, password hashing, middleware
|
|
130
|
+
│ │ │ ├── features/<name>/ # routes.ts, service.ts, schema.ts, __tests__/
|
|
131
|
+
│ │ │ └── lib/ # logger, env/config
|
|
132
|
+
│ │ └── vitest.config.ts
|
|
133
|
+
│ ├── web/ # React SPA (Vite)
|
|
134
|
+
│ │ ├── src/
|
|
135
|
+
│ │ │ ├── routes/ # login, force-change-password, users, settings, <modules>
|
|
136
|
+
│ │ │ ├── components/ui/ # shadcn vendored
|
|
137
|
+
│ │ │ └── lib/api.ts # typed fetch client (hono/client RPC)
|
|
138
|
+
│ │ └── vite.config.ts
|
|
139
|
+
│ └── cli/ # THE published package
|
|
140
|
+
│ ├── package.json # name: <app-name>, bin, files: ["dist","static","drizzle"]
|
|
141
|
+
│ ├── src/
|
|
142
|
+
│ │ ├── index.ts # #!/usr/bin/env node — commander program
|
|
143
|
+
│ │ └── commands/ # start.ts, status.ts, reset-admin.ts, <extra commands>
|
|
144
|
+
│ └── tsup.config.ts
|
|
145
|
+
└── e2e/ # Playwright against a started instance
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
**Publish pipeline (the critical mechanic):** `packages/cli` is the only published
|
|
149
|
+
artifact. Its build step (1) tsup-bundles the CLI + server into `dist/` with
|
|
150
|
+
`better-sqlite3` marked external — it is a native module and must remain a real
|
|
151
|
+
dependency, (2) runs `vite build` in `packages/web` and copies the output to
|
|
152
|
+
`cli/static/`, (3) copies `server/drizzle/` migrations into the package. The published
|
|
153
|
+
package is therefore self-contained: bundle + static UI + migrations.
|
|
154
|
+
|
|
155
|
+
Structural rules: feature-folder colocation, no barrel files, <300 lines/file, Zod at
|
|
156
|
+
every boundary, `any` forbidden, types via `z.infer<>`.
|
|
157
|
+
|
|
158
|
+
## When the Skill Triggers
|
|
159
|
+
|
|
160
|
+
Generate the spec when the user provides an **application name** and **version** that
|
|
161
|
+
corresponds to one of the custom applications defined in `CLAUDE.md`. The skill reads all
|
|
162
|
+
required inputs from the project's context files — no interactive Q&A is needed for the
|
|
163
|
+
core inputs.
|
|
164
|
+
|
|
165
|
+
The user invokes this skill by specifying the target application and version, for example:
|
|
166
|
+
- `/specgen-node-cli-web my_tool v1.0.0`
|
|
167
|
+
- `/specgen-node-cli-web my_tool v1.0.0 module:Inventory`
|
|
168
|
+
- `/specgen-node-cli-web "My Tool" v1.0.0`
|
|
169
|
+
|
|
170
|
+
The skill then locates the matching context folder and reads all input files automatically.
|
|
171
|
+
|
|
172
|
+
## Version Gate
|
|
173
|
+
|
|
174
|
+
Before starting any work, resolve the application folder first (see Input Resolution below), then check `CHANGELOG.md` in the application folder (`<app_folder>/CHANGELOG.md`):
|
|
175
|
+
|
|
176
|
+
1. If `<app_folder>/CHANGELOG.md` does not exist, skip this check (first-ever execution for this application).
|
|
177
|
+
2. If `<app_folder>/CHANGELOG.md` exists, scan all `## vX.Y.Z` headings and determine the **highest version** using semantic versioning comparison.
|
|
178
|
+
3. Compare the requested version against the highest version:
|
|
179
|
+
- If requested version **>=** highest version: proceed normally.
|
|
180
|
+
- If requested version **<** highest version: **STOP immediately**. Print: `"Version {requested} is lower than the current application version {highest} recorded in <app_folder>/CHANGELOG.md. Execution rejected."` Do NOT proceed with any work.
|
|
181
|
+
|
|
182
|
+
## Input Resolution
|
|
183
|
+
|
|
184
|
+
This skill uses standardized input resolution. Provide:
|
|
185
|
+
|
|
186
|
+
| Argument | Required | Example | Description |
|
|
187
|
+
|----------|----------|---------|-------------|
|
|
188
|
+
| `<application>` | Yes | `my_tool` | Application name to locate the context folder |
|
|
189
|
+
| `<version>` | Yes | `v1.0.0` | Version to scope processing |
|
|
190
|
+
| `module:<name>` | No | `module:Inventory` | Limit generation to a single module |
|
|
191
|
+
|
|
192
|
+
### Application Folder Resolution
|
|
193
|
+
|
|
194
|
+
The application name is matched against root-level application folders:
|
|
195
|
+
1. Strip any leading `<number>_` prefix from folder names (e.g., `1_my_tool` → `my_tool`)
|
|
196
|
+
2. Match case-insensitively against the provided application name
|
|
197
|
+
3. Accept snake_case, kebab-case, or title-case input (all match the same folder)
|
|
198
|
+
4. If no match found, list available applications and stop
|
|
199
|
+
|
|
200
|
+
### Auto-Resolved Paths
|
|
201
|
+
|
|
202
|
+
| File | Resolved Path |
|
|
203
|
+
|------|---------------|
|
|
204
|
+
| PRD.md | `<app_folder>/context/PRD.md` |
|
|
205
|
+
| Module Models | `<app_folder>/context/model/` |
|
|
206
|
+
| HTML Mockups | `<app_folder>/context/mockup/` |
|
|
207
|
+
| Output (specification) | `<app_folder>/context/specification/` |
|
|
208
|
+
|
|
209
|
+
### Version Filtering
|
|
210
|
+
|
|
211
|
+
When a version is provided, only include user stories, NFRs, and constraints from versions
|
|
212
|
+
<= the provided version. For example, if `v1.0.4` is specified:
|
|
213
|
+
- Include items tagged `[v1.0.0]` through `[v1.0.4]`
|
|
214
|
+
- Exclude items tagged `[v1.0.5]` or later
|
|
215
|
+
- Version comparison uses semantic versioning order
|
|
216
|
+
|
|
217
|
+
### Module Filtering
|
|
218
|
+
|
|
219
|
+
When `module:<name>` is provided:
|
|
220
|
+
- Only generate the `SPEC.md` for that specific module
|
|
221
|
+
- Other existing module spec files remain untouched
|
|
222
|
+
- `SPECIFICATION.md` (root) gets a partial update — only that module's entry in the TOC
|
|
223
|
+
is added or updated; all other TOC entries are preserved as-is
|
|
224
|
+
- The mandatory `user-management/SPEC.md` is regenerated only when the filtered module
|
|
225
|
+
IS the user management module
|
|
226
|
+
|
|
227
|
+
## Gathering Input
|
|
228
|
+
|
|
229
|
+
The specification is driven by **six input sources** read from the project's context
|
|
230
|
+
files. The skill does NOT ask the user for auth, ports, or optional component choices —
|
|
231
|
+
it **determines** these automatically from the context.
|
|
232
|
+
|
|
233
|
+
### Input 1: Application Name (from CLAUDE.md)
|
|
234
|
+
|
|
235
|
+
From CLAUDE.md (already loaded in context), locate the target application under the
|
|
236
|
+
**Custom Applications** section. Extract:
|
|
237
|
+
|
|
238
|
+
- **Application name**: The section heading (e.g., "Home Inventory", "Team Board")
|
|
239
|
+
- **Application description**: The description paragraph below the heading
|
|
240
|
+
- **Dependencies**: The "Depends on" list — a self-hosted local-first app normally has
|
|
241
|
+
none; any external service dependency becomes an optional HTTP integration in the spec
|
|
242
|
+
|
|
243
|
+
The application name is used to derive:
|
|
244
|
+
- **Package name / binary name**: kebab-case (e.g., `home-inventory`) — the npm package
|
|
245
|
+
name, the `bin` entry, AND the per-platform data directory name
|
|
246
|
+
- **App title**: Title-case, used in the SPA `<title>` and topbar
|
|
247
|
+
- **Env var prefix**: SCREAMING_SNAKE of the binary name is NOT used — the CLI env vars
|
|
248
|
+
are always `APP_PORT`, `APP_HOST`, `APP_DATA_DIR`
|
|
249
|
+
|
|
250
|
+
### Input 2: User Stories (from PRD.md)
|
|
251
|
+
|
|
252
|
+
Read `<app_folder>/context/PRD.md`. This file contains all user stories organized by
|
|
253
|
+
module. Extract:
|
|
254
|
+
|
|
255
|
+
- **System modules**: Modules under `# System Module` (e.g., Authentication, User
|
|
256
|
+
Management). These map onto the mandatory auth/user-management blueprint — merge their
|
|
257
|
+
IDs into its traceability rather than generating a competing design.
|
|
258
|
+
- **Business modules**: Modules under `# Business Module`. Each becomes a server feature
|
|
259
|
+
folder (`server/src/features/<module>/`), a set of SPA routes, and a `<module>/SPEC.md`.
|
|
260
|
+
- **CLI-facing stories**: Stories describing terminal interactions (e.g., "start the app
|
|
261
|
+
from my terminal", "reset the admin password offline") map to CLI commands.
|
|
262
|
+
|
|
263
|
+
**Important:** Items with strikethrough (`~~text~~`) are deprecated — do NOT include them
|
|
264
|
+
as active requirements. List them in the "Removed / Replaced" subsection of the
|
|
265
|
+
traceability table. Track the `[v1.0.x]` version tag for each item and carry it through
|
|
266
|
+
to the generated specification's traceability section.
|
|
267
|
+
|
|
268
|
+
### Input 3: Non-Functional Requirements (from PRD.md)
|
|
269
|
+
|
|
270
|
+
Each module's `### Non Functional Requirement` section informs:
|
|
271
|
+
|
|
272
|
+
- Pagination, filtering, and list-size decisions (Hono query params + SPA table setup)
|
|
273
|
+
- Validation rules (character limits, formats) → Zod schemas in `core/`
|
|
274
|
+
- Performance constraints (response budgets, LAN access expectations)
|
|
275
|
+
- Security posture beyond the mandatory auth baseline
|
|
276
|
+
|
|
277
|
+
### Input 4: Constraints (from PRD.md)
|
|
278
|
+
|
|
279
|
+
Each module's `### Constraint` section defines hard boundaries:
|
|
280
|
+
|
|
281
|
+
- Status enum values → Drizzle `text({ enum })` columns + shared Zod enums
|
|
282
|
+
- Business rules → service-layer invariants with tests
|
|
283
|
+
- Access control (e.g., "only ADMIN can ...") → route guard configuration
|
|
284
|
+
|
|
285
|
+
### Input 5: Module Model (from model/ folder)
|
|
286
|
+
|
|
287
|
+
Read `<app_folder>/context/model/MODEL.md` first as the index, then the individual module
|
|
288
|
+
model files (e.g., `model/inventory/model.md` + `schemas.json`). The module model maps to:
|
|
289
|
+
|
|
290
|
+
- Drizzle table definitions in `server/src/db/schema.ts` (field-for-field, not placeholder)
|
|
291
|
+
- Zod schemas in `core/src/schemas/<domain>.ts`
|
|
292
|
+
- Service method signatures and route request/response DTOs
|
|
293
|
+
- Generated SQL migrations shipped in `server/drizzle/`
|
|
294
|
+
|
|
295
|
+
This skill expects **relational models** (`modelgen-relational`) since the datastore is
|
|
296
|
+
SQLite. If only a NoSQL model exists, flatten document structures into relational tables
|
|
297
|
+
and note the mapping decisions in the spec.
|
|
298
|
+
|
|
299
|
+
### Input 6: HTML Mockup Screens (from mockup/ folder)
|
|
300
|
+
|
|
301
|
+
Read `<app_folder>/context/mockup/MOCKUP.html` first as the index, then the HTML files
|
|
302
|
+
organized by role in subfolders. The mockups map to:
|
|
303
|
+
|
|
304
|
+
- React page components in `web/src/routes/` (one per screen)
|
|
305
|
+
- shadcn/ui component selections (Table vs Cards, Dialog vs Sheet, etc.)
|
|
306
|
+
- Navigation structure and per-role menu items
|
|
307
|
+
- Tailwind v4 design tokens (colors, font, radius extracted from mockup CSS)
|
|
308
|
+
|
|
309
|
+
**Role folders inform access control, NOT URL paths.** `mockup/admin/users.html` means
|
|
310
|
+
the route requires the `admin` role — the URL is `/users`, never `/admin/users`. If no
|
|
311
|
+
mockups exist for the mandatory auth screens (login, force-change-password, users,
|
|
312
|
+
settings), spec them from the auth blueprint anyway — they are not optional.
|
|
313
|
+
|
|
314
|
+
## PRD.md Extended Sections
|
|
315
|
+
|
|
316
|
+
Before determining optional components, check PRD.md for the following extended sections:
|
|
317
|
+
|
|
318
|
+
### Architecture Principle Extraction
|
|
319
|
+
|
|
320
|
+
If PRD.md contains an `# Architecture Principle` section, extract patterns that affect
|
|
321
|
+
decisions — but remember this skill's architecture model is fixed. Principles like
|
|
322
|
+
"container based deployment" or "microservices" CONFLICT with the single-process
|
|
323
|
+
local-first model; surface the conflict to the user instead of silently complying.
|
|
324
|
+
Compatible principles (e.g., "offline-first", "no external services") are cited in the
|
|
325
|
+
spec's overview.
|
|
326
|
+
|
|
327
|
+
### Design System Extraction
|
|
328
|
+
|
|
329
|
+
If PRD.md contains a `# Design System` section with a file reference, resolve and read
|
|
330
|
+
it, then map design tokens into the Tailwind v4 CSS-first theme (`@theme` block in the
|
|
331
|
+
SPA's global CSS) and shadcn/ui CSS variables. If absent, derive tokens from the mockup
|
|
332
|
+
CSS (existing behavior).
|
|
333
|
+
|
|
334
|
+
### High Level Process Flow Extraction
|
|
335
|
+
|
|
336
|
+
If PRD.md contains a `# High Level Process Flow` section, flows inform service-method
|
|
337
|
+
sequencing, status enums surfaced in list filters, and the Playwright E2E scenario order.
|
|
338
|
+
If absent, derive flow from user stories only.
|
|
339
|
+
|
|
340
|
+
## Determining Optional Components
|
|
341
|
+
|
|
342
|
+
The mandatory baseline (CLI contract, data directory, bootstrap, auth and user lifecycle)
|
|
343
|
+
is never optional. Beyond it, the skill determines optional components by analyzing
|
|
344
|
+
PRD.md NFRs, constraints, and mockups:
|
|
345
|
+
|
|
346
|
+
| Content Pattern | Component Selection |
|
|
347
|
+
|---|---|
|
|
348
|
+
| NFRs mention "sortable columns", "bulk select", "export CSV", grids | DataGrid = yes (TanStack Table, shadcn Data Table) |
|
|
349
|
+
| NFRs mention "chart", "graph", "statistics", "dashboard metrics" | Charts = yes (Recharts) |
|
|
350
|
+
| NFRs mention "date picker", "date range", "calendar" | DatePickers = yes (react-day-picker) |
|
|
351
|
+
| User stories mention "rich text", "WYSIWYG", "formatted content" | RichText = yes (Tiptap) |
|
|
352
|
+
| User stories mention uploading files/images | FileStorage = yes (files under `<data-dir>/files/`, streamed by a Hono route — never inside the install dir) |
|
|
353
|
+
| NFRs mention periodic/background work ("every hour", "auto-prune", "scheduled") | InProcessJobs = yes (`setInterval` in the server process; no external queue, no daemon) |
|
|
354
|
+
| CLAUDE.md dependencies or NFRs reference an external REST API | HttpIntegration = yes (native `fetch`, config-driven base URL in `config.json`) |
|
|
355
|
+
| PRD.md defines CLI commands beyond start/status/reset-admin | ExtraCommands = yes (list them) |
|
|
356
|
+
|
|
357
|
+
### Summary of Determination
|
|
358
|
+
|
|
359
|
+
After analyzing all inputs, produce a determination summary before generating the spec.
|
|
360
|
+
Present it to the user for confirmation:
|
|
361
|
+
|
|
362
|
+
```
|
|
363
|
+
Mandatory baseline: CLI (start/status/reset-admin) + data dir + bootstrap + scrypt session auth
|
|
364
|
+
Optional Component Determination:
|
|
365
|
+
- DataGrid: yes (from PRD.md → NFR mentions sortable item list with bulk delete)
|
|
366
|
+
- Charts: no
|
|
367
|
+
- DatePickers: yes (from PRD.md → purchase date field)
|
|
368
|
+
- RichText: no
|
|
369
|
+
- FileStorage: yes (from PRD.md → item photo upload)
|
|
370
|
+
- InProcessJobs: no
|
|
371
|
+
- HttpIntegration: no
|
|
372
|
+
- ExtraCommands: yes (`export` — from PRD.md → offline backup story)
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
If the user disagrees with any determination, allow them to override before proceeding.
|
|
376
|
+
|
|
377
|
+
## Generating the Specification
|
|
378
|
+
|
|
379
|
+
Once inputs are gathered and optional components are determined, generate the
|
|
380
|
+
specification as a **multi-file output split by module**. Read the spec template at
|
|
381
|
+
`references/spec-template.md` for the exact structure and content of each section — it is
|
|
382
|
+
the authoritative guide. Read the pattern references when generating the corresponding
|
|
383
|
+
sections:
|
|
384
|
+
|
|
385
|
+
| Reference | Read when generating |
|
|
386
|
+
|---|---|
|
|
387
|
+
| `references/spec-template.md` | Always — the authoritative section-by-section template |
|
|
388
|
+
| `references/cli-packaging-patterns.md` | CLI contract, tsup config, publish pipeline, npm distribution sections |
|
|
389
|
+
| `references/server-patterns.md` | Hono composition, data directory, config, DB factory, logger sections |
|
|
390
|
+
| `references/auth-patterns.md` | Bootstrap, sessions, password hashing, user lifecycle sections |
|
|
391
|
+
| `references/testing-patterns.md` | Testing strategy, smoke test, and Playwright E2E sections |
|
|
392
|
+
|
|
393
|
+
The specification is split into two categories:
|
|
394
|
+
|
|
395
|
+
1. **Root `SPECIFICATION.md`** — TOC, monorepo + workspace config, CLI contract, data
|
|
396
|
+
directory, database layer, server composition, first-run bootstrap, authentication,
|
|
397
|
+
SPA shell, testing strategy, and packaging/distribution.
|
|
398
|
+
2. **Per-module `<module-name>/SPEC.md`** — Each module gets its own folder with a
|
|
399
|
+
self-contained blueprint spanning server feature (routes + service + schema) and SPA
|
|
400
|
+
feature (pages + components + typed client usage).
|
|
401
|
+
|
|
402
|
+
Additionally, generate the **mandatory `user-management/SPEC.md`** covering the auth and
|
|
403
|
+
user lifecycle screens (login, forced change, users list, settings) even when PRD.md has
|
|
404
|
+
no explicit module for it. When PRD.md DOES define an auth/user module, merge its story
|
|
405
|
+
IDs into this file's traceability — the security invariants in `references/auth-patterns.md`
|
|
406
|
+
still win over any conflicting PRD phrasing, and conflicts must be flagged to the user.
|
|
407
|
+
|
|
408
|
+
**Important:** The generated spec must use **real application data** from the context
|
|
409
|
+
files, not generic placeholders:
|
|
410
|
+
|
|
411
|
+
- **Modules** use actual module names from PRD.md and MODEL.md
|
|
412
|
+
- **Drizzle tables and TypeScript types** match the model files field-for-field
|
|
413
|
+
- **Routes and services** map to actual user stories
|
|
414
|
+
- **Pages** map to actual mockup screens; URL paths are module-based, not role-prefixed
|
|
415
|
+
- **Zod schemas** enforce the actual PRD constraints
|
|
416
|
+
- **Version tags** on every user story ID, NFR ID, constraint ID, and mockup screen in
|
|
417
|
+
traceability tables (e.g., `USHI00003 [v1.0.2]`); **ALL traceability sub-tables MUST
|
|
418
|
+
include the `| Version |` column**
|
|
419
|
+
- **Removed / Replaced** subsection lists deprecated items with the removing version,
|
|
420
|
+
replacement ID (if any), and reason
|
|
421
|
+
|
|
422
|
+
### Output Structure
|
|
423
|
+
|
|
424
|
+
```
|
|
425
|
+
<app_folder>/context/specification/
|
|
426
|
+
├── SPECIFICATION.md ← Root: TOC + shared infrastructure (CLI, data dir, DB, server, auth, packaging)
|
|
427
|
+
├── user-management/
|
|
428
|
+
│ └── SPEC.md ← MANDATORY: auth + user lifecycle blueprint
|
|
429
|
+
├── <module-1>/
|
|
430
|
+
│ └── SPEC.md ← Business module blueprint (server feature + SPA feature)
|
|
431
|
+
├── <module-2>/
|
|
432
|
+
│ └── SPEC.md
|
|
433
|
+
└── ... ← One folder per business module from PRD.md
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
**Sample code is mandatory.** Every component described in any spec file must include a
|
|
437
|
+
complete, self-explanatory code sample. The code must be continuous (no `// ...` gaps)
|
|
438
|
+
and usable as a direct reference by a coding agent.
|
|
439
|
+
|
|
440
|
+
## Changelog Append
|
|
441
|
+
|
|
442
|
+
After all specification files are successfully generated, append an entry to `CHANGELOG.md` in the application folder (`<app_folder>/CHANGELOG.md`):
|
|
443
|
+
|
|
444
|
+
1. Read `<app_folder>/CHANGELOG.md`. If it does not exist, create it with:
|
|
445
|
+
```markdown
|
|
446
|
+
# Changelog
|
|
447
|
+
|
|
448
|
+
- This file tracks all skill executions by version for this application.
|
|
449
|
+
- The highest version recorded here is the current application version.
|
|
450
|
+
- Skills MUST NOT execute for a version lower than the highest version in this file.
|
|
451
|
+
|
|
452
|
+
---
|
|
453
|
+
```
|
|
454
|
+
2. Search for a `## {version}` heading matching the current version.
|
|
455
|
+
3. If the section **exists**: append a new row to its table.
|
|
456
|
+
4. If the section **does not exist**: insert a new section after the `---` below the context header and before any existing `## vX.Y.Z` section (newest-first ordering), with a new table header and the first row.
|
|
457
|
+
5. Row format: `| {YYYY-MM-DD} | {application_name} | specgen-node-cli-web | {module or "All"} | Generated self-hosted Node.js CLI web application technical specification |`
|
|
458
|
+
6. **Never modify or delete existing rows.**
|
|
459
|
+
|
|
460
|
+
## Constraints (Non-Negotiable)
|
|
461
|
+
|
|
462
|
+
These constraints apply to every code sample in the generated spec. Where the coding
|
|
463
|
+
agent's habits conflict with them, these constraints win.
|
|
464
|
+
|
|
465
|
+
### Structure & Types
|
|
466
|
+
|
|
467
|
+
**TypeScript strict mode everywhere.** `"strict": true` in every package. No `any` —
|
|
468
|
+
use `unknown` with Zod narrowing. Types derive from schemas via `z.infer<>`.
|
|
469
|
+
|
|
470
|
+
**Zod at every boundary.** CLI flags, `config.json`, every API request body/query, and
|
|
471
|
+
every external input are parsed with a Zod schema before use. Shared schemas live in
|
|
472
|
+
`packages/core` and are consumed by both server routes and SPA forms.
|
|
473
|
+
|
|
474
|
+
**Feature-folder colocation, no barrel files, <300 lines per file.** Each server feature
|
|
475
|
+
is `features/<name>/{routes.ts, service.ts, schema.ts, __tests__/}`. No `index.ts`
|
|
476
|
+
re-export barrels.
|
|
477
|
+
|
|
478
|
+
**Thin CLI handlers.** Command handlers parse flags with commander, validate with Zod,
|
|
479
|
+
and delegate to `server`/`core` functions. No business logic in `packages/cli`.
|
|
480
|
+
|
|
481
|
+
### Process & Distribution
|
|
482
|
+
|
|
483
|
+
**Foreground process only.** `start` runs in the foreground; Ctrl-C stops it with a
|
|
484
|
+
graceful shutdown that closes the SQLite handle. NEVER implement forking/daemon logic —
|
|
485
|
+
daemonization belongs to `systemd`/`pm2`.
|
|
486
|
+
|
|
487
|
+
**Fail loud on a taken port.** Print a clear message naming the flag to change it
|
|
488
|
+
(`--port`); never auto-increment silently.
|
|
489
|
+
|
|
490
|
+
**Option resolution order** for every `start` option: CLI flag → environment variable
|
|
491
|
+
(`APP_PORT`, `APP_HOST`, `APP_DATA_DIR`) → `config.json` → default (port `3000`, host
|
|
492
|
+
`0.0.0.0` for LAN access).
|
|
493
|
+
|
|
494
|
+
**The install directory is read-only at runtime.** Global npm installs may not be
|
|
495
|
+
writable — never write anything next to the installed code. All state (DB, config, files,
|
|
496
|
+
logs) lives in the per-platform data directory, created `0700` on first run.
|
|
497
|
+
|
|
498
|
+
**`better-sqlite3` stays external.** It is a native module: a real runtime `dependency`
|
|
499
|
+
of the published package, never bundled by tsup, never a devDependency. Everything else
|
|
500
|
+
is bundled into `dist/` — end users must not need pnpm or the workspace.
|
|
501
|
+
|
|
502
|
+
**Migrations auto-run on every `start`** before the server binds, against the shipped
|
|
503
|
+
`drizzle/` folder. Idempotent; no user-facing migrate command.
|
|
504
|
+
|
|
505
|
+
### Server & Security
|
|
506
|
+
|
|
507
|
+
**One Hono app serves everything.** `/api/*` routes first, then `serveStatic` for the SPA
|
|
508
|
+
build, with an SPA fallback rewriting unknown non-API GETs to `index.html`. Middleware
|
|
509
|
+
order: request-id → logger → session resolution → route guards → routes.
|
|
510
|
+
|
|
511
|
+
**No CORS, security headers on.** `hono/secure-headers` on all responses. The UI is
|
|
512
|
+
same-origin by construction — never add permissive CORS.
|
|
513
|
+
|
|
514
|
+
**Typed API contract via `hono/client`.** Export the route tree's type from `server`;
|
|
515
|
+
`web` consumes a fully typed RPC client. No OpenAPI codegen step.
|
|
516
|
+
|
|
517
|
+
**Auth is hand-rolled scrypt sessions — nothing else.** scrypt via `node:crypto`
|
|
518
|
+
(N=2^15, r=8, p=1, 32-byte key, 16-byte salt, `timingSafeEqual` verify). Opaque session
|
|
519
|
+
tokens: raw token client-side in an `httpOnly` `SameSite=Lax` cookie, only the SHA-256
|
|
520
|
+
hash server-side; sliding expiry, 30-day absolute cap. NEVER implement email flows,
|
|
521
|
+
self-serve registration, OAuth/social login, JWTs, or password recovery other than
|
|
522
|
+
`reset-admin` (CLI) and admin-reset (UI).
|
|
523
|
+
|
|
524
|
+
**Forced password change is server-enforced.** While `must_change_password` is true,
|
|
525
|
+
every API route except login, change-password, and logout returns
|
|
526
|
+
`403 PASSWORD_CHANGE_REQUIRED` from middleware. The SPA redirect is convenience, not the
|
|
527
|
+
control.
|
|
528
|
+
|
|
529
|
+
**Server-side invariants with tests:** cannot delete the last remaining admin; changing a
|
|
530
|
+
password revokes all other sessions; login is rate-limited in-memory (10 attempts / 15
|
|
531
|
+
min per username+IP); the plaintext bootstrap password is printed once and never written
|
|
532
|
+
to any file or log.
|
|
533
|
+
|
|
534
|
+
**No module-level DB singletons.** The connection factory takes the resolved data-dir
|
|
535
|
+
path as an argument (so tests inject `:memory:`) and always sets the mandatory pragmas:
|
|
536
|
+
WAL mode, `foreign_keys = ON`, `busy_timeout = 5000`.
|
|
537
|
+
|
|
538
|
+
### Verification
|
|
539
|
+
|
|
540
|
+
**`pnpm verify` must pass before any task is complete** — `check` (tsc + Biome), `test`
|
|
541
|
+
(Vitest with real migrations on `:memory:`, never a mocked DB), `build`, and the
|
|
542
|
+
**mandatory smoke stage** that executes the *built* CLI: random port, temp `--data-dir`,
|
|
543
|
+
HTTP 200 on `/` and the health endpoint, login with the printed admin credentials, clean
|
|
544
|
+
shutdown. Shebang, bundling, native-module, and asset-path failures only surface
|
|
545
|
+
post-build — testing source alone is insufficient.
|
|
546
|
+
|
|
547
|
+
## Principles Embedded in the Spec
|
|
548
|
+
|
|
549
|
+
- Local-first: the user's machine is the source of truth; filesystem access is the root
|
|
550
|
+
of trust (hence `reset-admin` instead of email recovery)
|
|
551
|
+
- One printed status block on successful start: local URL, network URL (detected LAN IP),
|
|
552
|
+
data directory, version — structured logs after that
|
|
553
|
+
- The `package.json` version field equals the version argument from skill invocation;
|
|
554
|
+
`--version` prints it and the SPA footer renders it
|
|
555
|
+
- Password policy is NIST 800-63B posture: minimum 10 characters, reject
|
|
556
|
+
username-as-password, no composition-class rules
|
|
557
|
+
- `Secure` cookie flag only when the request arrived over HTTPS — local HTTP on a LAN
|
|
558
|
+
must still work; TLS termination is a reverse-proxy concern (documented, not built)
|
|
559
|
+
- Definition of Done per task: structure per the monorepo layout, thin CLI handlers, Zod
|
|
560
|
+
boundaries, shipped migrations, auth invariants tested, `pnpm verify` green including
|
|
561
|
+
the built-binary smoke test, `CLAUDE.md` and `--help` updated when commands change
|