@panuwatbas/spec-driven-dev 1.0.2

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,378 @@
1
+ # Spec-Driven Development Skill
2
+
3
+ > **Plan first, then build.** สร้าง Requirements → Design → Tasks ก่อน แล้วค่อย Code
4
+
5
+ Skill เป็น workflow ที่เน้นการวางแผนอย่างเป็นระบบ
6
+ ก่อนเขียน code ทุกครั้ง ลดความผิดพลาด ลดการทำซ้ำ และสร้าง documentation
7
+
8
+ ---
9
+
10
+ ## Features
11
+
12
+ - **Structured Planning** — 3 เฟสชัดเจน: Requirements → Design → Tasks
13
+ - **GIVEN/WHEN/THEN** — Acceptance criteria แบบ Gherkin ที่ทดสอบได้
14
+ - **Mermaid Diagrams** — Architecture และ Sequence diagrams อัตโนมัติ
15
+ - **Traceability** — ทุก task อ้างอิงกลับไปหา requirement
16
+ - **Progress Tracking** — `[ ]` `[/]` `[x]` สำหรับ track progress
17
+ - **Human-in-the-Loop** — ต้อง approve ก่อนไปเฟสถัดไป
18
+ - **3 Workflow Variants** — Requirements-First, Design-First, Bugfix Mode
19
+ - **Agent-Compatible** — ใช้ได้กับ AI agent ทุกตัว
20
+
21
+ ---
22
+
23
+ ## โครงสร้าง Skill
24
+
25
+ ```
26
+ spec-driven-dev/
27
+ ├── SKILL.md # คำสั่งหลัก (AI Agent อ่านไฟล์นี้)
28
+ ├── README.md # คู่มือนี้
29
+ ├── templates/
30
+ │ ├── requirements.template.md # เทมเพลต: กำหนดว่า "ทำอะไร"
31
+ │ ├── design.template.md # เทมเพลต: กำหนดว่า "ทำยังไง"
32
+ │ └── tasks.template.md # เทมเพลต: แผนการทำงาน
33
+ ├── examples/
34
+ │ ├── example-requirements.md # ตัวอย่าง: Shopping Cart requirements
35
+ │ ├── example-design.md # ตัวอย่าง: Shopping Cart design
36
+ │ └── example-tasks.md # ตัวอย่าง: Shopping Cart tasks
37
+ └── scripts/
38
+ ├── init-spec.sh # Script สร้าง spec ใหม่ (Linux/Mac)
39
+ └── init-spec.bat # Script สร้าง spec ใหม่ (Windows)
40
+ ```
41
+
42
+ ---
43
+
44
+ ## การติดตั้ง
45
+
46
+ ### วิธีที่ 1: ติดตั้งผ่าน npx (แนะนำ)
47
+
48
+ รันคำสั่งเดียวที่ root ของ project:
49
+
50
+ ```bash
51
+ npx spec-driven-dev
52
+ ```
53
+
54
+ ระบบจะถามว่าต้องการติดตั้งลง IDE ตัวไหน แล้วคัดลอกไฟล์ให้อัตโนมัติ
55
+
56
+ ถ้าต้องการระบุ IDE เลย ใช้ `--target`:
57
+
58
+ ```bash
59
+ # ติดตั้งลง Gemini CLI / Antigravity
60
+ npx spec-driven-dev --target gemini
61
+
62
+ # ติดตั้งลง Cursor
63
+ npx spec-driven-dev --target cursor
64
+
65
+ # ติดตั้งลง Windsurf
66
+ npx spec-driven-dev --target windsurf
67
+
68
+ # ติดตั้งลง GitHub Copilot
69
+ npx spec-driven-dev --target copilot
70
+
71
+ # ติดตั้งลง path ที่กำหนดเอง
72
+ npx spec-driven-dev --target ./my-custom-path
73
+ ```
74
+
75
+ สร้าง spec ใหม่สำหรับ feature:
76
+
77
+ ```bash
78
+ npx spec-driven-dev --init user-authentication
79
+ ```
80
+
81
+ ---
82
+
83
+ ### วิธีที่ 2: คัดลอกด้วยตัวเอง
84
+
85
+ คัดลอกโฟลเดอร์ `spec-driven-dev` ไปวางในโฟลเดอร์ skills ของเครื่องมือที่ใช้:
86
+
87
+ ```powershell
88
+ # Gemini CLI / Antigravity
89
+ Copy-Item -Recurse "spec-driven-dev" ".gemini\skills\spec-driven-dev"
90
+
91
+ # Cursor
92
+ Copy-Item -Recurse "spec-driven-dev" ".cursor\skills\spec-driven-dev"
93
+
94
+ # Windsurf
95
+ Copy-Item -Recurse "spec-driven-dev" ".windsurf\skills\spec-driven-dev"
96
+ ```
97
+
98
+ ### เครื่องมืออื่นๆ
99
+
100
+ ชี้ให้ AI agent อ่านไฟล์ `SKILL.md` โดยตรง หรือ copy เนื้อหาเข้า system prompt
101
+
102
+ ---
103
+
104
+ ## วิธีใช้งาน
105
+
106
+ ### วิธีที่ 1: บอก AI Agent โดยตรง
107
+
108
+ พิมพ์ประโยคแบบนี้ใน chat:
109
+
110
+ ```
111
+ สร้าง spec สำหรับ feature ระบบ login
112
+ ```
113
+
114
+ ```
115
+ ช่วย spec feature ตะกร้าสินค้า ตาม spec-driven-dev skill
116
+ ```
117
+
118
+ ```
119
+ Start a spec for user-authentication using the spec-driven-dev skill
120
+ ```
121
+
122
+ Agent จะเริ่มทำตาม workflow 3 เฟสอัตโนมัติ
123
+
124
+ ---
125
+
126
+ ### วิธีที่ 2: ใช้ Script สร้างโครงสร้างก่อน
127
+
128
+ ```powershell
129
+ # Windows
130
+ .\scripts\init-spec.bat user-authentication
131
+
132
+ # Linux / Mac
133
+ bash scripts/init-spec.sh user-authentication
134
+ ```
135
+
136
+ จะได้โครงสร้าง:
137
+
138
+ ```
139
+ .specs/user-authentication/
140
+ ├── requirements.md <- เทมเพลตพร้อมแก้ไข
141
+ ├── design.md <- เทมเพลตพร้อมแก้ไข
142
+ └── tasks.md <- เทมเพลตพร้อมแก้ไข
143
+ ```
144
+
145
+ แล้วบอก agent: `"ช่วยเติม spec ใน .specs/user-authentication/"`
146
+
147
+ ---
148
+
149
+ ## Workflow 3 เฟส
150
+
151
+ ```
152
+ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
153
+ │ Phase 1 │ │ Phase 2 │ │ Phase 3 │
154
+ │ REQUIREMENTS │ --> │ DESIGN │ --> │ TASKS │
155
+ │ │ │ │ │ │
156
+ │ กำหนดว่า │ │ กำหนดว่า │ │ แผนการทำงาน │
157
+ │ "ทำอะไร" │ │ "ทำยังไง" │ │ ทีละขั้นตอน │
158
+ │ │ │ │ │ │
159
+ │ - User Stories │ │ - Architecture │ │ - Task List │
160
+ │ - GIVEN/WHEN/ │ │ - Components │ │ - Phases │
161
+ │ THEN │ │ - Data Models │ │ - Verification │
162
+ │ - Edge Cases │ │ - API Contracts│ │ - Status [x] │
163
+ └────────┬────────┘ └────────┬────────┘ └────────┬────────┘
164
+ │ │ │
165
+ คุณ approve คุณ approve คุณ approve
166
+
167
+ เริ่ม code!
168
+ ```
169
+
170
+ ### เฟส 1 — Requirements (`requirements.md`)
171
+
172
+ กำหนด **"ทำอะไร"** จากมุมมองผู้ใช้
173
+
174
+ ```markdown
175
+ # Feature: ระบบ Login
176
+
177
+ ## User Story
178
+ **As a** ผู้ใช้ทั่วไป,
179
+ **I want to** เข้าสู่ระบบด้วย email และ password,
180
+ **so that** ฉันสามารถเข้าถึงข้อมูลส่วนตัวของฉันได้.
181
+
182
+ ## Acceptance Criteria
183
+
184
+ ### AC-1.1: เข้าสู่ระบบสำเร็จ
185
+ **Given** ผู้ใช้อยู่ที่หน้า login
186
+ **And** มีบัญชีอยู่แล้วในระบบ
187
+ **When** กรอก email และ password ที่ถูกต้อง แล้วกดปุ่ม "Login"
188
+ **Then** ระบบพาไปหน้า dashboard
189
+ **And** แสดงชื่อผู้ใช้ที่มุมบนขวา
190
+
191
+ ### AC-1.2: กรอก password ผิด
192
+ **Given** ผู้ใช้อยู่ที่หน้า login
193
+ **When** กรอก email ถูกต้อง แต่ password ผิด
194
+ **Then** แสดงข้อความ "อีเมลหรือรหัสผ่านไม่ถูกต้อง"
195
+ **And** ไม่บอกว่าผิดอันไหน (เพื่อความปลอดภัย)
196
+ ```
197
+
198
+ **คุณรีวิว -> แก้ไข -> approve** -> ไปเฟส 2
199
+
200
+ ---
201
+
202
+ ### เฟส 2 — Design (`design.md`)
203
+
204
+ กำหนด **"ทำยังไง"** ในเชิงเทคนิค
205
+
206
+ ```markdown
207
+ ## Architecture
208
+ ┌──────────┐ ┌──────────┐ ┌──────────┐
209
+ │ React │ --> │ Express │ --> │ Postgres │
210
+ │ Frontend│ │ API │ │ Database │
211
+ └──────────┘ └──────────┘ └──────────┘
212
+
213
+ ## Component: AuthService
214
+ - Responsibility: จัดการ login, logout, token refresh
215
+ - Location: src/server/services/AuthService.ts
216
+
217
+ ## API Contract
218
+ POST /api/auth/login
219
+ Request: { "email": "string", "password": "string" }
220
+ Response: { "token": "jwt", "user": { "id", "name" } }
221
+ ```
222
+
223
+ **คุณรีวิว -> แก้ไข -> approve** -> ไปเฟส 3
224
+
225
+ ---
226
+
227
+ ### เฟส 3 — Tasks (`tasks.md`)
228
+
229
+ แผนการทำงานเป็น **checklist**
230
+
231
+ ```markdown
232
+ ## Phase 1: Database
233
+ - [x] Task 1.1: สร้าง users table migration
234
+ - [x] Task 1.2: สร้าง User model
235
+
236
+ ## Phase 2: Backend API
237
+ - [/] Task 2.1: สร้าง POST /api/auth/login <- กำลังทำ
238
+ - [ ] Task 2.2: สร้าง JWT middleware
239
+ - [ ] Task 2.3: สร้าง rate limiting
240
+
241
+ ## Phase 3: Frontend
242
+ - [ ] Task 3.1: สร้าง LoginForm component
243
+ - [ ] Task 3.2: สร้าง auth context/store
244
+ - [ ] Task 3.3: สร้าง protected route
245
+
246
+ ## Phase 4: Testing
247
+ - [ ] Task 4.1: Unit tests สำหรับ AuthService
248
+ - [ ] Task 4.2: E2E test login flow
249
+ ```
250
+
251
+ **คุณ approve -> Agent เริ่ม code ทีละ task**
252
+
253
+ ---
254
+
255
+ ## Workflow Variants
256
+
257
+ ### 1. Requirements-First (ค่าเริ่มต้น)
258
+
259
+ เหมาะกับ **feature ใหม่** ที่เน้น business logic
260
+
261
+ ```
262
+ requirements.md -> design.md -> tasks.md
263
+ ```
264
+
265
+ **ใช้เมื่อ:** สร้างฟีเจอร์ใหม่ตั้งแต่ต้น
266
+
267
+ ---
268
+
269
+ ### 2. Design-First
270
+
271
+ เหมาะกับ **ระบบซับซ้อน** ที่มีข้อจำกัดทางเทคนิค
272
+
273
+ ```
274
+ design.md -> requirements.md (derived) -> tasks.md
275
+ ```
276
+
277
+ **ใช้เมื่อ:** มี architecture constraints, performance requirements, หรือต้อง integrate กับระบบเดิม
278
+
279
+ ---
280
+
281
+ ### 3. Bugfix Mode
282
+
283
+ เหมาะกับ **bug ที่ซับซ้อน** ต้องวิเคราะห์ root cause
284
+
285
+ ```
286
+ bugfix.md -> design.md (root cause + fix) -> tasks.md
287
+ ```
288
+
289
+ **ใช้เมื่อ:** Bug ที่ reproduce ยาก หรือเกี่ยวข้องหลาย component
290
+
291
+ ---
292
+
293
+ ## ตัวอย่างคำสั่งสำหรับ AI Agent
294
+
295
+ | สถานการณ์ | พูดกับ Agent ว่า |
296
+ |----------|-----------------|
297
+ | เริ่ม feature ใหม่ | `"สร้าง spec สำหรับ feature [ชื่อ]"` |
298
+ | Fix bug ซับซ้อน | `"สร้าง bugfix spec สำหรับ [ปัญหา]"` |
299
+ | มี design อยู่แล้ว | `"เริ่มจาก design-first สำหรับ [ชื่อ]"` |
300
+ | Approve เฟส | `"approve แล้ว ไปเฟสถัดไป"` |
301
+ | เริ่ม code | `"approve tasks แล้ว เริ่ม execute ได้เลย"` |
302
+ | แก้ requirement | `"แก้ AC-1.2 เป็น... แล้ว sync ลง tasks"` |
303
+ | ดูตัวอย่าง | `"ดูตัวอย่าง requirements จาก examples"` |
304
+ | สร้างจากเทมเพลต | `"สร้าง requirements จาก template"` |
305
+
306
+ ---
307
+
308
+ ## Output ที่ได้
309
+
310
+ เมื่อใช้ skill นี้กับ project จะได้โครงสร้าง:
311
+
312
+ ```
313
+ your-project/
314
+ ├── .specs/
315
+ │ ├── user-authentication/
316
+ │ │ ├── requirements.md <- Approved
317
+ │ │ ├── design.md <- Approved
318
+ │ │ └── tasks.md <- In Progress (12/15 tasks done)
319
+ │ │
320
+ │ ├── shopping-cart/
321
+ │ │ ├── requirements.md <- Approved
322
+ │ │ ├── design.md <- Draft
323
+ │ │ └── tasks.md <- Not Started
324
+ │ │
325
+ │ └── payment-integration/
326
+ │ └── requirements.md <- Draft
327
+
328
+ ├── src/
329
+ │ └── ... <- code ที่สร้างจาก tasks
330
+ └── ...
331
+ ```
332
+
333
+ ---
334
+
335
+ ## หลักการสำคัญ
336
+
337
+ | หลักการ | คำอธิบาย |
338
+ |---------|---------|
339
+ | **Plan First** | วางแผนก่อน code เสมอ |
340
+ | **Traceability** | ทุก task อ้างอิงกลับไป requirement |
341
+ | **Human-in-the-Loop** | คนต้อง approve ก่อนทุกเฟส |
342
+ | **Small Tasks** | แต่ละ task เล็กพอทำจบได้ในรอบเดียว |
343
+ | **Living Documentation** | Spec อัปเดตตาม code ที่เปลี่ยน |
344
+ | **Verify Often** | ทุกเฟสมี verification step |
345
+
346
+ ---
347
+
348
+ ## ไฟล์ Reference
349
+
350
+ | ไฟล์ | คำอธิบาย |
351
+ |------|---------|
352
+ | [`SKILL.md`](./SKILL.md) | คำสั่งหลักที่ AI Agent อ่าน |
353
+ | [`templates/requirements.template.md`](./templates/requirements.template.md) | เทมเพลต requirements |
354
+ | [`templates/design.template.md`](./templates/design.template.md) | เทมเพลต design |
355
+ | [`templates/tasks.template.md`](./templates/tasks.template.md) | เทมเพลต tasks |
356
+ | [`examples/example-requirements.md`](./examples/example-requirements.md) | ตัวอย่าง requirements (Shopping Cart) |
357
+ | [`examples/example-design.md`](./examples/example-design.md) | ตัวอย่าง design (Shopping Cart) |
358
+ | [`examples/example-tasks.md`](./examples/example-tasks.md) | ตัวอย่าง tasks (Shopping Cart) |
359
+
360
+ ---
361
+
362
+ ## Compatibility
363
+
364
+ | เครื่องมือ | รองรับ | วิธีติดตั้ง |
365
+ |-----------|-------|-----------|
366
+ | Google Antigravity / Gemini CLI | Yes | `.gemini/skills/` |
367
+ | Cursor | Yes | `.cursor/skills/` |
368
+ | Windsurf | Yes | `.windsurf/skills/` |
369
+ | Claude (Anthropic) | Yes | ใส่ SKILL.md ใน system prompt |
370
+ | ChatGPT / GPT-4 | Yes | ใส่ SKILL.md ใน system prompt |
371
+ | GitHub Copilot | Yes | `.github/copilot/skills/` |
372
+ | อื่นๆ | Yes | อ้างอิง SKILL.md โดยตรง |
373
+
374
+ ---
375
+
376
+ <p align="center">
377
+ <b>Spec-Driven Development</b> — Stop vibe coding. Start spec coding.
378
+ </p>
package/bin/cli.js ADDED
@@ -0,0 +1,289 @@
1
+ #!/usr/bin/env node
2
+
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const readline = require("readline");
6
+
7
+ // ---------------------------------------------------------------------------
8
+ // Config
9
+ // ---------------------------------------------------------------------------
10
+
11
+ const SKILL_SOURCE = path.join(__dirname, "..", "skill");
12
+
13
+ const TARGETS = {
14
+ gemini: ".gemini/skills/spec-driven-dev",
15
+ cursor: ".cursor/skills/spec-driven-dev",
16
+ windsurf: ".windsurf/skills/spec-driven-dev",
17
+ copilot: ".github/copilot/skills/spec-driven-dev",
18
+ custom: null, // user picks path
19
+ };
20
+
21
+ const SPEC_INIT_TARGET = ".specs";
22
+
23
+ // ---------------------------------------------------------------------------
24
+ // Helpers
25
+ // ---------------------------------------------------------------------------
26
+
27
+ function log(msg) { console.log(msg); }
28
+ function warn(msg) { console.log("[WARN] " + msg); }
29
+ function err(msg) { console.error("[ERROR] " + msg); process.exit(1); }
30
+
31
+ function copyDirSync(src, dest) {
32
+ fs.mkdirSync(dest, { recursive: true });
33
+ const entries = fs.readdirSync(src, { withFileTypes: true });
34
+ for (const entry of entries) {
35
+ const srcPath = path.join(src, entry.name);
36
+ const destPath = path.join(dest, entry.name);
37
+ if (entry.isDirectory()) {
38
+ copyDirSync(srcPath, destPath);
39
+ } else {
40
+ fs.copyFileSync(srcPath, destPath);
41
+ }
42
+ }
43
+ }
44
+
45
+ function detectIDEs(projectDir) {
46
+ const found = [];
47
+ if (fs.existsSync(path.join(projectDir, ".gemini"))) found.push("gemini");
48
+ if (fs.existsSync(path.join(projectDir, ".cursor"))) found.push("cursor");
49
+ if (fs.existsSync(path.join(projectDir, ".windsurf"))) found.push("windsurf");
50
+ if (fs.existsSync(path.join(projectDir, ".github", "copilot"))) found.push("copilot");
51
+ return found;
52
+ }
53
+
54
+ function prompt(question) {
55
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
56
+ return new Promise((resolve) => {
57
+ rl.question(question, (answer) => {
58
+ rl.close();
59
+ resolve(answer.trim());
60
+ });
61
+ });
62
+ }
63
+
64
+ function printHelp() {
65
+ log("");
66
+ log(" spec-driven-dev - Install Spec-Driven Development skill");
67
+ log("");
68
+ log(" Usage:");
69
+ log(" npx spec-driven-dev Interactive install");
70
+ log(" npx spec-driven-dev --target gemini Install to .gemini/skills/");
71
+ log(" npx spec-driven-dev --target cursor Install to .cursor/skills/");
72
+ log(" npx spec-driven-dev --target windsurf Install to .windsurf/skills/");
73
+ log(" npx spec-driven-dev --target copilot Install to .github/copilot/skills/");
74
+ log(" npx spec-driven-dev --target <path> Install to custom path");
75
+ log(" npx spec-driven-dev --init <name> Scaffold a new spec");
76
+ log(" npx spec-driven-dev --help Show this help");
77
+ log("");
78
+ log(" Examples:");
79
+ log(" npx spec-driven-dev");
80
+ log(" npx spec-driven-dev --target gemini");
81
+ log(" npx spec-driven-dev --init user-authentication");
82
+ log("");
83
+ }
84
+
85
+ // ---------------------------------------------------------------------------
86
+ // Commands
87
+ // ---------------------------------------------------------------------------
88
+
89
+ function installSkill(targetPath, projectDir) {
90
+ const fullPath = path.resolve(projectDir, targetPath);
91
+
92
+ if (fs.existsSync(fullPath)) {
93
+ warn("Directory already exists: " + fullPath);
94
+ warn("Overwriting...");
95
+ fs.rmSync(fullPath, { recursive: true, force: true });
96
+ }
97
+
98
+ copyDirSync(SKILL_SOURCE, fullPath);
99
+ log("");
100
+ log(" Installed to: " + fullPath);
101
+ log("");
102
+ log(" Files:");
103
+
104
+ const listFiles = (dir, prefix) => {
105
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
106
+ for (const entry of entries) {
107
+ const rel = prefix + entry.name;
108
+ if (entry.isDirectory()) {
109
+ log(" " + rel + "/");
110
+ listFiles(path.join(dir, entry.name), rel + "/");
111
+ } else {
112
+ log(" " + rel);
113
+ }
114
+ }
115
+ };
116
+ listFiles(fullPath, "");
117
+
118
+ log("");
119
+ log(" Done! Your AI agent can now use the spec-driven-dev skill.");
120
+ log("");
121
+ }
122
+
123
+ function initSpec(featureName, projectDir) {
124
+ const specDir = path.join(projectDir, SPEC_INIT_TARGET, featureName);
125
+
126
+ if (fs.existsSync(specDir)) {
127
+ err("Spec directory already exists: " + specDir);
128
+ }
129
+
130
+ fs.mkdirSync(specDir, { recursive: true });
131
+
132
+ // Try to find templates from installed skill
133
+ let templateDir = null;
134
+ const searchPaths = [
135
+ path.join(projectDir, ".gemini/skills/spec-driven-dev/templates"),
136
+ path.join(projectDir, ".cursor/skills/spec-driven-dev/templates"),
137
+ path.join(projectDir, ".windsurf/skills/spec-driven-dev/templates"),
138
+ path.join(projectDir, ".github/copilot/skills/spec-driven-dev/templates"),
139
+ path.join(SKILL_SOURCE, "templates"),
140
+ ];
141
+
142
+ for (const p of searchPaths) {
143
+ if (fs.existsSync(p)) {
144
+ templateDir = p;
145
+ break;
146
+ }
147
+ }
148
+
149
+ const date = new Date().toISOString().split("T")[0];
150
+ const title = featureName
151
+ .replace(/[-_]/g, " ")
152
+ .replace(/\b\w/g, (c) => c.toUpperCase());
153
+
154
+ if (templateDir) {
155
+ const files = {
156
+ "requirements.template.md": "requirements.md",
157
+ "design.template.md": "design.md",
158
+ "tasks.template.md": "tasks.md",
159
+ };
160
+
161
+ for (const [src, dest] of Object.entries(files)) {
162
+ const srcPath = path.join(templateDir, src);
163
+ if (fs.existsSync(srcPath)) {
164
+ let content = fs.readFileSync(srcPath, "utf-8");
165
+ content = content.replace(/\[Feature Name\]/g, title);
166
+ content = content.replace(/\[Date\]/g, date);
167
+ fs.writeFileSync(path.join(specDir, dest), content, "utf-8");
168
+ }
169
+ }
170
+ log(" Copied templates from: " + templateDir);
171
+ } else {
172
+ // Create minimal files
173
+ fs.writeFileSync(
174
+ path.join(specDir, "requirements.md"),
175
+ "# Feature: " + title + "\n\n> **Status:** Draft\n\n## Overview\n\n[Describe the feature here.]\n\n## User Stories\n\n### US-1: [Story Title]\n\n**As a** [persona],\n**I want to** [action],\n**so that** [benefit].\n\n#### Acceptance Criteria\n\n##### AC-1.1: [Scenario]\n\n**Given** [precondition]\n**When** [action]\n**Then** [outcome]\n",
176
+ "utf-8"
177
+ );
178
+ fs.writeFileSync(
179
+ path.join(specDir, "design.md"),
180
+ "# Technical Design: " + title + "\n\n> **Status:** Draft\n\n## Overview\n\n[Describe the technical approach.]\n\n## Architecture\n\n[Define the architecture.]\n\n## Component Design\n\n[Define the components.]\n",
181
+ "utf-8"
182
+ );
183
+ fs.writeFileSync(
184
+ path.join(specDir, "tasks.md"),
185
+ "# Implementation Tasks: " + title + "\n\n> **Status:** Not Started\n\n## Phase 1: [Foundation]\n\n- [ ] **Task 1.1:** [Description]\n- [ ] **Task 1.2 (Verify):** Verification\n\n## Phase 2: [Core Logic]\n\n- [ ] **Task 2.1:** [Description]\n- [ ] **Task 2.2 (Verify):** Verification\n",
186
+ "utf-8"
187
+ );
188
+ log(" Created minimal spec files (templates not found in project).");
189
+ }
190
+
191
+ log("");
192
+ log(" Spec initialized: " + specDir);
193
+ log("");
194
+ log(" " + featureName + "/requirements.md <- Define WHAT to build");
195
+ log(" " + featureName + "/design.md <- Define HOW to build it");
196
+ log(" " + featureName + "/tasks.md <- Execution plan");
197
+ log("");
198
+ log(" Next: Ask your AI agent to fill in the spec, or edit manually.");
199
+ log("");
200
+ }
201
+
202
+ // ---------------------------------------------------------------------------
203
+ // Interactive mode
204
+ // ---------------------------------------------------------------------------
205
+
206
+ async function interactive(projectDir) {
207
+ log("");
208
+ log(" Spec-Driven Development Skill Installer");
209
+ log(" ----------------------------------------");
210
+ log("");
211
+
212
+ // Detect existing IDEs
213
+ const detected = detectIDEs(projectDir);
214
+
215
+ log(" Where do you want to install the skill?");
216
+ log("");
217
+ log(" 1) Gemini CLI / Antigravity (.gemini/skills/)" + (detected.includes("gemini") ? " [detected]" : ""));
218
+ log(" 2) Cursor (.cursor/skills/)" + (detected.includes("cursor") ? " [detected]" : ""));
219
+ log(" 3) Windsurf (.windsurf/skills/)" + (detected.includes("windsurf") ? " [detected]" : ""));
220
+ log(" 4) GitHub Copilot (.github/copilot/skills/)" + (detected.includes("copilot") ? " [detected]" : ""));
221
+ log(" 5) Custom path");
222
+ log("");
223
+
224
+ const defaultChoice = detected.length > 0
225
+ ? String(["gemini", "cursor", "windsurf", "copilot"].indexOf(detected[0]) + 1)
226
+ : "1";
227
+
228
+ const choice = await prompt(" Choose [" + defaultChoice + "]: ") || defaultChoice;
229
+
230
+ let targetPath;
231
+
232
+ switch (choice) {
233
+ case "1": targetPath = TARGETS.gemini; break;
234
+ case "2": targetPath = TARGETS.cursor; break;
235
+ case "3": targetPath = TARGETS.windsurf; break;
236
+ case "4": targetPath = TARGETS.copilot; break;
237
+ case "5":
238
+ targetPath = await prompt(" Enter custom path: ");
239
+ if (!targetPath) err("Path is required.");
240
+ break;
241
+ default:
242
+ err("Invalid choice: " + choice);
243
+ }
244
+
245
+ installSkill(targetPath, projectDir);
246
+ }
247
+
248
+ // ---------------------------------------------------------------------------
249
+ // Main
250
+ // ---------------------------------------------------------------------------
251
+
252
+ async function main() {
253
+ const args = process.argv.slice(2);
254
+ const projectDir = process.cwd();
255
+
256
+ // --help
257
+ if (args.includes("--help") || args.includes("-h")) {
258
+ printHelp();
259
+ return;
260
+ }
261
+
262
+ // --init <name>
263
+ const initIdx = args.indexOf("--init");
264
+ if (initIdx !== -1) {
265
+ const name = args[initIdx + 1];
266
+ if (!name) err("Feature name is required. Usage: npx spec-driven-dev --init <feature-name>");
267
+ initSpec(name, projectDir);
268
+ return;
269
+ }
270
+
271
+ // --target <target>
272
+ const targetIdx = args.indexOf("--target");
273
+ if (targetIdx !== -1) {
274
+ const target = args[targetIdx + 1];
275
+ if (!target) err("Target is required. Usage: npx spec-driven-dev --target <gemini|cursor|windsurf|copilot|path>");
276
+
277
+ const targetPath = TARGETS[target] || target;
278
+ installSkill(targetPath, projectDir);
279
+ return;
280
+ }
281
+
282
+ // No args -> interactive
283
+ await interactive(projectDir);
284
+ }
285
+
286
+ main().catch((e) => {
287
+ console.error(e);
288
+ process.exit(1);
289
+ });