openspec-stack-init 1.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.
package/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# openspec-stack-init
|
|
2
|
+
|
|
3
|
+
> Initialize OpenSpec + Beads + claude-mem + skills in any project — one command.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Current directory
|
|
9
|
+
npx openspec-stack-init
|
|
10
|
+
|
|
11
|
+
# Specific project path
|
|
12
|
+
npx openspec-stack-init ./my-project
|
|
13
|
+
npx openspec-stack-init /absolute/path/to/project
|
|
14
|
+
|
|
15
|
+
# Preview without making changes
|
|
16
|
+
npx openspec-stack-init --dry-run
|
|
17
|
+
npx openspec-stack-init ./my-project --dry-run
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## What it installs
|
|
21
|
+
|
|
22
|
+
| Tool | What it does | Non-interactive flag used |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| **OpenSpec** | Spec-driven development | `openspec init --tools claude --profile expanded --force` |
|
|
25
|
+
| **Beads** | Git-backed issue tracker / agent memory | `bd init --quiet` + `bd setup claude` |
|
|
26
|
+
| **claude-mem** | Automatic session memory via hooks | `claude plugin marketplace add` + `claude plugin install` |
|
|
27
|
+
| **openspec-to-beads** | Syncs OpenSpec tasks.md → Beads issues | `npx @smithery/cli skill add` |
|
|
28
|
+
| **/migrate-to-openspec** | Brownfield migration skill | Copied to `.claude/skills/migrate-to-openspec/` |
|
|
29
|
+
|
|
30
|
+
## Prerequisites
|
|
31
|
+
|
|
32
|
+
> ⚠️ **This package does NOT install the tools below for you.**
|
|
33
|
+
> It only wires them together in your project.
|
|
34
|
+
> Make sure all of the following are installed before running `npx openspec-stack-init`.
|
|
35
|
+
|
|
36
|
+
| Tool | Install instructions |
|
|
37
|
+
|---|---|
|
|
38
|
+
| **OpenSpec** | [github.com/Fission-AI/OpenSpec](https://github.com/Fission-AI/OpenSpec) |
|
|
39
|
+
| **Beads** | [INSTALLING.md](https://github.com/steveyegge/beads/blob/main/docs/INSTALLING.md) |
|
|
40
|
+
| **claude-mem** | [github.com/thedotmack/claude-mem](https://github.com/thedotmack/claude-mem) |
|
|
41
|
+
| **Claude Code** | `npm install -g @anthropic-ai/claude-code` |
|
|
42
|
+
| **Node.js** | [nodejs.org](https://nodejs.org) (v18+) |
|
|
43
|
+
|
|
44
|
+
Each tool has multiple installation options — pick whichever works best for your environment.
|
|
45
|
+
|
|
46
|
+
## Platform support
|
|
47
|
+
|
|
48
|
+
Works on **macOS**, **Windows**, and **Linux** — it's a Node.js script, no bash required.
|
|
49
|
+
|
|
50
|
+
Requires Node.js 18+.
|
|
51
|
+
|
|
52
|
+
## After running
|
|
53
|
+
|
|
54
|
+
### Step 1 — Initialize Claude Code in your project
|
|
55
|
+
|
|
56
|
+
Open Claude Code in the project directory and run:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
/init
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
This creates `CLAUDE.md` — Claude Code's project-level memory file. It also
|
|
63
|
+
ensures the `.claude/` folder is fully recognized by Claude Code. Run this
|
|
64
|
+
**before** using any skills or slash commands.
|
|
65
|
+
|
|
66
|
+
> **Note:** `openspec-stack-init` already creates `.claude/skills/` so the
|
|
67
|
+
> installed skills will be found automatically. But without `CLAUDE.md`
|
|
68
|
+
> (generated by `/init`), Claude Code has no project context to work with.
|
|
69
|
+
|
|
70
|
+
### Step 2 — Brownfield project
|
|
71
|
+
|
|
72
|
+
Run inside Claude Code:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
/migrate-to-openspec
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
This scans the codebase using 4 parallel scout agents and auto-generates all
|
|
79
|
+
OpenSpec files: `config.yaml`, architecture specs, feature specs, and active
|
|
80
|
+
changes from TODOs/FIXMEs. See `openspec/MIGRATION_REPORT.md` for a summary
|
|
81
|
+
of what was created and what needs human review.
|
|
82
|
+
|
|
83
|
+
### Step 2 — Greenfield project
|
|
84
|
+
|
|
85
|
+
Skip `/migrate-to-openspec`. Instead:
|
|
86
|
+
|
|
87
|
+
1. Edit `openspec/config.yaml` — describe your planned stack and conventions
|
|
88
|
+
2. Run `/opsx:propose <feature>` to start your first spec
|
|
89
|
+
|
|
90
|
+
## Local development / run without publishing
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
git clone <this-repo>
|
|
94
|
+
cd openspec-stack-init
|
|
95
|
+
npm install
|
|
96
|
+
node src/index.js ./target-project
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## Publish to npm (optional)
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
npm publish --access public
|
|
103
|
+
# Then anyone can run: npx openspec-stack-init
|
|
104
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "openspec-stack-init",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Initialize OpenSpec + Beads + claude-mem + skills in any project",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "VirtualMaestro",
|
|
7
|
+
"email": "virtualmaestro@gmail.com"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+ssh://git@github.com/VirtualMaestro/openspec-stack-init.git"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/VirtualMaestro/openspec-stack-init#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/VirtualMaestro/openspec-stack-init/issues"
|
|
16
|
+
},
|
|
17
|
+
"bin": {
|
|
18
|
+
"openspec-stack-init": "./src/index.js"
|
|
19
|
+
},
|
|
20
|
+
"scripts": {
|
|
21
|
+
"start": "node src/index.js"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"chalk": "^5.3.0",
|
|
25
|
+
"execa": "^8.0.1",
|
|
26
|
+
"ora": "^8.0.1"
|
|
27
|
+
},
|
|
28
|
+
"engines": {
|
|
29
|
+
"node": ">=18.0.0"
|
|
30
|
+
},
|
|
31
|
+
"keywords": ["openspec", "beads", "claude-mem", "claude-code", "ai-stack"],
|
|
32
|
+
"license": "MIT"
|
|
33
|
+
}
|
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: migrate-to-openspec
|
|
3
|
+
description: >
|
|
4
|
+
Brownfield migration skill. Scans an existing project and automatically
|
|
5
|
+
generates a complete OpenSpec baseline: config.yaml, architecture specs,
|
|
6
|
+
feature specs, and active changes from TODOs. Also optimizes CLAUDE.md by
|
|
7
|
+
removing references to docs now absorbed into OpenSpec. Invoke manually for
|
|
8
|
+
brownfield projects only. NOT for greenfield.
|
|
9
|
+
disable-model-invocation: true
|
|
10
|
+
allowed-tools: Bash, Glob, Grep, Read, Write, Task
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# /migrate-to-openspec — Brownfield Migration to OpenSpec
|
|
14
|
+
|
|
15
|
+
You are performing a **one-time brownfield migration** of an existing project into
|
|
16
|
+
OpenSpec format. Your job is to scan the codebase automatically and generate all
|
|
17
|
+
OpenSpec files from scratch. The user will review and adjust the results afterward.
|
|
18
|
+
|
|
19
|
+
## Pre-flight checks
|
|
20
|
+
|
|
21
|
+
Before doing anything else, verify the environment:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# 1. OpenSpec must be initialized
|
|
25
|
+
openspec status --json 2>&1 || echo "NOT_INITIALIZED"
|
|
26
|
+
|
|
27
|
+
# 2. Check what already exists
|
|
28
|
+
ls openspec/specs/ 2>/dev/null | wc -l
|
|
29
|
+
ls openspec/changes/ 2>/dev/null | wc -l
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
If OpenSpec is not initialized, stop and tell the user:
|
|
33
|
+
> OpenSpec is not initialized. Run `openspec init --tools claude --profile expanded --force` first, then run `/migrate-to-openspec` again.
|
|
34
|
+
|
|
35
|
+
If `openspec/specs/` already contains files, warn the user:
|
|
36
|
+
> ⚠️ OpenSpec specs already exist. This migration will ADD to existing specs, not overwrite them. Proceed? (y/N)
|
|
37
|
+
|
|
38
|
+
Wait for confirmation before continuing.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Migration Strategy: Multi-Agent Phases
|
|
43
|
+
|
|
44
|
+
This migration uses **4 parallel scout agents** (via Task tool) to scan the
|
|
45
|
+
codebase simultaneously, then a synthesis phase to write all OpenSpec files.
|
|
46
|
+
|
|
47
|
+
**Do not start synthesis until all 4 scout agents have returned results.**
|
|
48
|
+
|
|
49
|
+
Announce to the user:
|
|
50
|
+
> Starting brownfield migration. Spawning 4 scout agents to analyze the project in parallel. This may take a few minutes...
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Phase 1: Spawn Scout Agents (parallel, via Task tool)
|
|
55
|
+
|
|
56
|
+
Spawn all 4 agents simultaneously using the Task tool:
|
|
57
|
+
|
|
58
|
+
### Scout Agent 1 — Project Structure & Tech Stack
|
|
59
|
+
|
|
60
|
+
Task prompt:
|
|
61
|
+
```
|
|
62
|
+
You are a read-only scout agent. Scan this project and return a structured report.
|
|
63
|
+
Do NOT modify any files.
|
|
64
|
+
|
|
65
|
+
Collect ALL of the following:
|
|
66
|
+
|
|
67
|
+
1. PROJECT OVERVIEW
|
|
68
|
+
- Primary language(s) and versions (check *.csproj, package.json, go.mod, Cargo.toml, etc.)
|
|
69
|
+
- Framework/engine (Unity, React, Django, etc.) and version
|
|
70
|
+
- Project type (game, web app, library, CLI, etc.)
|
|
71
|
+
- Top-level folder structure (2 levels deep)
|
|
72
|
+
- Entry points (main files, startup scenes, index files)
|
|
73
|
+
- Build system (Makefile, cmake, gradle, Unity build settings, etc.)
|
|
74
|
+
|
|
75
|
+
2. ARCHITECTURE PATTERNS
|
|
76
|
+
- Identify dominant patterns: MVC, MVVM, HMVC, ECS, layered, microservices, etc.
|
|
77
|
+
- Key abstractions: what are the main classes/modules/systems?
|
|
78
|
+
- Dependency direction: what depends on what?
|
|
79
|
+
- Data flow: how does data move through the system?
|
|
80
|
+
- Read up to 20 key source files to understand the architecture.
|
|
81
|
+
Focus on: base classes, interfaces, managers, controllers, core systems.
|
|
82
|
+
|
|
83
|
+
3. EXTERNAL DEPENDENCIES
|
|
84
|
+
- Third-party libraries/packages (from lock files and manifests)
|
|
85
|
+
- External APIs or services used
|
|
86
|
+
- Database or persistence layer
|
|
87
|
+
|
|
88
|
+
4. TEST COVERAGE
|
|
89
|
+
- Does a test folder exist? What framework?
|
|
90
|
+
- Rough estimate: are there many, some, or no tests?
|
|
91
|
+
|
|
92
|
+
5. BUILD & CI
|
|
93
|
+
- CI config files (.github/workflows, .gitlab-ci.yml, etc.)
|
|
94
|
+
- Scripts in package.json or Makefile
|
|
95
|
+
|
|
96
|
+
Return your findings as a structured markdown report under these exact headings:
|
|
97
|
+
## TECH_STACK
|
|
98
|
+
## ARCHITECTURE
|
|
99
|
+
## DEPENDENCIES
|
|
100
|
+
## TESTING
|
|
101
|
+
## BUILD_CI
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Scout Agent 2 — Existing Documentation & CLAUDE.md Audit
|
|
105
|
+
|
|
106
|
+
Task prompt:
|
|
107
|
+
```
|
|
108
|
+
You are a read-only scout agent. Find and extract ALL existing documentation,
|
|
109
|
+
and perform a full audit of CLAUDE.md. Do NOT modify any files.
|
|
110
|
+
|
|
111
|
+
PART A — DOCUMENTATION HARVEST
|
|
112
|
+
|
|
113
|
+
Search for and read:
|
|
114
|
+
1. README.md, README.*, CONTRIBUTING.md, ARCHITECTURE.md, DESIGN.md
|
|
115
|
+
2. Any /docs, /documentation, /wiki, /specs, /.notes folder
|
|
116
|
+
3. Any existing proposals, design docs, ADRs (Architecture Decision Records)
|
|
117
|
+
4. CHANGELOG.md or HISTORY.md
|
|
118
|
+
5. Any .md files in root or subdirectories (sample up to 30 files)
|
|
119
|
+
6. Comments at the top of key source files that describe the module purpose
|
|
120
|
+
7. Any openspec/ folder content that already exists
|
|
121
|
+
|
|
122
|
+
For each document found, extract:
|
|
123
|
+
- Its PURPOSE (what does it describe?)
|
|
124
|
+
- Key REQUIREMENTS or CONSTRAINTS mentioned
|
|
125
|
+
- DECISIONS already made
|
|
126
|
+
- FUTURE PLANS mentioned
|
|
127
|
+
|
|
128
|
+
PART B — CLAUDE.md AUDIT
|
|
129
|
+
|
|
130
|
+
Read CLAUDE.md carefully (if it exists). For every file reference, link, or
|
|
131
|
+
"read this document" instruction found inside CLAUDE.md:
|
|
132
|
+
|
|
133
|
+
1. Note the referenced file path
|
|
134
|
+
2. Check if that file actually exists on disk
|
|
135
|
+
3. Estimate the token cost: is it a large doc (>200 lines) or small?
|
|
136
|
+
4. Classify the reference as one of:
|
|
137
|
+
- ESSENTIAL: Claude genuinely needs this every session (e.g. project conventions,
|
|
138
|
+
critical architecture rules, active task lists)
|
|
139
|
+
- REDUNDANT_AFTER_MIGRATION: this doc's knowledge will be fully covered by
|
|
140
|
+
OpenSpec specs and config.yaml after migration
|
|
141
|
+
- STALE: file does not exist on disk or is clearly outdated
|
|
142
|
+
- UNCLEAR: cannot determine without more context
|
|
143
|
+
|
|
144
|
+
Return your findings as a structured markdown report under these exact headings:
|
|
145
|
+
## EXISTING_DOCS (list of files found with one-line summary each)
|
|
146
|
+
## EXTRACTED_REQUIREMENTS (bulleted list of concrete requirements found)
|
|
147
|
+
## ARCHITECTURAL_DECISIONS (decisions already made, from ADRs or docs)
|
|
148
|
+
## FUTURE_PLANS (things mentioned as planned/upcoming/TODO in documentation)
|
|
149
|
+
## RAW_EXCERPTS (paste the most important 3-5 paragraphs from docs verbatim)
|
|
150
|
+
## CLAUDE_MD_AUDIT
|
|
151
|
+
### Current references in CLAUDE.md:
|
|
152
|
+
- <file path> | <classification> | <token cost estimate> | <reason>
|
|
153
|
+
### Estimated token waste per session (sum of REDUNDANT + STALE docs):
|
|
154
|
+
<N> lines / approx <N> tokens loaded unnecessarily every session
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Scout Agent 3 — Technical Debt & Active Work
|
|
158
|
+
|
|
159
|
+
Task prompt:
|
|
160
|
+
```
|
|
161
|
+
You are a read-only scout agent. Find ALL signals of active work and technical debt.
|
|
162
|
+
Do NOT modify any files.
|
|
163
|
+
|
|
164
|
+
1. SEARCH FOR DEBT MARKERS
|
|
165
|
+
Run these searches across all source files:
|
|
166
|
+
- grep -rn "TODO" --include="*.cs" --include="*.ts" --include="*.js" --include="*.py" --include="*.dart" --include="*.go" --include="*.rs" --include="*.lua" . | head -200
|
|
167
|
+
- grep -rn "FIXME\|HACK\|BUG\|BROKEN\|WORKAROUND\|TEMPORARY\|TEMP\b" --include="*.cs" --include="*.ts" --include="*.js" --include="*.py" --include="*.dart" --include="*.go" --include="*.rs" --include="*.lua" . | head -200
|
|
168
|
+
- grep -rn "DEPRECATED\|OBSOLETE\|REMOVE\|DELETE ME\|REFACTOR" --include="*.cs" --include="*.ts" --include="*.js" --include="*.py" --include="*.dart" --include="*.go" --include="*.rs" --include="*.lua" . | head -100
|
|
169
|
+
- Adapt file extensions to the actual tech stack of this project.
|
|
170
|
+
|
|
171
|
+
2. CLASSIFY EACH ITEM into one of:
|
|
172
|
+
- FEATURE: something new to build
|
|
173
|
+
- BUG: known bug
|
|
174
|
+
- DEBT: refactoring needed
|
|
175
|
+
- QUESTION: unresolved design question
|
|
176
|
+
- PERF: performance issue
|
|
177
|
+
- DEPRECATION: legacy code to remove
|
|
178
|
+
|
|
179
|
+
3. FIND GIT SIGNALS
|
|
180
|
+
- git log --oneline -50 (recent commits to understand current focus)
|
|
181
|
+
- git diff --name-only HEAD~10 (recently changed files)
|
|
182
|
+
- git stash list (any stashed work?)
|
|
183
|
+
|
|
184
|
+
4. FIND INCOMPLETE WORK
|
|
185
|
+
- Partially implemented features (stub files, empty methods, "not implemented" exceptions)
|
|
186
|
+
- Files with many commented-out blocks
|
|
187
|
+
|
|
188
|
+
Return your findings as a structured markdown report under these headings:
|
|
189
|
+
## DEBT_SUMMARY (count by category: X features, Y bugs, Z debt items, etc.)
|
|
190
|
+
## FEATURES (list: "filename:line - description")
|
|
191
|
+
## BUGS (list: "filename:line - description")
|
|
192
|
+
## DEBT (list: "filename:line - description")
|
|
193
|
+
## QUESTIONS (list: "filename:line - description")
|
|
194
|
+
## PERF (list: "filename:line - description")
|
|
195
|
+
## DEPRECATIONS (list: "filename:line - description")
|
|
196
|
+
## GIT_SIGNALS (what recent commits reveal about current priorities)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Scout Agent 4 — Module Boundaries & Feature Map
|
|
200
|
+
|
|
201
|
+
Task prompt:
|
|
202
|
+
```
|
|
203
|
+
You are a read-only scout agent. Map the features and modules of this project.
|
|
204
|
+
Do NOT modify any files.
|
|
205
|
+
|
|
206
|
+
1. IDENTIFY ALL FEATURES/SYSTEMS
|
|
207
|
+
Walk through the entire source code and identify discrete features, systems,
|
|
208
|
+
or capabilities. A "feature" is something a user or another system can do.
|
|
209
|
+
Examples for a game: "card combat", "deck building", "matchmaking", "save system"
|
|
210
|
+
Examples for a web app: "user auth", "payment processing", "notifications"
|
|
211
|
+
|
|
212
|
+
Read enough files in each module to understand what it does.
|
|
213
|
+
|
|
214
|
+
2. FOR EACH FEATURE/SYSTEM, document:
|
|
215
|
+
- Name (short, kebab-case)
|
|
216
|
+
- Purpose (1 sentence)
|
|
217
|
+
- Key files (list main files)
|
|
218
|
+
- Status: COMPLETE | IN_PROGRESS | BROKEN | PARTIAL | PLANNED
|
|
219
|
+
- Stability: STABLE | UNSTABLE | LEGACY | EXPERIMENTAL
|
|
220
|
+
- Dependencies on other features
|
|
221
|
+
|
|
222
|
+
3. IDENTIFY CROSS-CUTTING CONCERNS
|
|
223
|
+
- Logging, error handling, configuration, authentication patterns
|
|
224
|
+
- Any shared utilities or base classes used everywhere
|
|
225
|
+
|
|
226
|
+
Return your findings as a structured markdown report under these headings:
|
|
227
|
+
## FEATURE_MAP (one entry per feature in format below)
|
|
228
|
+
### Feature: <n>
|
|
229
|
+
- Purpose: ...
|
|
230
|
+
- Files: ...
|
|
231
|
+
- Status: ...
|
|
232
|
+
- Stability: ...
|
|
233
|
+
- Depends on: ...
|
|
234
|
+
|
|
235
|
+
## CROSS_CUTTING_CONCERNS
|
|
236
|
+
## SUGGESTED_SPEC_GROUPS (how to group features into spec files)
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
---
|
|
240
|
+
|
|
241
|
+
## Phase 2: Synthesize Results
|
|
242
|
+
|
|
243
|
+
After all 4 agents return, you now have complete information about the project.
|
|
244
|
+
Proceed to write all OpenSpec files. **Do not ask the user for input during this phase.**
|
|
245
|
+
Write everything based on what the agents discovered.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Phase 3: Write `openspec/config.yaml`
|
|
250
|
+
|
|
251
|
+
Generate `openspec/config.yaml` from the combined scout reports.
|
|
252
|
+
|
|
253
|
+
Use this structure (fill in all fields from discovered data — do NOT leave placeholders):
|
|
254
|
+
|
|
255
|
+
```yaml
|
|
256
|
+
# OpenSpec Project Config — auto-generated by /migrate-to-openspec
|
|
257
|
+
# Review and adjust as needed.
|
|
258
|
+
|
|
259
|
+
schema: spec-driven
|
|
260
|
+
|
|
261
|
+
context: |
|
|
262
|
+
Project: <name from structure scan>
|
|
263
|
+
Type: <game / web app / library / etc.>
|
|
264
|
+
|
|
265
|
+
Tech stack:
|
|
266
|
+
<list discovered languages, frameworks, versions>
|
|
267
|
+
|
|
268
|
+
Architecture: <describe the pattern found, e.g. "HMVC with ECS for combat systems">
|
|
269
|
+
|
|
270
|
+
Key systems:
|
|
271
|
+
<bullet list of major features/systems found>
|
|
272
|
+
|
|
273
|
+
External dependencies:
|
|
274
|
+
<key libraries/services found>
|
|
275
|
+
|
|
276
|
+
Testing: <what was found — none / unit tests / integration tests / etc.>
|
|
277
|
+
|
|
278
|
+
Conventions discovered:
|
|
279
|
+
<naming patterns, folder conventions, coding style observed in codebase>
|
|
280
|
+
|
|
281
|
+
Known constraints:
|
|
282
|
+
<things the agents discovered that constrain development>
|
|
283
|
+
|
|
284
|
+
rules:
|
|
285
|
+
proposal:
|
|
286
|
+
- Always describe impact on existing systems
|
|
287
|
+
- Reference the spec file(s) being modified
|
|
288
|
+
specs:
|
|
289
|
+
- Use Given/When/Then format for all scenarios
|
|
290
|
+
- Each Requirement must have at least one Scenario
|
|
291
|
+
design:
|
|
292
|
+
- Must reference at least one existing file by path
|
|
293
|
+
- Must describe impact on other systems
|
|
294
|
+
tasks:
|
|
295
|
+
- Keep each task scoped to 1-3 files maximum
|
|
296
|
+
- Order tasks so earlier ones never depend on later ones
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
Write to `openspec/config.yaml`.
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Phase 4: Write Architecture Spec
|
|
304
|
+
|
|
305
|
+
Based on Scout Agent 1 and 4 findings, write `openspec/specs/architecture/spec.md`.
|
|
306
|
+
|
|
307
|
+
Use the template from `templates/architecture-spec.md` (in this skill's folder).
|
|
308
|
+
Adapt it fully — use real names, real file paths, real patterns found by the agents.
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## Phase 5: Write Feature Specs
|
|
313
|
+
|
|
314
|
+
For each feature/system identified by Scout Agent 4 with status COMPLETE or STABLE,
|
|
315
|
+
write a spec file at `openspec/specs/<feature-name>/spec.md`.
|
|
316
|
+
|
|
317
|
+
Use the template from `templates/feature-spec.md` (in this skill's folder).
|
|
318
|
+
|
|
319
|
+
**Priority order for writing specs:**
|
|
320
|
+
1. Core/foundational systems first (things many other features depend on)
|
|
321
|
+
2. User-facing features second
|
|
322
|
+
3. Infrastructure/tooling last
|
|
323
|
+
|
|
324
|
+
Limit to the **10 most important** features on first pass.
|
|
325
|
+
Note at the top of each spec file: `# Auto-generated — review for accuracy`
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Phase 6: Create OpenSpec Changes for Active Work
|
|
330
|
+
|
|
331
|
+
For each item in Scout Agent 3's FEATURES and BUGS lists that represents
|
|
332
|
+
**unfinished or planned work**, create an OpenSpec change.
|
|
333
|
+
|
|
334
|
+
For each such item:
|
|
335
|
+
|
|
336
|
+
1. Create `openspec/changes/<kebab-name>/`
|
|
337
|
+
2. Write `proposal.md`:
|
|
338
|
+
|
|
339
|
+
```markdown
|
|
340
|
+
# Proposal: <title>
|
|
341
|
+
# Auto-generated from: <filename>:<line> — review and refine as needed.
|
|
342
|
+
|
|
343
|
+
## Why
|
|
344
|
+
<Describe what the TODO/FIXME says needs to be done>
|
|
345
|
+
|
|
346
|
+
Discovered in: `<file path>:<line number>`
|
|
347
|
+
Original comment: `<exact text of the TODO/FIXME>`
|
|
348
|
+
|
|
349
|
+
## What Changes
|
|
350
|
+
<List the files or systems likely affected>
|
|
351
|
+
|
|
352
|
+
## Impact
|
|
353
|
+
<What breaks or changes if this isn't done vs. if it is done>
|
|
354
|
+
|
|
355
|
+
## Rollback
|
|
356
|
+
<How to undo this change if it goes wrong>
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
3. Write `tasks.md` with a single starter task:
|
|
360
|
+
|
|
361
|
+
```markdown
|
|
362
|
+
# Tasks
|
|
363
|
+
|
|
364
|
+
## 1. Implementation
|
|
365
|
+
- [ ] 1.1 Implement: <short description>
|
|
366
|
+
- Files: `<filename>`
|
|
367
|
+
- Details: <from the TODO comment>
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
**Limit**: Create at most **20 changes** on first pass. If there are more,
|
|
371
|
+
create a summary file at `openspec/changes/_backlog.md` listing all remaining items.
|
|
372
|
+
|
|
373
|
+
> **Note on Beads sync:** Do NOT create Beads issues manually here.
|
|
374
|
+
> After migration is complete, use the `/openspec-to-beads` skill to sync
|
|
375
|
+
> all OpenSpec changes to Beads in one step. It was installed by
|
|
376
|
+
> `openspec-stack-init` and handles this automatically.
|
|
377
|
+
|
|
378
|
+
---
|
|
379
|
+
|
|
380
|
+
## Phase 7: Optimize CLAUDE.md
|
|
381
|
+
|
|
382
|
+
This phase eliminates token waste in future sessions. Every doc reference in
|
|
383
|
+
CLAUDE.md that is now covered by OpenSpec gets loaded into context on every
|
|
384
|
+
single session start — even though the knowledge already lives in openspec/specs/
|
|
385
|
+
and openspec/config.yaml. This phase removes that redundancy.
|
|
386
|
+
|
|
387
|
+
### Step 1 — Read CLAUDE.md
|
|
388
|
+
|
|
389
|
+
```bash
|
|
390
|
+
cat CLAUDE.md 2>/dev/null || echo "NO_CLAUDE_MD"
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
If CLAUDE.md does not exist, skip this phase and note it in the report.
|
|
394
|
+
|
|
395
|
+
### Step 2 — Determine what to remove
|
|
396
|
+
|
|
397
|
+
Using the `## CLAUDE_MD_AUDIT` from Scout Agent 2, build two lists:
|
|
398
|
+
|
|
399
|
+
**REMOVE** (references that are now redundant):
|
|
400
|
+
- All references classified as **REDUNDANT_AFTER_MIGRATION**
|
|
401
|
+
— their knowledge is now in `openspec/specs/` and `openspec/config.yaml`
|
|
402
|
+
- All references classified as **STALE**
|
|
403
|
+
— files that do not exist on disk
|
|
404
|
+
|
|
405
|
+
**KEEP** (do not touch):
|
|
406
|
+
- All references classified as **ESSENTIAL**
|
|
407
|
+
- All references classified as **UNCLEAR** (when in doubt, keep)
|
|
408
|
+
- Any content that is NOT a doc reference (inline conventions, tool config, etc.)
|
|
409
|
+
- Any blocks marked with OpenSpec's own managed markers
|
|
410
|
+
|
|
411
|
+
### Step 3 — Back up and rewrite
|
|
412
|
+
|
|
413
|
+
```bash
|
|
414
|
+
cp CLAUDE.md CLAUDE.md.pre-migration
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
Rewrite CLAUDE.md: keep all ESSENTIAL content intact, remove REDUNDANT and STALE
|
|
418
|
+
doc references, and add this single replacement block where the removed references
|
|
419
|
+
were:
|
|
420
|
+
|
|
421
|
+
```markdown
|
|
422
|
+
## Project Knowledge Base
|
|
423
|
+
|
|
424
|
+
Architecture, requirements, and active work are maintained in OpenSpec.
|
|
425
|
+
See: openspec/specs/ (source of truth) and openspec/changes/ (active work).
|
|
426
|
+
Project context is injected automatically via openspec/config.yaml.
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Step 4 — Safety rules
|
|
430
|
+
|
|
431
|
+
- Do NOT delete CLAUDE.md — only edit it
|
|
432
|
+
- Do NOT remove OpenSpec managed blocks (marked with OpenSpec markers)
|
|
433
|
+
- Do NOT remove git hooks, tool configurations, or coding conventions
|
|
434
|
+
- If uncertain about any reference — keep it
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## Phase 8: Write Migration Report
|
|
439
|
+
|
|
440
|
+
Write `openspec/MIGRATION_REPORT.md`:
|
|
441
|
+
|
|
442
|
+
```markdown
|
|
443
|
+
# OpenSpec Migration Report
|
|
444
|
+
Generated: <date>
|
|
445
|
+
By: /migrate-to-openspec skill
|
|
446
|
+
|
|
447
|
+
## What Was Created
|
|
448
|
+
|
|
449
|
+
### config.yaml
|
|
450
|
+
<one-line summary of what was put in context>
|
|
451
|
+
|
|
452
|
+
### Specs Created (<N> total)
|
|
453
|
+
<list of specs/*/spec.md with one-line description each>
|
|
454
|
+
|
|
455
|
+
### Changes Created (<N> total)
|
|
456
|
+
<list of changes/*/proposal.md with source location each>
|
|
457
|
+
|
|
458
|
+
### Backlog
|
|
459
|
+
<N remaining items in changes/_backlog.md — review manually>
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## CLAUDE.md Optimization
|
|
464
|
+
|
|
465
|
+
### Token savings
|
|
466
|
+
Before: ~<N> tokens loaded per session (all referenced docs)
|
|
467
|
+
After: ~<N> tokens loaded per session (essential only)
|
|
468
|
+
Saved: ~<N> tokens per session
|
|
469
|
+
|
|
470
|
+
### References removed (<N> total)
|
|
471
|
+
| File | Classification | Reason |
|
|
472
|
+
|---|---|---|
|
|
473
|
+
| <path> | REDUNDANT_AFTER_MIGRATION | Covered by openspec/specs/<n>/spec.md |
|
|
474
|
+
| <path> | STALE | File does not exist on disk |
|
|
475
|
+
|
|
476
|
+
### Docs now covered by OpenSpec (safe to archive)
|
|
477
|
+
These files were removed from CLAUDE.md because their knowledge is now in OpenSpec.
|
|
478
|
+
The files themselves have NOT been deleted. You may archive or delete them at
|
|
479
|
+
your discretion once you have verified the corresponding specs are accurate.
|
|
480
|
+
|
|
481
|
+
| File | Was used for | Now covered by |
|
|
482
|
+
|---|---|---|
|
|
483
|
+
| <path> | <original purpose> | openspec/specs/<n>/spec.md |
|
|
484
|
+
|
|
485
|
+
Original CLAUDE.md backed up to: `CLAUDE.md.pre-migration`
|
|
486
|
+
|
|
487
|
+
---
|
|
488
|
+
|
|
489
|
+
## What Needs Human Review
|
|
490
|
+
|
|
491
|
+
1. **config.yaml** — Verify the `context:` block is accurate.
|
|
492
|
+
Check: architecture description, tech stack versions, key constraints.
|
|
493
|
+
|
|
494
|
+
2. **Architecture spec** — Verify patterns match your intent, not just current code.
|
|
495
|
+
|
|
496
|
+
3. **Feature specs** — Describe current behavior. Use OpenSpec changes for
|
|
497
|
+
anything that should change in the future.
|
|
498
|
+
|
|
499
|
+
4. **Changes from TODOs** — Some may be outdated or already fixed.
|
|
500
|
+
Review openspec/changes/ and delete irrelevant ones.
|
|
501
|
+
|
|
502
|
+
5. **CLAUDE.md** — Review the optimized version. Restore from
|
|
503
|
+
`CLAUDE.md.pre-migration` if anything essential was removed by mistake.
|
|
504
|
+
|
|
505
|
+
---
|
|
506
|
+
|
|
507
|
+
## Items NOT Migrated (require manual work)
|
|
508
|
+
|
|
509
|
+
<list anything the agents found but could not classify automatically>
|
|
510
|
+
|
|
511
|
+
---
|
|
512
|
+
|
|
513
|
+
## Suggested Next Steps
|
|
514
|
+
|
|
515
|
+
1. Review this report carefully, especially the CLAUDE.md optimization section
|
|
516
|
+
2. Run `/openspec-to-beads` — sync all OpenSpec changes to Beads issues
|
|
517
|
+
3. Run `/opsx:explore` — let Claude validate the migration made sense
|
|
518
|
+
4. Pick one change from openspec/changes/ and run `/opsx:apply <n>`
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
---
|
|
522
|
+
|
|
523
|
+
## Final Announcement
|
|
524
|
+
|
|
525
|
+
Tell the user:
|
|
526
|
+
|
|
527
|
+
> ✅ Migration complete! Here's what was done:
|
|
528
|
+
>
|
|
529
|
+
> - `openspec/config.yaml` — project context injected into every future spec
|
|
530
|
+
> - `openspec/specs/` — <N> architecture and feature specs
|
|
531
|
+
> - `openspec/changes/` — <N> active changes from TODOs/FIXMEs
|
|
532
|
+
> - `CLAUDE.md` — optimized: <N> redundant doc references removed (~<N> tokens saved per session)
|
|
533
|
+
> - `CLAUDE.md.pre-migration` — backup of original
|
|
534
|
+
> - `openspec/MIGRATION_REPORT.md` — full summary, token savings, docs to archive
|
|
535
|
+
>
|
|
536
|
+
> **Recommended next steps:**
|
|
537
|
+
> 1. Read `openspec/MIGRATION_REPORT.md`
|
|
538
|
+
> 2. Run `/openspec-to-beads` to sync changes → Beads issues
|
|
539
|
+
> 3. Run `/opsx:explore` to validate the baseline
|
|
540
|
+
|
|
541
|
+
---
|
|
542
|
+
|
|
543
|
+
## Error Handling
|
|
544
|
+
|
|
545
|
+
If any phase fails, do NOT stop the migration. Log the error to
|
|
546
|
+
`openspec/MIGRATION_REPORT.md` under a `## Errors` section and continue
|
|
547
|
+
with remaining phases. Partial output is better than no output.
|
|
548
|
+
|
|
549
|
+
If a scout agent returns empty or incomplete results, proceed with
|
|
550
|
+
whatever data is available and note the gap in the report.
|
|
551
|
+
|
|
552
|
+
**Phase 7 (CLAUDE.md) is the most sensitive phase** — it modifies a file
|
|
553
|
+
that affects every future Claude Code session. If anything goes wrong:
|
|
554
|
+
|
|
555
|
+
```bash
|
|
556
|
+
cp CLAUDE.md.pre-migration CLAUDE.md
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
Note the failure in the report and ask the user to optimize CLAUDE.md manually
|
|
560
|
+
using the `## CLAUDE_MD_AUDIT` section as a guide.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# Architecture Specification
|
|
2
|
+
# Auto-generated by /migrate-to-openspec — review for accuracy.
|
|
3
|
+
|
|
4
|
+
## Requirement: Folder Structure
|
|
5
|
+
The system SHALL maintain the established folder conventions.
|
|
6
|
+
|
|
7
|
+
### Scenario: New source file added
|
|
8
|
+
- GIVEN a developer adds a new source file
|
|
9
|
+
- WHEN placing it in the project
|
|
10
|
+
- THEN it SHALL be placed in the appropriate module folder
|
|
11
|
+
- AND it SHALL follow the naming convention established in existing files
|
|
12
|
+
|
|
13
|
+
## Requirement: Dependency Direction
|
|
14
|
+
The system SHALL enforce unidirectional dependencies between layers.
|
|
15
|
+
|
|
16
|
+
### Scenario: Cross-layer dependency
|
|
17
|
+
- GIVEN module A depends on module B
|
|
18
|
+
- WHEN B is in a lower layer than A
|
|
19
|
+
- THEN this dependency is valid
|
|
20
|
+
- AND the reverse dependency SHALL NOT exist
|
|
21
|
+
|
|
22
|
+
## Requirement: Tech Stack Stability
|
|
23
|
+
The system SHALL not introduce new languages, runtimes, or major frameworks
|
|
24
|
+
without an explicit architectural decision.
|
|
25
|
+
|
|
26
|
+
### Scenario: Adding a new tool
|
|
27
|
+
- GIVEN a new tool is proposed
|
|
28
|
+
- WHEN evaluating it
|
|
29
|
+
- THEN a proposal MUST be created in openspec/changes/
|
|
30
|
+
- AND alternatives MUST be documented
|
|
31
|
+
|
|
32
|
+
## Requirement: Naming Conventions
|
|
33
|
+
The system SHALL follow established naming patterns throughout the codebase.
|
|
34
|
+
|
|
35
|
+
### Scenario: Naming a new type
|
|
36
|
+
- GIVEN a developer creates a new class, file, or component
|
|
37
|
+
- WHEN choosing its name
|
|
38
|
+
- THEN it SHALL follow the convention established in similar existing types
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Feature Spec: <Feature Name>
|
|
2
|
+
# Auto-generated by /migrate-to-openspec — review for accuracy.
|
|
3
|
+
#
|
|
4
|
+
# Status at time of migration: <COMPLETE | IN_PROGRESS | PARTIAL>
|
|
5
|
+
# Key files: <list main files for this feature>
|
|
6
|
+
|
|
7
|
+
## Requirement: Core Behavior
|
|
8
|
+
The system SHALL <describe what this feature does at a high level>.
|
|
9
|
+
|
|
10
|
+
### Scenario: Happy path
|
|
11
|
+
- GIVEN <initial state>
|
|
12
|
+
- WHEN <trigger>
|
|
13
|
+
- THEN <expected outcome>
|
|
14
|
+
- AND <additional outcome>
|
|
15
|
+
|
|
16
|
+
### Scenario: Error case
|
|
17
|
+
- GIVEN <state where error can occur>
|
|
18
|
+
- WHEN <trigger>
|
|
19
|
+
- THEN <error is handled gracefully>
|
|
20
|
+
- AND <system returns to stable state>
|
|
21
|
+
|
|
22
|
+
## Requirement: <Second Requirement>
|
|
23
|
+
The system SHALL <describe second requirement>.
|
|
24
|
+
|
|
25
|
+
### Scenario: <Name>
|
|
26
|
+
- GIVEN ...
|
|
27
|
+
- WHEN ...
|
|
28
|
+
- THEN ...
|
|
29
|
+
|
|
30
|
+
## Requirement: Performance
|
|
31
|
+
The system SHALL complete <operation> within <N>ms under normal load.
|
|
32
|
+
|
|
33
|
+
### Scenario: Acceptable load
|
|
34
|
+
- GIVEN <N> concurrent <operations>
|
|
35
|
+
- WHEN <trigger>
|
|
36
|
+
- THEN response time SHALL be under <N>ms
|
|
37
|
+
|
|
38
|
+
## Notes
|
|
39
|
+
- <Any caveats, known limitations, or implementation notes discovered during migration>
|
|
40
|
+
- <References to related specs>
|
package/src/index.js
ADDED
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// openspec-stack-init — cross-platform initializer for:
|
|
4
|
+
// OpenSpec + Beads + claude-mem + openspec-to-beads skill + brownfield-baseline skill
|
|
5
|
+
//
|
|
6
|
+
// Usage:
|
|
7
|
+
// npx openspec-stack-init — current directory
|
|
8
|
+
// npx openspec-stack-init ./my-project — specific path
|
|
9
|
+
// npx openspec-stack-init --dry-run — preview without executing
|
|
10
|
+
|
|
11
|
+
import { execSync, spawnSync } from "child_process";
|
|
12
|
+
import { existsSync, mkdirSync, writeFileSync, appendFileSync, readFileSync } from "fs";
|
|
13
|
+
import { resolve, basename, join } from "path";
|
|
14
|
+
import { platform } from "os";
|
|
15
|
+
import process from "process";
|
|
16
|
+
|
|
17
|
+
// ─── Minimal inline styling (avoids requiring chalk to be pre-installed) ─────
|
|
18
|
+
const c = {
|
|
19
|
+
reset: "\x1b[0m",
|
|
20
|
+
bold: "\x1b[1m",
|
|
21
|
+
red: "\x1b[31m",
|
|
22
|
+
green: "\x1b[32m",
|
|
23
|
+
yellow: "\x1b[33m",
|
|
24
|
+
blue: "\x1b[34m",
|
|
25
|
+
cyan: "\x1b[36m",
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const log = {
|
|
29
|
+
info: (msg) => console.log(`${c.blue}[INFO]${c.reset} ${msg}`),
|
|
30
|
+
ok: (msg) => console.log(`${c.green}[ OK ]${c.reset} ${msg}`),
|
|
31
|
+
warn: (msg) => console.log(`${c.yellow}[WARN]${c.reset} ${msg}`),
|
|
32
|
+
skip: (msg) => console.log(`${c.yellow}[SKIP]${c.reset} ${msg}`),
|
|
33
|
+
error: (msg) => console.error(`${c.red}[ERR ]${c.reset} ${msg}`),
|
|
34
|
+
step: (msg) => console.log(`\n${c.bold}${c.cyan}══> ${msg}${c.reset}`),
|
|
35
|
+
section: (msg) => console.log(`${c.bold}${msg}${c.reset}`),
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
// ─── Args ────────────────────────────────────────────────────────────────────
|
|
39
|
+
const args = process.argv.slice(2);
|
|
40
|
+
const DRY_RUN = args.includes("--dry-run") || args.includes("-n");
|
|
41
|
+
const targetArg = args.find((a) => !a.startsWith("--") && !a.startsWith("-"));
|
|
42
|
+
const TARGET_DIR = resolve(targetArg || process.cwd());
|
|
43
|
+
const PROJECT_NAME = basename(TARGET_DIR);
|
|
44
|
+
const IS_WINDOWS = platform() === "win32";
|
|
45
|
+
|
|
46
|
+
// ─── Utilities ───────────────────────────────────────────────────────────────
|
|
47
|
+
|
|
48
|
+
/** Run a shell command, return true on success */
|
|
49
|
+
function run(cmd, opts = {}) {
|
|
50
|
+
if (DRY_RUN) {
|
|
51
|
+
log.info(`[DRY RUN] ${cmd}`);
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
try {
|
|
55
|
+
execSync(cmd, {
|
|
56
|
+
cwd: TARGET_DIR,
|
|
57
|
+
stdio: opts.silent ? "pipe" : "inherit",
|
|
58
|
+
shell: true,
|
|
59
|
+
...opts,
|
|
60
|
+
});
|
|
61
|
+
return true;
|
|
62
|
+
} catch (e) {
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Check if a CLI tool is available in PATH */
|
|
68
|
+
function hasCmd(cmd) {
|
|
69
|
+
const check = IS_WINDOWS ? `where ${cmd}` : `command -v ${cmd}`;
|
|
70
|
+
try {
|
|
71
|
+
execSync(check, { stdio: "pipe", shell: true });
|
|
72
|
+
return true;
|
|
73
|
+
} catch {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/** Write file only if it doesn't exist (or DRY_RUN) */
|
|
79
|
+
function writeIfMissing(filePath, content, description) {
|
|
80
|
+
const full = join(TARGET_DIR, filePath);
|
|
81
|
+
if (existsSync(full)) {
|
|
82
|
+
log.skip(`${filePath} already exists`);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (DRY_RUN) {
|
|
86
|
+
log.info(`[DRY RUN] Would create: ${filePath}`);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
mkdirSync(join(TARGET_DIR, filePath.split("/").slice(0, -1).join("/")), { recursive: true });
|
|
90
|
+
writeFileSync(full, content, "utf8");
|
|
91
|
+
log.ok(`Created ${filePath}${description ? ` — ${description}` : ""}`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Append to .gitignore if entry is missing */
|
|
95
|
+
function gitignoreAdd(entry, comment) {
|
|
96
|
+
const gitignorePath = join(TARGET_DIR, ".gitignore");
|
|
97
|
+
if (!existsSync(gitignorePath)) {
|
|
98
|
+
if (!DRY_RUN) writeFileSync(gitignorePath, "", "utf8");
|
|
99
|
+
}
|
|
100
|
+
const content = existsSync(gitignorePath) ? readFileSync(gitignorePath, "utf8") : "";
|
|
101
|
+
if (content.includes(entry)) return;
|
|
102
|
+
if (DRY_RUN) {
|
|
103
|
+
log.info(`[DRY RUN] Would add to .gitignore: ${entry}`);
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
appendFileSync(gitignorePath, `\n# ${comment}\n${entry}\n`, "utf8");
|
|
107
|
+
log.info(` .gitignore ← ${entry}`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ─── Banner ───────────────────────────────────────────────────────────────────
|
|
111
|
+
console.log(`
|
|
112
|
+
${c.bold}╔══════════════════════════════════════════╗
|
|
113
|
+
║ AI Stack Init v1.0 ║
|
|
114
|
+
║ OpenSpec + Beads + claude-mem + skills ║
|
|
115
|
+
╚══════════════════════════════════════════╝${c.reset}
|
|
116
|
+
Project : ${c.cyan}${PROJECT_NAME}${c.reset}
|
|
117
|
+
Path : ${c.cyan}${TARGET_DIR}${c.reset}
|
|
118
|
+
Mode : ${DRY_RUN ? c.yellow + "DRY RUN (no changes)" + c.reset : c.green + "LIVE" + c.reset}
|
|
119
|
+
`);
|
|
120
|
+
|
|
121
|
+
if (!existsSync(TARGET_DIR)) {
|
|
122
|
+
log.error(`Directory not found: ${TARGET_DIR}`);
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// ─── 1. Dependency check ──────────────────────────────────────────────────────
|
|
127
|
+
log.step("Checking required tools");
|
|
128
|
+
|
|
129
|
+
const deps = [
|
|
130
|
+
{ cmd: "openspec", install: "npm install -g @fission-ai/openspec@latest" },
|
|
131
|
+
{ cmd: "bd", install: "brew install beads OR go install github.com/steveyegge/beads/cmd/bd@latest" },
|
|
132
|
+
{ cmd: "claude", install: "npm install -g @anthropic-ai/claude-code" },
|
|
133
|
+
{ cmd: "npx", install: "Node.js (https://nodejs.org)" },
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
let missing = false;
|
|
137
|
+
for (const { cmd, install } of deps) {
|
|
138
|
+
if (hasCmd(cmd)) {
|
|
139
|
+
log.ok(cmd);
|
|
140
|
+
} else {
|
|
141
|
+
log.warn(`${cmd} not found — install: ${install}`);
|
|
142
|
+
missing = true;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (missing && !DRY_RUN) {
|
|
147
|
+
console.log();
|
|
148
|
+
log.warn("Some tools are missing. Continuing anyway — affected steps will be skipped.");
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// ─── 2. OpenSpec init ─────────────────────────────────────────────────────────
|
|
152
|
+
log.step("OpenSpec — init");
|
|
153
|
+
|
|
154
|
+
if (existsSync(join(TARGET_DIR, "openspec"))) {
|
|
155
|
+
log.skip("openspec/ already exists");
|
|
156
|
+
} else if (hasCmd("openspec")) {
|
|
157
|
+
// --tools claude : select Claude Code without interactive prompt
|
|
158
|
+
// --profile expanded: enable all workflow commands (new, ff, verify, sync, etc.)
|
|
159
|
+
// --force : skip all remaining prompts, auto-cleanup legacy files
|
|
160
|
+
const ok = run("openspec init --tools claude --profile expanded --force");
|
|
161
|
+
if (ok) {
|
|
162
|
+
log.ok("OpenSpec initialized (expanded profile, Claude tools)");
|
|
163
|
+
} else {
|
|
164
|
+
// Fallback: openspec init may not support --force on older versions
|
|
165
|
+
log.warn("Non-interactive init failed — trying interactive...");
|
|
166
|
+
log.warn("Run manually: openspec init --tools claude --profile expanded");
|
|
167
|
+
}
|
|
168
|
+
} else {
|
|
169
|
+
log.warn("openspec not found — skipping");
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ─── 3. OpenSpec config.yaml ──────────────────────────────────────────────────
|
|
173
|
+
log.step("OpenSpec — config.yaml");
|
|
174
|
+
|
|
175
|
+
writeIfMissing(
|
|
176
|
+
"openspec/config.yaml",
|
|
177
|
+
`# OpenSpec Project Config — ${PROJECT_NAME}
|
|
178
|
+
# This context is injected into every artifact (proposal, specs, design, tasks)
|
|
179
|
+
|
|
180
|
+
schema: spec-driven
|
|
181
|
+
|
|
182
|
+
context: |
|
|
183
|
+
Project: ${PROJECT_NAME}
|
|
184
|
+
|
|
185
|
+
# TODO: fill in your actual stack and conventions
|
|
186
|
+
# Tech stack: Unity 2022, C#, Flutter backend
|
|
187
|
+
# Architecture: HMVC
|
|
188
|
+
# Testing: NUnit
|
|
189
|
+
# Key constraints: legacy codebase, brownfield migration
|
|
190
|
+
|
|
191
|
+
rules:
|
|
192
|
+
proposal:
|
|
193
|
+
- Always include a rollback plan for legacy code changes
|
|
194
|
+
- List all affected modules
|
|
195
|
+
specs:
|
|
196
|
+
- Use Given/When/Then format for scenarios
|
|
197
|
+
design:
|
|
198
|
+
- Respect existing legacy constraints
|
|
199
|
+
tasks:
|
|
200
|
+
- Keep tasks atomic (max 2-3 files per task)
|
|
201
|
+
- After all tasks complete, run /opsx:verify
|
|
202
|
+
`,
|
|
203
|
+
"fill in 'context' with your project details"
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
// ─── 4. Beads init ────────────────────────────────────────────────────────────
|
|
207
|
+
log.step("Beads — init");
|
|
208
|
+
|
|
209
|
+
const beadsInitialized =
|
|
210
|
+
existsSync(join(TARGET_DIR, ".beads")) ||
|
|
211
|
+
existsSync(join(TARGET_DIR, "beads.jsonl")) ||
|
|
212
|
+
existsSync(join(TARGET_DIR, "issues.jsonl"));
|
|
213
|
+
|
|
214
|
+
if (beadsInitialized) {
|
|
215
|
+
log.skip("Beads already initialized");
|
|
216
|
+
} else if (hasCmd("bd")) {
|
|
217
|
+
// --quiet: non-interactive, no prompts, no spinner
|
|
218
|
+
const ok = run("bd init --quiet");
|
|
219
|
+
if (ok) log.ok("Beads initialized (quiet mode)");
|
|
220
|
+
else log.warn("bd init failed — run manually: bd init --quiet");
|
|
221
|
+
} else {
|
|
222
|
+
log.warn("bd not found — skipping Beads init");
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// bd setup claude: installs SessionStart + PreCompact hooks for Claude Code
|
|
226
|
+
// This is idempotent — safe to run even if already set up
|
|
227
|
+
log.step("Beads — Claude Code integration");
|
|
228
|
+
|
|
229
|
+
if (hasCmd("bd")) {
|
|
230
|
+
const ok = run("bd setup claude");
|
|
231
|
+
if (ok) log.ok("Beads hooks installed for Claude Code (SessionStart + PreCompact)");
|
|
232
|
+
else log.warn("bd setup claude failed — run manually: bd setup claude");
|
|
233
|
+
} else {
|
|
234
|
+
log.warn("bd not found — skipping Claude Code integration");
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// ─── 5. claude-mem plugin ─────────────────────────────────────────────────────
|
|
238
|
+
log.step("claude-mem — plugin install");
|
|
239
|
+
|
|
240
|
+
// claude plugin marketplace add / install are native CLI commands in Claude Code 2.x
|
|
241
|
+
// They work without entering the REPL (confirmed in official docs)
|
|
242
|
+
if (hasCmd("claude")) {
|
|
243
|
+
log.info("Adding marketplace: thedotmack/claude-mem");
|
|
244
|
+
// marketplace add is idempotent — if already added, it updates
|
|
245
|
+
run("claude plugin marketplace add thedotmack/claude-mem", { silent: true });
|
|
246
|
+
|
|
247
|
+
log.info("Installing plugin: claude-mem");
|
|
248
|
+
const ok = run("claude plugin install claude-mem", { silent: true });
|
|
249
|
+
|
|
250
|
+
if (ok) {
|
|
251
|
+
log.ok("claude-mem installed via native claude plugin CLI");
|
|
252
|
+
} else {
|
|
253
|
+
log.warn("claude plugin CLI failed. Install manually inside Claude Code:");
|
|
254
|
+
log.warn(" /plugin marketplace add thedotmack/claude-mem");
|
|
255
|
+
log.warn(" /plugin install claude-mem");
|
|
256
|
+
}
|
|
257
|
+
} else {
|
|
258
|
+
log.warn("claude not found — install claude-mem manually:");
|
|
259
|
+
log.warn(" /plugin marketplace add thedotmack/claude-mem");
|
|
260
|
+
log.warn(" /plugin install claude-mem");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// ─── 6. Skill: openspec-to-beads ─────────────────────────────────────────────
|
|
264
|
+
log.step("Skill — openspec-to-beads");
|
|
265
|
+
|
|
266
|
+
// npx @smithery/cli skill add is non-interactive
|
|
267
|
+
const smitheryOk = run(
|
|
268
|
+
"npx @smithery/cli@latest skill add lucastamoios/openspec-to-beads --agent claude-code"
|
|
269
|
+
);
|
|
270
|
+
if (smitheryOk) {
|
|
271
|
+
log.ok("Skill openspec-to-beads installed");
|
|
272
|
+
} else {
|
|
273
|
+
log.warn("Skill install failed — run manually:");
|
|
274
|
+
log.warn(" npx @smithery/cli@latest skill add lucastamoios/openspec-to-beads --agent claude-code");
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// ─── 7. Skill: migrate-to-openspec ───────────────────────────────────────────
|
|
278
|
+
log.step("Skill — /migrate-to-openspec (brownfield migration)");
|
|
279
|
+
|
|
280
|
+
// The skill files are bundled alongside this script in ../skills/
|
|
281
|
+
import { fileURLToPath } from "url";
|
|
282
|
+
import { dirname, join as pathJoin } from "path";
|
|
283
|
+
import { cpSync } from "fs";
|
|
284
|
+
|
|
285
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
286
|
+
const __dirname = dirname(__filename);
|
|
287
|
+
const skillSrc = pathJoin(__dirname, "..", "skills", "migrate-to-openspec");
|
|
288
|
+
const skillDst = join(TARGET_DIR, ".claude", "skills", "migrate-to-openspec");
|
|
289
|
+
|
|
290
|
+
if (existsSync(skillDst)) {
|
|
291
|
+
log.skip(".claude/skills/migrate-to-openspec/ already exists");
|
|
292
|
+
} else if (existsSync(skillSrc)) {
|
|
293
|
+
if (!DRY_RUN) {
|
|
294
|
+
mkdirSync(join(TARGET_DIR, ".claude", "skills"), { recursive: true });
|
|
295
|
+
cpSync(skillSrc, skillDst, { recursive: true });
|
|
296
|
+
log.ok("Skill /migrate-to-openspec installed → .claude/skills/migrate-to-openspec/");
|
|
297
|
+
} else {
|
|
298
|
+
log.info("[DRY RUN] Would install: .claude/skills/migrate-to-openspec/");
|
|
299
|
+
}
|
|
300
|
+
} else {
|
|
301
|
+
log.warn("Skill source not found — skipping migrate-to-openspec");
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
log.info(" Usage: run /migrate-to-openspec in Claude Code on a brownfield project");
|
|
305
|
+
log.info(" This skill uses 4 parallel scout agents + writes all OpenSpec files automatically");
|
|
306
|
+
|
|
307
|
+
// ─── 8. .gitignore ────────────────────────────────────────────────────────────
|
|
308
|
+
log.step("Updating .gitignore");
|
|
309
|
+
|
|
310
|
+
// NOTE: beads.jsonl and issues.jsonl are intentionally committed to git (that's the feature)
|
|
311
|
+
// Only ignore local SQLite cache and claude-mem local data
|
|
312
|
+
gitignoreAdd(".beads-cache/", "Beads local SQLite cache (not needed in git)");
|
|
313
|
+
gitignoreAdd(".claude-mem/", "claude-mem local session data");
|
|
314
|
+
|
|
315
|
+
log.ok(".gitignore updated");
|
|
316
|
+
|
|
317
|
+
// ─── 9. Summary ───────────────────────────────────────────────────────────────
|
|
318
|
+
console.log(`
|
|
319
|
+
${c.bold}${c.green}╔══════════════════════════════════════════╗
|
|
320
|
+
║ Setup Complete! ║
|
|
321
|
+
╚══════════════════════════════════════════╝${c.reset}
|
|
322
|
+
|
|
323
|
+
${c.bold}What was done:${c.reset}
|
|
324
|
+
${c.green}✓${c.reset} OpenSpec → openspec/ + expanded profile + Claude tools
|
|
325
|
+
${c.green}✓${c.reset} openspec/config.yaml → auto-filled by /migrate-to-openspec
|
|
326
|
+
${c.green}✓${c.reset} Beads → initialized (--quiet) + Claude Code hooks
|
|
327
|
+
${c.green}✓${c.reset} claude-mem → plugin installed via native claude CLI
|
|
328
|
+
${c.green}✓${c.reset} openspec-to-beads → skill installed via Smithery
|
|
329
|
+
${c.green}✓${c.reset} /migrate-to-openspec → .claude/skills/migrate-to-openspec/
|
|
330
|
+
|
|
331
|
+
${c.bold}Next steps — ${c.cyan}BROWNFIELD${c.reset} project:${c.reset}
|
|
332
|
+
1. Restart Claude Code
|
|
333
|
+
2. ${c.cyan}/migrate-to-openspec${c.reset} — scans project + fills all OpenSpec files automatically
|
|
334
|
+
3. Review ${c.cyan}openspec/MIGRATION_REPORT.md${c.reset}
|
|
335
|
+
4. ${c.cyan}bd ready${c.reset} — see task list in Beads
|
|
336
|
+
|
|
337
|
+
${c.bold}Next steps — ${c.cyan}GREENFIELD${c.reset} project:${c.reset}
|
|
338
|
+
1. Edit ${c.cyan}openspec/config.yaml${c.reset} — describe your planned stack
|
|
339
|
+
2. Restart Claude Code
|
|
340
|
+
3. ${c.cyan}/opsx:propose <feature>${c.reset} — start first feature
|
|
341
|
+
|
|
342
|
+
${c.bold}Key commands:${c.reset}
|
|
343
|
+
${c.cyan}bd ready${c.reset} unblocked tasks right now
|
|
344
|
+
${c.cyan}bd create "..."${c.reset} create a Beads issue
|
|
345
|
+
${c.cyan}openspec list${c.reset} active OpenSpec changes
|
|
346
|
+
${c.cyan}/opsx:explore${c.reset} explore codebase
|
|
347
|
+
${c.cyan}/opsx:new <name>${c.reset} new change
|
|
348
|
+
${c.cyan}/opsx:ff${c.reset} generate all artifacts at once
|
|
349
|
+
${c.cyan}/opsx:apply${c.reset} implement tasks
|
|
350
|
+
${c.cyan}/opsx:verify${c.reset} verify implementation vs specs
|
|
351
|
+
${c.cyan}/opsx:archive${c.reset} archive change → specs/
|
|
352
|
+
`);
|