@abranjith/spec-lite 0.0.3 → 0.0.4
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 +340 -37
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/prompts/architect.md +2 -2
- package/prompts/brainstorm.md +2 -2
- package/prompts/code_review.md +2 -2
- package/prompts/devops.md +2 -2
- package/prompts/feature.md +2 -2
- package/prompts/fix.md +2 -2
- package/prompts/implement.md +1 -1
- package/prompts/integration_tests.md +2 -2
- package/prompts/memorize.md +2 -2
- package/prompts/orchestrator.md +2 -2
- package/prompts/performance_review.md +2 -2
- package/prompts/planner.md +3 -3
- package/prompts/readme.md +1 -1
- package/prompts/security_audit.md +2 -2
- package/prompts/spec_help.md +1 -1
- package/prompts/technical_docs.md +2 -2
- package/prompts/unit_tests.md +2 -2
package/dist/index.js
CHANGED
|
@@ -12,14 +12,255 @@ import inquirer from "inquirer";
|
|
|
12
12
|
// src/providers/copilot.ts
|
|
13
13
|
import path from "path";
|
|
14
14
|
import fs from "fs-extra";
|
|
15
|
+
var AGENT_HANDOFFS = {
|
|
16
|
+
spec_help: [],
|
|
17
|
+
brainstorm: [
|
|
18
|
+
{
|
|
19
|
+
label: "Create Plan",
|
|
20
|
+
agent: "spec.planner",
|
|
21
|
+
prompt: "Create a detailed technical plan based on the brainstorm above."
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
label: "Capture Conventions",
|
|
25
|
+
agent: "spec.memorize",
|
|
26
|
+
prompt: "Bootstrap memory from the project context established in the brainstorm."
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
planner: [
|
|
30
|
+
{
|
|
31
|
+
label: "Break Down Features",
|
|
32
|
+
agent: "spec.feature",
|
|
33
|
+
prompt: "Break the plan into individual feature specification files."
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
label: "Design Architecture",
|
|
37
|
+
agent: "spec.architect",
|
|
38
|
+
prompt: "Create a detailed cloud and infrastructure architecture for the plan."
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
label: "Capture Conventions",
|
|
42
|
+
agent: "spec.memorize",
|
|
43
|
+
prompt: "Bootstrap memory from the plan's tech stack and conventions."
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
architect: [
|
|
47
|
+
{
|
|
48
|
+
label: "Break Down Features",
|
|
49
|
+
agent: "spec.feature",
|
|
50
|
+
prompt: "Break the plan into individual feature specification files."
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
label: "Set Up Infrastructure",
|
|
54
|
+
agent: "spec.devops",
|
|
55
|
+
prompt: "Set up Docker, CI/CD, and deployment infrastructure based on the architecture."
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
feature: [
|
|
59
|
+
{
|
|
60
|
+
label: "Implement Feature",
|
|
61
|
+
agent: "spec.implement",
|
|
62
|
+
prompt: "Implement the feature spec produced above."
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
label: "Write Unit Tests",
|
|
66
|
+
agent: "spec.unit_tests",
|
|
67
|
+
prompt: "Write unit tests for the feature spec produced above."
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
implement: [
|
|
71
|
+
{
|
|
72
|
+
label: "Write Unit Tests",
|
|
73
|
+
agent: "spec.unit_tests",
|
|
74
|
+
prompt: "Write comprehensive unit tests for the code just implemented."
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
label: "Review Code",
|
|
78
|
+
agent: "spec.code_review",
|
|
79
|
+
prompt: "Review the code just implemented for correctness, architecture, and readability."
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
label: "Write Integration Tests",
|
|
83
|
+
agent: "spec.integration_tests",
|
|
84
|
+
prompt: "Write integration test scenarios for the feature just implemented."
|
|
85
|
+
}
|
|
86
|
+
],
|
|
87
|
+
unit_tests: [
|
|
88
|
+
{
|
|
89
|
+
label: "Review Code",
|
|
90
|
+
agent: "spec.code_review",
|
|
91
|
+
prompt: "Review the implementation and tests for correctness, architecture, and readability."
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
label: "Write Integration Tests",
|
|
95
|
+
agent: "spec.integration_tests",
|
|
96
|
+
prompt: "Write integration test scenarios to complement the unit tests."
|
|
97
|
+
}
|
|
98
|
+
],
|
|
99
|
+
code_review: [
|
|
100
|
+
{
|
|
101
|
+
label: "Fix Issues",
|
|
102
|
+
agent: "spec.fix",
|
|
103
|
+
prompt: "Fix the issues identified in the code review above."
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
label: "Security Audit",
|
|
107
|
+
agent: "spec.security_audit",
|
|
108
|
+
prompt: "Run a security audit on the code reviewed above."
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
label: "Write Technical Docs",
|
|
112
|
+
agent: "spec.technical_docs",
|
|
113
|
+
prompt: "Write technical documentation for the reviewed code."
|
|
114
|
+
}
|
|
115
|
+
],
|
|
116
|
+
integration_tests: [
|
|
117
|
+
{
|
|
118
|
+
label: "Security Audit",
|
|
119
|
+
agent: "spec.security_audit",
|
|
120
|
+
prompt: "Run a security audit on the features covered by integration tests."
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
label: "Performance Review",
|
|
124
|
+
agent: "spec.performance_review",
|
|
125
|
+
prompt: "Review performance of the features covered by integration tests."
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
label: "Write Technical Docs",
|
|
129
|
+
agent: "spec.technical_docs",
|
|
130
|
+
prompt: "Write technical documentation for the features covered by integration tests."
|
|
131
|
+
}
|
|
132
|
+
],
|
|
133
|
+
performance_review: [
|
|
134
|
+
{
|
|
135
|
+
label: "Fix Critical Issues",
|
|
136
|
+
agent: "spec.fix",
|
|
137
|
+
prompt: "Fix the critical performance issues identified in the review above."
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
label: "Security Audit",
|
|
141
|
+
agent: "spec.security_audit",
|
|
142
|
+
prompt: "Run a security audit alongside the performance improvements."
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
label: "Write Technical Docs",
|
|
146
|
+
agent: "spec.technical_docs",
|
|
147
|
+
prompt: "Write technical documentation capturing the performance findings and fixes."
|
|
148
|
+
}
|
|
149
|
+
],
|
|
150
|
+
security_audit: [
|
|
151
|
+
{
|
|
152
|
+
label: "Fix Vulnerabilities",
|
|
153
|
+
agent: "spec.fix",
|
|
154
|
+
prompt: "Fix the vulnerabilities and security issues identified in the audit above."
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
label: "Write Technical Docs",
|
|
158
|
+
agent: "spec.technical_docs",
|
|
159
|
+
prompt: "Write technical documentation capturing the security findings and mitigations."
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
label: "Update README",
|
|
163
|
+
agent: "spec.readme",
|
|
164
|
+
prompt: "Update the README to reflect the hardened security posture."
|
|
165
|
+
}
|
|
166
|
+
],
|
|
167
|
+
fix: [
|
|
168
|
+
{
|
|
169
|
+
label: "Review Fix",
|
|
170
|
+
agent: "spec.code_review",
|
|
171
|
+
prompt: "Review the fix applied above for correctness and regressions."
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
label: "Write Regression Tests",
|
|
175
|
+
agent: "spec.unit_tests",
|
|
176
|
+
prompt: "Write regression tests to cover the bug fixed above."
|
|
177
|
+
}
|
|
178
|
+
],
|
|
179
|
+
memorize: [
|
|
180
|
+
{
|
|
181
|
+
label: "Create Plan",
|
|
182
|
+
agent: "spec.planner",
|
|
183
|
+
prompt: "Create a technical plan for the project using the conventions captured in memory."
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
label: "Add Feature",
|
|
187
|
+
agent: "spec.feature",
|
|
188
|
+
prompt: "Define a feature specification using the conventions captured in memory."
|
|
189
|
+
}
|
|
190
|
+
],
|
|
191
|
+
technical_docs: [
|
|
192
|
+
{
|
|
193
|
+
label: "Update README",
|
|
194
|
+
agent: "spec.readme",
|
|
195
|
+
prompt: "Write or update the project README based on the technical docs produced above."
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
label: "Set Up DevOps",
|
|
199
|
+
agent: "spec.devops",
|
|
200
|
+
prompt: "Set up deployment infrastructure to complement the documented architecture."
|
|
201
|
+
}
|
|
202
|
+
],
|
|
203
|
+
readme: [
|
|
204
|
+
{
|
|
205
|
+
label: "Set Up DevOps",
|
|
206
|
+
agent: "spec.devops",
|
|
207
|
+
prompt: "Set up Docker, CI/CD, and deployment infrastructure for this project."
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
label: "Security Audit",
|
|
211
|
+
agent: "spec.security_audit",
|
|
212
|
+
prompt: "Run a final security audit before releasing the project."
|
|
213
|
+
}
|
|
214
|
+
],
|
|
215
|
+
devops: [
|
|
216
|
+
{
|
|
217
|
+
label: "Security Audit",
|
|
218
|
+
agent: "spec.security_audit",
|
|
219
|
+
prompt: "Run a security audit on the infrastructure and deployment configuration."
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
label: "Update README",
|
|
223
|
+
agent: "spec.readme",
|
|
224
|
+
prompt: "Update the README with deployment and infrastructure instructions."
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
label: "Update Technical Docs",
|
|
228
|
+
agent: "spec.technical_docs",
|
|
229
|
+
prompt: "Update the technical documentation to include the DevOps setup."
|
|
230
|
+
}
|
|
231
|
+
]
|
|
232
|
+
};
|
|
233
|
+
function buildAgentFrontmatter(meta) {
|
|
234
|
+
const handoffs = AGENT_HANDOFFS[meta.name] ?? [];
|
|
235
|
+
const lines = ["---", `description: ${meta.description}`];
|
|
236
|
+
if (handoffs.length > 0) {
|
|
237
|
+
lines.push("handoffs:");
|
|
238
|
+
for (const h of handoffs) {
|
|
239
|
+
lines.push(` - label: ${h.label}`);
|
|
240
|
+
lines.push(` agent: ${h.agent}`);
|
|
241
|
+
lines.push(` prompt: ${h.prompt}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
lines.push("---", "");
|
|
245
|
+
return lines.join("\n");
|
|
246
|
+
}
|
|
15
247
|
var CopilotProvider = class {
|
|
16
248
|
name = "GitHub Copilot";
|
|
17
249
|
alias = "copilot";
|
|
18
250
|
description = "GitHub Copilot (VS Code, JetBrains, Neovim)";
|
|
251
|
+
/** Primary target: the .agent.md file in .github/agents/ */
|
|
19
252
|
getTargetPath(promptName) {
|
|
20
|
-
return path.join(".github", "
|
|
253
|
+
return path.join(".github", "agents", `spec.${promptName}.agent.md`);
|
|
21
254
|
}
|
|
255
|
+
/** Transform content into an agent file: YAML frontmatter + prompt body. */
|
|
22
256
|
transformPrompt(content, meta) {
|
|
257
|
+
return buildAgentFrontmatter(meta) + content;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Transform content into a prompt file (no frontmatter — just the managed-file
|
|
261
|
+
* header comment followed by the prompt body).
|
|
262
|
+
*/
|
|
263
|
+
transformPromptFile(content, meta) {
|
|
23
264
|
const header = [
|
|
24
265
|
`<!-- spec-lite | ${meta.name} | DO NOT EDIT below the project-context block \u2014 managed by spec-lite -->`,
|
|
25
266
|
`<!-- To update: run "spec-lite update" \u2014 your Project Context edits will be preserved -->`,
|
|
@@ -27,22 +268,31 @@ var CopilotProvider = class {
|
|
|
27
268
|
].join("\n");
|
|
28
269
|
return header + content;
|
|
29
270
|
}
|
|
271
|
+
/** Returns the path for the companion .prompt.md file */
|
|
272
|
+
getPromptFilePath(promptName) {
|
|
273
|
+
return path.join(".github", "prompts", `${promptName}.prompt.md`);
|
|
274
|
+
}
|
|
30
275
|
async detectExisting(workspaceRoot) {
|
|
31
276
|
const existing = [];
|
|
32
|
-
const
|
|
33
|
-
if (await fs.pathExists(
|
|
34
|
-
const files = await fs.readdir(
|
|
277
|
+
const agentsDir = path.join(workspaceRoot, ".github", "agents");
|
|
278
|
+
if (await fs.pathExists(agentsDir)) {
|
|
279
|
+
const files = await fs.readdir(agentsDir);
|
|
35
280
|
for (const f of files) {
|
|
36
|
-
if (f.
|
|
37
|
-
existing.push(path.join(".github", "
|
|
281
|
+
if (f.startsWith("spec.") && f.endsWith(".agent.md")) {
|
|
282
|
+
existing.push(path.join(".github", "agents", f));
|
|
38
283
|
}
|
|
39
284
|
}
|
|
40
285
|
}
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
286
|
+
const promptsDir = path.join(workspaceRoot, ".github", "prompts");
|
|
287
|
+
if (await fs.pathExists(promptsDir)) {
|
|
288
|
+
const files = await fs.readdir(promptsDir);
|
|
289
|
+
for (const f of files) {
|
|
290
|
+
if (f.endsWith(".prompt.md")) {
|
|
291
|
+
existing.push(path.join(".github", "prompts", f));
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
const mainFile = path.join(workspaceRoot, ".github", "copilot-instructions.md");
|
|
46
296
|
if (await fs.pathExists(mainFile)) {
|
|
47
297
|
existing.push(".github/copilot-instructions.md");
|
|
48
298
|
}
|
|
@@ -60,13 +310,14 @@ var CopilotProvider = class {
|
|
|
60
310
|
"",
|
|
61
311
|
"\u{1F4CB} GitHub Copilot setup complete!",
|
|
62
312
|
"",
|
|
63
|
-
"
|
|
313
|
+
" Agent files : .github/agents/spec.<name>.agent.md",
|
|
314
|
+
" Prompt files : .github/prompts/<name>.prompt.md",
|
|
64
315
|
"",
|
|
65
316
|
" How to use:",
|
|
66
317
|
" 1. Open GitHub Copilot Chat in VS Code",
|
|
67
|
-
" 2.
|
|
68
|
-
"
|
|
69
|
-
" 3.
|
|
318
|
+
" 2. Select a sub-agent from the agents dropdown (e.g., spec.planner)",
|
|
319
|
+
" \u2014 or \u2014 reference a prompt file with #file or type / to browse",
|
|
320
|
+
" 3. Agent files include handoff buttons to guide you through the pipeline",
|
|
70
321
|
" 4. Customize the Project Context block in each file for your project",
|
|
71
322
|
""
|
|
72
323
|
].join("\n");
|
|
@@ -79,18 +330,28 @@ function generateSpecLiteBlock(installedPrompts) {
|
|
|
79
330
|
SPEC_LITE_MARKER_START,
|
|
80
331
|
"## spec-lite Sub-Agents",
|
|
81
332
|
"",
|
|
82
|
-
"This project uses [spec-lite](https://github.com/
|
|
333
|
+
"This project uses [spec-lite](https://github.com/abranjith/spec-lite) sub-agent prompts",
|
|
83
334
|
"for structured software engineering workflows.",
|
|
84
335
|
"",
|
|
85
|
-
"The following specialist sub-agents are available
|
|
336
|
+
"The following specialist sub-agents are available:",
|
|
337
|
+
"",
|
|
338
|
+
"**Agent files** (`.github/agents/`) \u2014 select from the agents dropdown in Copilot Chat:",
|
|
86
339
|
""
|
|
87
340
|
];
|
|
88
341
|
for (const name of installedPrompts) {
|
|
89
|
-
lines.push(`- [
|
|
342
|
+
lines.push(`- [spec.${name}](.github/agents/spec.${name}.agent.md)`);
|
|
343
|
+
}
|
|
344
|
+
lines.push(
|
|
345
|
+
"",
|
|
346
|
+
"**Prompt files** (`.github/prompts/`) \u2014 reference with `#file` or browse with `/`:",
|
|
347
|
+
""
|
|
348
|
+
);
|
|
349
|
+
for (const name of installedPrompts) {
|
|
350
|
+
lines.push(`- [${name}](.github/prompts/${name}.prompt.md)`);
|
|
90
351
|
}
|
|
91
352
|
lines.push(
|
|
92
353
|
"",
|
|
93
|
-
"To invoke a sub-agent
|
|
354
|
+
"To invoke a sub-agent, select it from the agents dropdown or use `#file` to reference a prompt file.",
|
|
94
355
|
SPEC_LITE_MARKER_END
|
|
95
356
|
);
|
|
96
357
|
return lines.join("\n");
|
|
@@ -177,7 +438,7 @@ function generateClaudeRootMd(installedPrompts) {
|
|
|
177
438
|
"",
|
|
178
439
|
"# Project Instructions",
|
|
179
440
|
"",
|
|
180
|
-
"This project uses [spec-lite](https://github.com/
|
|
441
|
+
"This project uses [spec-lite](https://github.com/abranjith/spec-lite) sub-agent prompts",
|
|
181
442
|
"for structured software engineering workflows.",
|
|
182
443
|
"",
|
|
183
444
|
"## Available Sub-Agents",
|
|
@@ -699,6 +960,27 @@ ${existingFiles.map((f) => ` - ${f}`).join("\n")}`
|
|
|
699
960
|
written++;
|
|
700
961
|
}
|
|
701
962
|
if (provider.alias === "copilot") {
|
|
963
|
+
const copilotProvider = provider;
|
|
964
|
+
for (const prompt of prompts) {
|
|
965
|
+
const promptRelPath = copilotProvider.getPromptFilePath(prompt.name);
|
|
966
|
+
const promptAbsPath = path6.join(cwd, promptRelPath);
|
|
967
|
+
if (!options.force && existingFiles.includes(promptRelPath) && globalAction === "skip") {
|
|
968
|
+
continue;
|
|
969
|
+
}
|
|
970
|
+
let content = prompt.content;
|
|
971
|
+
if (contextBlock) {
|
|
972
|
+
content = replaceProjectContext(content, contextBlock);
|
|
973
|
+
}
|
|
974
|
+
const transformed = copilotProvider.transformPromptFile(content, {
|
|
975
|
+
name: prompt.name,
|
|
976
|
+
title: prompt.title,
|
|
977
|
+
description: prompt.description
|
|
978
|
+
});
|
|
979
|
+
await fs6.ensureDir(path6.dirname(promptAbsPath));
|
|
980
|
+
await fs6.writeFile(promptAbsPath, transformed, "utf-8");
|
|
981
|
+
written++;
|
|
982
|
+
console.log(chalk.green(` \u2713 ${promptRelPath}`));
|
|
983
|
+
}
|
|
702
984
|
const copilotInstructionsPath = path6.join(cwd, ".github", "copilot-instructions.md");
|
|
703
985
|
await fs6.ensureDir(path6.join(cwd, ".github"));
|
|
704
986
|
const existingContent = await fs6.pathExists(copilotInstructionsPath) ? await fs6.readFile(copilotInstructionsPath, "utf-8") : null;
|
|
@@ -841,7 +1123,7 @@ async function loadPackageVersion() {
|
|
|
841
1123
|
const pkg2 = require3("../../package.json");
|
|
842
1124
|
return pkg2.version;
|
|
843
1125
|
} catch {
|
|
844
|
-
return "0.0.
|
|
1126
|
+
return "0.0.4";
|
|
845
1127
|
}
|
|
846
1128
|
}
|
|
847
1129
|
|
|
@@ -881,24 +1163,9 @@ async function updateCommand(options) {
|
|
|
881
1163
|
let updated = 0;
|
|
882
1164
|
let preserved = 0;
|
|
883
1165
|
let unchanged = 0;
|
|
884
|
-
let migrated = 0;
|
|
885
1166
|
for (const prompt of prompts) {
|
|
886
1167
|
const targetRelPath = provider.getTargetPath(prompt.name);
|
|
887
1168
|
const targetAbsPath = path7.join(cwd, targetRelPath);
|
|
888
|
-
if (provider.alias === "copilot") {
|
|
889
|
-
const oldRelPath = path7.join(".github", "copilot", `${prompt.name}.md`);
|
|
890
|
-
const oldAbsPath = path7.join(cwd, oldRelPath);
|
|
891
|
-
if (targetRelPath !== oldRelPath && await fs7.pathExists(oldAbsPath) && !await fs7.pathExists(targetAbsPath)) {
|
|
892
|
-
await fs7.ensureDir(path7.dirname(targetAbsPath));
|
|
893
|
-
await fs7.rename(oldAbsPath, targetAbsPath);
|
|
894
|
-
console.log(
|
|
895
|
-
chalk2.cyan(
|
|
896
|
-
` \u2197 ${oldRelPath} \u2192 ${targetRelPath} (migrated to .prompt.md)`
|
|
897
|
-
)
|
|
898
|
-
);
|
|
899
|
-
migrated++;
|
|
900
|
-
}
|
|
901
|
-
}
|
|
902
1169
|
const newContent = provider.transformPrompt(prompt.content, {
|
|
903
1170
|
name: prompt.name,
|
|
904
1171
|
title: prompt.title,
|
|
@@ -942,6 +1209,42 @@ async function updateCommand(options) {
|
|
|
942
1209
|
console.log(chalk2.green(` \u2713 CLAUDE.md (regenerated)`));
|
|
943
1210
|
}
|
|
944
1211
|
if (provider.alias === "copilot") {
|
|
1212
|
+
const copilotProvider = provider;
|
|
1213
|
+
for (const prompt of prompts) {
|
|
1214
|
+
const promptRelPath = copilotProvider.getPromptFilePath(prompt.name);
|
|
1215
|
+
const promptAbsPath = path7.join(cwd, promptRelPath);
|
|
1216
|
+
const newContent = copilotProvider.transformPromptFile(prompt.content, {
|
|
1217
|
+
name: prompt.name,
|
|
1218
|
+
title: prompt.title,
|
|
1219
|
+
description: prompt.description
|
|
1220
|
+
});
|
|
1221
|
+
if (!await fs7.pathExists(promptAbsPath)) {
|
|
1222
|
+
await fs7.ensureDir(path7.dirname(promptAbsPath));
|
|
1223
|
+
await fs7.writeFile(promptAbsPath, newContent, "utf-8");
|
|
1224
|
+
console.log(chalk2.green(` \u2713 ${promptRelPath} (restored)`));
|
|
1225
|
+
updated++;
|
|
1226
|
+
continue;
|
|
1227
|
+
}
|
|
1228
|
+
const currentContent = await fs7.readFile(promptAbsPath, "utf-8");
|
|
1229
|
+
if (currentContent === newContent) {
|
|
1230
|
+
unchanged++;
|
|
1231
|
+
continue;
|
|
1232
|
+
}
|
|
1233
|
+
if (!options.force) {
|
|
1234
|
+
const userContext = extractProjectContext(currentContent);
|
|
1235
|
+
if (userContext) {
|
|
1236
|
+
const mergedContent = replaceProjectContext(newContent, userContext);
|
|
1237
|
+
await fs7.writeFile(promptAbsPath, mergedContent, "utf-8");
|
|
1238
|
+
console.log(chalk2.green(` \u2713 ${promptRelPath} (updated, Project Context preserved)`));
|
|
1239
|
+
preserved++;
|
|
1240
|
+
updated++;
|
|
1241
|
+
continue;
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
await fs7.writeFile(promptAbsPath, newContent, "utf-8");
|
|
1245
|
+
console.log(chalk2.green(` \u2713 ${promptRelPath} (updated)`));
|
|
1246
|
+
updated++;
|
|
1247
|
+
}
|
|
945
1248
|
const copilotInstructionsPath = path7.join(cwd, ".github", "copilot-instructions.md");
|
|
946
1249
|
await fs7.ensureDir(path7.join(cwd, ".github"));
|
|
947
1250
|
const existingContent = await fs7.pathExists(copilotInstructionsPath) ? await fs7.readFile(copilotInstructionsPath, "utf-8") : null;
|
|
@@ -961,7 +1264,7 @@ async function updateCommand(options) {
|
|
|
961
1264
|
console.log(
|
|
962
1265
|
chalk2.bold(
|
|
963
1266
|
`
|
|
964
|
-
Done! ${updated} updated, ${unchanged} unchanged, ${preserved} with preserved edits
|
|
1267
|
+
Done! ${updated} updated, ${unchanged} unchanged, ${preserved} with preserved edits.`
|
|
965
1268
|
)
|
|
966
1269
|
);
|
|
967
1270
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/providers/copilot.ts","../src/providers/claude-code.ts","../src/providers/generic.ts","../src/providers/index.ts","../src/utils/prompts.ts","../src/utils/stacks.ts","../src/commands/update.ts","../src/commands/list.ts"],"sourcesContent":["import { Command } from \"commander\";\r\nimport { initCommand } from \"./commands/init.js\";\r\nimport { updateCommand } from \"./commands/update.js\";\r\nimport { listCommand } from \"./commands/list.js\";\r\nimport { createRequire } from \"module\";\r\n\r\nconst require = createRequire(import.meta.url);\r\nconst pkg = require(\"../package.json\");\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name(\"spec-lite\")\r\n .description(\r\n \"Install structured AI sub-agent prompts into your workspace for any AI coding assistant\"\r\n )\r\n .version(pkg.version);\r\n\r\nprogram\r\n .command(\"init\")\r\n .description(\"Initialize spec-lite sub-agent prompts in your workspace\")\r\n .option(\r\n \"--ai <provider>\",\r\n \"AI provider to configure for (copilot, claude-code, generic)\"\r\n )\r\n .option(\r\n \"--exclude <prompts>\",\r\n \"Comma-separated list of prompts to exclude (e.g., brainstorm,readme)\"\r\n )\r\n .option(\"--force\", \"Overwrite existing files without prompting\", false)\r\n .option(\r\n \"--skip-profile\",\r\n \"Skip the project profile questionnaire (for CI/scripting)\"\r\n )\r\n .action(initCommand);\r\n\r\nprogram\r\n .command(\"update\")\r\n .description(\r\n \"Update spec-lite prompts to the latest version, preserving your Project Context edits\"\r\n )\r\n .option(\"--force\", \"Overwrite all files including user-modified ones\", false)\r\n .action(updateCommand);\r\n\r\nprogram\r\n .command(\"list\")\r\n .description(\"List all available spec-lite sub-agents and their purpose\")\r\n .action(listCommand);\r\n\r\nprogram.parse();\r\n","import path from \"path\";\r\nimport fs from \"fs-extra\";\r\nimport chalk from \"chalk\";\r\nimport inquirer from \"inquirer\";\r\nimport { getProvider, getAllProviders } from \"../providers/index.js\";\r\nimport type { SpecLiteConfig, ProjectProfile } from \"../providers/base.js\";\r\nimport { loadPrompts, replaceProjectContext } from \"../utils/prompts.js\";\r\nimport { generateClaudeRootMd } from \"../providers/claude-code.js\";\r\nimport { mergeCopilotInstructions } from \"../providers/copilot.js\";\r\nimport { getStackSnippet } from \"../utils/stacks.js\";\r\n\r\ninterface InitOptions {\r\n ai?: string;\r\n exclude?: string;\r\n force?: boolean;\r\n skipProfile?: boolean;\r\n}\r\n\r\nconst LANGUAGE_CHOICES = [\r\n { name: \"TypeScript\", value: \"TypeScript\" },\r\n { name: \"Python\", value: \"Python\" },\r\n { name: \"Java\", value: \"Java\" },\r\n { name: \"C# / .NET\", value: \"C#\" },\r\n { name: \"Go\", value: \"Go\" },\r\n { name: \"Rust\", value: \"Rust\" },\r\n { name: \"Other (specify below)\", value: \"__other__\" },\r\n];\r\n\r\nconst ARCHITECTURE_CHOICES = [\r\n { name: \"Monolith\", value: \"Monolith\" },\r\n { name: \"Microservices\", value: \"Microservices\" },\r\n { name: \"Serverless\", value: \"Serverless\" },\r\n { name: \"Monorepo\", value: \"Monorepo\" },\r\n { name: \"Other (specify below)\", value: \"__other__\" },\r\n];\r\n\r\n/**\r\n * Collect project profile via interactive questionnaire.\r\n * Returns a ProjectProfile with the user's answers.\r\n */\r\nasync function collectProjectProfile(): Promise<ProjectProfile> {\r\n console.log(\r\n chalk.cyan(\r\n \"\\n 📋 Project Profile — a few questions to personalize your setup:\\n\"\r\n )\r\n );\r\n\r\n const answers = await inquirer.prompt([\r\n {\r\n type: \"list\",\r\n name: \"language\",\r\n message: \"Primary programming language?\",\r\n choices: LANGUAGE_CHOICES,\r\n },\r\n {\r\n type: \"input\",\r\n name: \"languageOther\",\r\n message: \"Specify your primary language:\",\r\n when: (prev: Record<string, string>) => prev.language === \"__other__\",\r\n validate: (input: string) =>\r\n input.trim() ? true : \"Please enter a language.\",\r\n },\r\n {\r\n type: \"input\",\r\n name: \"frameworks\",\r\n message:\r\n 'Framework(s) in use? (e.g., \"Express + React\", \"FastAPI\", \"ASP.NET Core\")',\r\n default: \"None / not sure yet\",\r\n },\r\n {\r\n type: \"input\",\r\n name: \"testFramework\",\r\n message:\r\n 'Testing framework? (e.g., \"Jest\", \"Vitest\", \"pytest\", \"xUnit\")',\r\n default: \"Not decided yet\",\r\n },\r\n {\r\n type: \"list\",\r\n name: \"architecture\",\r\n message: \"Architectural pattern?\",\r\n choices: ARCHITECTURE_CHOICES,\r\n },\r\n {\r\n type: \"input\",\r\n name: \"architectureOther\",\r\n message: \"Specify your architectural pattern:\",\r\n when: (prev: Record<string, string>) => prev.architecture === \"__other__\",\r\n validate: (input: string) =>\r\n input.trim() ? true : \"Please enter a pattern.\",\r\n },\r\n {\r\n type: \"input\",\r\n name: \"conventions\",\r\n message:\r\n 'Any specific coding conventions? (e.g., \"Airbnb style guide\", \"PEP 8\") — leave blank if none',\r\n default: \"\",\r\n },\r\n ]);\r\n\r\n return {\r\n language:\r\n answers.language === \"__other__\"\r\n ? answers.languageOther.trim()\r\n : answers.language,\r\n frameworks: answers.frameworks.trim(),\r\n testFramework: answers.testFramework.trim(),\r\n architecture:\r\n answers.architecture === \"__other__\"\r\n ? answers.architectureOther.trim()\r\n : answers.architecture,\r\n conventions: answers.conventions.trim(),\r\n };\r\n}\r\n\r\n/**\r\n * Build a Project Context block string from a ProjectProfile.\r\n * This replaces the placeholder content inside <!-- project-context-start/end --> markers.\r\n */\r\nfunction buildProjectContextBlock(profile: ProjectProfile): string {\r\n const lines = [\r\n \"\",\r\n \"## Project Context (Customize per project)\",\r\n \"\",\r\n \"> Auto-populated by spec-lite init. Edit these values as your project evolves.\",\r\n \"\",\r\n `- **Language(s)**: ${profile.language}`,\r\n `- **Framework(s)**: ${profile.frameworks}`,\r\n `- **Test Framework**: ${profile.testFramework}`,\r\n `- **Architecture**: ${profile.architecture}`,\r\n ];\r\n if (profile.conventions) {\r\n lines.push(`- **Conventions**: ${profile.conventions}`);\r\n }\r\n lines.push(\"\");\r\n return lines.join(\"\\n\");\r\n}\r\n\r\n/**\r\n * Build a seeded .spec-lite/memory.md from raw content scraped from a provider's\r\n * existing instructions file (e.g. copilot-instructions.md, CLAUDE.md).\r\n * The file is intentionally unstructured — /memorize bootstrap will organize it.\r\n */\r\nfunction buildSeededMemory(\r\n sourceContent: string,\r\n sourcePath: string,\r\n version: string\r\n): string {\r\n const date = new Date().toISOString().split(\"T\")[0];\r\n return [\r\n `<!-- Generated by spec-lite v${version} | sub-agent: memorize | seeded-from: ${sourcePath} | updated: ${date} -->`,\r\n \"\",\r\n \"# Memory — Standing Instructions\",\r\n \"\",\r\n `> These instructions were **auto-seeded** from \\`${sourcePath}\\` during \\`spec-lite init\\`.`,\r\n \"> They have not yet been organized into sections.\",\r\n \"> Run \\`/memorize bootstrap\\` in your AI assistant to review, reorganize, and refine them.\",\r\n \">\",\r\n \"> Memory is the **authoritative source** for coding standards, architecture, testing, logging, and security.\",\r\n \"> Plans may contain plan-specific overrides but should not duplicate these rules.\",\r\n \"> Managed by the Memorize sub-agent. Do not edit section headers manually.\",\r\n \"> To add or change instructions, invoke: `/memorize <your instructions>`\",\r\n \"> To override: `/memorize override <your instructions>`\",\r\n \"> To generate from project analysis: `/memorize bootstrap`\",\r\n \"\",\r\n `<!-- seed-start: raw content imported from ${sourcePath} -->`,\r\n \"\",\r\n `## Imported from \\`${sourcePath}\\``,\r\n \"\",\r\n sourceContent.trim(),\r\n \"\",\r\n \"<!-- seed-end -->\",\r\n \"\",\r\n ].join(\"\\n\");\r\n}\r\n\r\nexport async function initCommand(options: InitOptions): Promise<void> {\r\n const cwd = process.cwd();\r\n\r\n console.log(chalk.bold(\"\\n⚡ spec-lite init\\n\"));\r\n\r\n // 1. Resolve provider\r\n let providerAlias = options.ai;\r\n\r\n if (!providerAlias) {\r\n const providers = getAllProviders();\r\n const answer = await inquirer.prompt([\r\n {\r\n type: \"list\",\r\n name: \"provider\",\r\n message: \"Which AI coding assistant are you using?\",\r\n choices: providers.map((p) => ({\r\n name: `${p.name} — ${p.description}`,\r\n value: p.alias,\r\n })),\r\n },\r\n ]);\r\n providerAlias = answer.provider as string;\r\n }\r\n\r\n const provider = getProvider(providerAlias!);\r\n if (!provider) {\r\n console.error(\r\n chalk.red(\r\n `Unknown provider: \"${providerAlias}\". Available: ${getAllProviders()\r\n .map((p) => p.alias)\r\n .join(\", \")}`\r\n )\r\n );\r\n process.exit(1);\r\n }\r\n\r\n console.log(chalk.cyan(` Provider: ${provider.name}`));\r\n\r\n // 2. Collect project profile (unless --skip-profile)\r\n let projectProfile: ProjectProfile | undefined;\r\n if (!options.skipProfile) {\r\n projectProfile = await collectProjectProfile();\r\n console.log(chalk.green(\" ✓ Project profile collected\"));\r\n } else {\r\n console.log(chalk.dim(\" Skipping project profile questionnaire.\"));\r\n }\r\n\r\n // 3. Parse exclusions (split on commas or spaces to handle both bash and PowerShell)\r\n const exclude = options.exclude\r\n ? options.exclude.split(/[,\\s]+/).map((s) => s.trim()).filter(Boolean)\r\n : [];\r\n\r\n if (exclude.length > 0) {\r\n console.log(chalk.dim(` Excluding: ${exclude.join(\", \")}`));\r\n }\r\n\r\n // 3b. Capture pre-existing seed content (before we write anything to the provider's instructions file)\r\n const memorySeedSource = await provider.getMemorySeedSource(cwd);\r\n let preSeedContent: string | null = null;\r\n if (memorySeedSource) {\r\n const seedAbsPath = path.join(cwd, memorySeedSource.path);\r\n if (await fs.pathExists(seedAbsPath)) {\r\n preSeedContent = await fs.readFile(seedAbsPath, \"utf-8\");\r\n }\r\n }\r\n\r\n // 4. Check for existing files\r\n const existingFiles = await provider.detectExisting(cwd);\r\n let globalAction: \"overwrite\" | \"skip\" | null = null;\r\n\r\n if (existingFiles.length > 0 && !options.force) {\r\n console.log(\r\n chalk.yellow(\r\n `\\n Found existing instruction files:\\n${existingFiles\r\n .map((f) => ` - ${f}`)\r\n .join(\"\\n\")}`\r\n )\r\n );\r\n\r\n const answer = await inquirer.prompt([\r\n {\r\n type: \"list\",\r\n name: \"action\",\r\n message: \"How should we handle existing files?\",\r\n choices: [\r\n {\r\n name: \"Overwrite — replace all existing files\",\r\n value: \"overwrite\",\r\n },\r\n {\r\n name: \"Skip — only write files that don't exist yet\",\r\n value: \"skip\",\r\n },\r\n { name: \"Abort — cancel initialization\", value: \"abort\" },\r\n ],\r\n },\r\n ]);\r\n\r\n if (answer.action === \"abort\") {\r\n console.log(chalk.dim(\" Aborted.\"));\r\n return;\r\n }\r\n\r\n globalAction = answer.action as \"overwrite\" | \"skip\";\r\n\r\n if (globalAction === \"skip\") {\r\n console.log(chalk.dim(\" Skipping existing files.\"));\r\n }\r\n }\r\n\r\n // 5. Build project context block (if profile was collected)\r\n const contextBlock = projectProfile\r\n ? buildProjectContextBlock(projectProfile)\r\n : null;\r\n\r\n // 6. Load and write prompts\r\n const prompts = await loadPrompts(exclude);\r\n let written = 0;\r\n let skipped = 0;\r\n const installedPrompts: string[] = [];\r\n\r\n for (const prompt of prompts) {\r\n const targetRelPath = provider.getTargetPath(prompt.name);\r\n const targetAbsPath = path.join(cwd, targetRelPath);\r\n\r\n // Skip if file exists and user chose \"skip\" globally\r\n if (\r\n !options.force &&\r\n existingFiles.includes(targetRelPath) &&\r\n globalAction === \"skip\"\r\n ) {\r\n skipped++;\r\n installedPrompts.push(prompt.name);\r\n continue;\r\n }\r\n\r\n // Inject project context into prompt if profile was collected\r\n let content = prompt.content;\r\n if (contextBlock) {\r\n content = replaceProjectContext(content, contextBlock);\r\n }\r\n\r\n const transformed = provider.transformPrompt(content, {\r\n name: prompt.name,\r\n title: prompt.title,\r\n description: prompt.description,\r\n });\r\n\r\n await fs.ensureDir(path.dirname(targetAbsPath));\r\n await fs.writeFile(targetAbsPath, transformed, \"utf-8\");\r\n written++;\r\n installedPrompts.push(prompt.name);\r\n\r\n console.log(chalk.green(` ✓ ${targetRelPath}`));\r\n }\r\n\r\n // 7. Provider-specific extras\r\n if (provider.alias === \"claude-code\") {\r\n const claudeMdPath = path.join(cwd, \"CLAUDE.md\");\r\n const claudeMdContent = generateClaudeRootMd(installedPrompts);\r\n await fs.writeFile(claudeMdPath, claudeMdContent, \"utf-8\");\r\n console.log(chalk.green(` ✓ CLAUDE.md`));\r\n written++;\r\n }\r\n\r\n if (provider.alias === \"copilot\") {\r\n const copilotInstructionsPath = path.join(cwd, \".github\", \"copilot-instructions.md\");\r\n await fs.ensureDir(path.join(cwd, \".github\"));\r\n const existingContent = (await fs.pathExists(copilotInstructionsPath))\r\n ? await fs.readFile(copilotInstructionsPath, \"utf-8\")\r\n : null;\r\n const merged = mergeCopilotInstructions(existingContent, installedPrompts);\r\n await fs.writeFile(copilotInstructionsPath, merged, \"utf-8\");\r\n if (existingContent) {\r\n console.log(chalk.green(` ✓ .github/copilot-instructions.md (updated with spec-lite block)`));\r\n } else {\r\n console.log(chalk.green(` ✓ .github/copilot-instructions.md`));\r\n }\r\n written++;\r\n }\r\n\r\n // 8. Create .spec-lite/ directory structure for agent outputs\r\n const specDirs = [\r\n path.join(\".spec-lite\", \"features\"),\r\n path.join(\".spec-lite\", \"reviews\"),\r\n ];\r\n for (const dir of specDirs) {\r\n const absDir = path.join(cwd, dir);\r\n if (!(await fs.pathExists(absDir))) {\r\n await fs.ensureDir(absDir);\r\n console.log(chalk.green(` ✓ ${dir}/`));\r\n }\r\n }\r\n\r\n // 8b. Create .spec-lite/TODO.md skeleton\r\n const todoPath = path.join(cwd, \".spec-lite\", \"TODO.md\");\r\n if (!(await fs.pathExists(todoPath))) {\r\n const todoContent = [\r\n \"# TODO — Enhancements & Ideas\",\r\n \"\",\r\n \"> Discovered by sub-agents during planning and development.\",\r\n \"> Items here are out-of-scope for their current task but worth tracking.\",\r\n \"\",\r\n \"## General\",\r\n \"\",\r\n \"## General / Caching\",\r\n \"\",\r\n \"## UI\",\r\n \"\",\r\n \"## Performance\",\r\n \"\",\r\n \"## Security\",\r\n \"\",\r\n \"## DX (Developer Experience)\",\r\n \"\",\r\n ].join(\"\\n\");\r\n await fs.writeFile(todoPath, todoContent, \"utf-8\");\r\n console.log(chalk.green(` ✓ .spec-lite/TODO.md`));\r\n }\r\n\r\n // 9. Copy bundled stack snippet to .spec-lite/stacks/ (if profile was collected)\r\n if (projectProfile) {\r\n const snippet = getStackSnippet(projectProfile.language);\r\n if (snippet) {\r\n const stacksTargetDir = path.join(cwd, \".spec-lite\", \"stacks\");\r\n await fs.ensureDir(stacksTargetDir);\r\n const snippetFileName = `${projectProfile.language.toLowerCase().replace(/[^a-z0-9]/g, \"-\")}.md`;\r\n const snippetPath = path.join(stacksTargetDir, snippetFileName);\r\n\r\n if (await fs.pathExists(snippetPath) && !options.force) {\r\n console.log(\r\n chalk.dim(` – .spec-lite/stacks/${snippetFileName} already exists (kept your edits)`)\r\n );\r\n } else {\r\n await fs.writeFile(snippetPath, snippet, \"utf-8\");\r\n console.log(\r\n chalk.green(` ✓ .spec-lite/stacks/${snippetFileName}`)\r\n );\r\n console.log(\r\n chalk.dim(\" ↳ Edit this file to customize defaults before running /memorize bootstrap\")\r\n );\r\n written++;\r\n }\r\n }\r\n }\r\n\r\n // 9b. Offer to seed .spec-lite/memory.md from pre-existing provider instructions\r\n let memorySeedWritten = false;\r\n const memoryPath = path.join(cwd, \".spec-lite\", \"memory.md\");\r\n if (preSeedContent && memorySeedSource && !(await fs.pathExists(memoryPath))) {\r\n console.log(\r\n chalk.cyan(`\\n 💡 Found existing ${memorySeedSource.label} (${memorySeedSource.path}).`)\r\n );\r\n const seedAnswer = await inquirer.prompt([\r\n {\r\n type: \"confirm\",\r\n name: \"seedMemory\",\r\n message: `Seed .spec-lite/memory.md from it so /memorize bootstrap can refine your existing conventions?`,\r\n default: true,\r\n },\r\n ]);\r\n if (seedAnswer.seedMemory) {\r\n const seedPkg = await loadPackageVersion();\r\n const seededContent = buildSeededMemory(preSeedContent, memorySeedSource.path, seedPkg);\r\n await fs.ensureDir(path.join(cwd, \".spec-lite\"));\r\n await fs.writeFile(memoryPath, seededContent, \"utf-8\");\r\n memorySeedWritten = true;\r\n written++;\r\n console.log(chalk.green(` ✓ .spec-lite/memory.md (seeded from ${memorySeedSource.path})`));\r\n console.log(chalk.dim(\" ↳ Run /memorize bootstrap to organize and refine into standing instructions\"));\r\n }\r\n }\r\n\r\n // 10. Write .spec-lite.json config\r\n const pkg = await loadPackageVersion();\r\n const config: SpecLiteConfig = {\r\n version: pkg,\r\n provider: provider.alias,\r\n installedPrompts,\r\n installedAt: new Date().toISOString(),\r\n updatedAt: new Date().toISOString(),\r\n ...(projectProfile ? { projectProfile } : {}),\r\n };\r\n const configPath = path.join(cwd, \".spec-lite.json\");\r\n await fs.writeJson(configPath, config, { spaces: 2 });\r\n console.log(chalk.green(` ✓ .spec-lite.json`));\r\n\r\n // 11. Summary\r\n console.log(\r\n chalk.bold(\r\n `\\n Done! ${written} files written, ${skipped} skipped.`\r\n )\r\n );\r\n console.log(provider.getPostInitMessage());\r\n\r\n // 12. Bootstrap next-step guidance\r\n if (projectProfile || memorySeedWritten) {\r\n if (memorySeedWritten) {\r\n console.log(\r\n chalk.cyan(\r\n \"\\n 📌 Next step: Run \") +\r\n chalk.bold(\"/memorize bootstrap\") +\r\n chalk.cyan(\r\n \" in your AI assistant.\\n It will see your seeded memory and offer to merge or refine it\\n into properly organized standing instructions.\"\r\n )\r\n );\r\n } else {\r\n console.log(\r\n chalk.cyan(\r\n \"\\n 📌 Next step: Run \") +\r\n chalk.bold(\"/memorize bootstrap\") +\r\n chalk.cyan(\r\n \" in your AI assistant to auto-generate\\n coding standards, architecture guidelines, and best practices\\n for your project based on the profile you just provided.\"\r\n )\r\n );\r\n }\r\n }\r\n}\r\n\r\nasync function loadPackageVersion(): Promise<string> {\r\n try {\r\n const { createRequire } = await import(\"module\");\r\n const require = createRequire(import.meta.url);\r\n const pkg = require(\"../../package.json\");\r\n return pkg.version;\r\n } catch {\r\n return \"0.0.3\";\r\n }\r\n}\r\n","import path from \"path\";\r\nimport fs from \"fs-extra\";\r\nimport type { Provider, PromptMeta } from \"./base.js\";\r\n\r\n/**\r\n * GitHub Copilot provider.\r\n *\r\n * Writes individual agent files to `.github/copilot-instructions/` as markdown,\r\n * plus a main `.github/copilot-instructions.md` that references the spec-lite agents.\r\n *\r\n * GitHub Copilot supports:\r\n * - `.github/copilot-instructions.md` — global instructions loaded into every Copilot Chat session\r\n * - Individual prompt files that can be referenced via @workspace or loaded as custom instructions\r\n */\r\nexport class CopilotProvider implements Provider {\r\n name = \"GitHub Copilot\";\r\n alias = \"copilot\";\r\n description = \"GitHub Copilot (VS Code, JetBrains, Neovim)\";\r\n\r\n getTargetPath(promptName: string): string {\r\n return path.join(\".github\", \"copilot\", `${promptName}.prompt.md`);\r\n }\r\n\r\n transformPrompt(content: string, meta: PromptMeta): string {\r\n // Copilot expects standard markdown. We add a brief header comment\r\n // identifying this as a spec-lite managed file.\r\n const header = [\r\n `<!-- spec-lite | ${meta.name} | DO NOT EDIT below the project-context block — managed by spec-lite -->`,\r\n `<!-- To update: run \"spec-lite update\" — your Project Context edits will be preserved -->`,\r\n \"\",\r\n ].join(\"\\n\");\r\n\r\n return header + content;\r\n }\r\n\r\n async detectExisting(workspaceRoot: string): Promise<string[]> {\r\n const existing: string[] = [];\r\n\r\n // Check for copilot instructions directory\r\n const copilotDir = path.join(workspaceRoot, \".github\", \"copilot\");\r\n if (await fs.pathExists(copilotDir)) {\r\n const files = await fs.readdir(copilotDir);\r\n for (const f of files) {\r\n if (f.endsWith(\".prompt.md\") || f.endsWith(\".md\")) {\r\n existing.push(path.join(\".github\", \"copilot\", f));\r\n }\r\n }\r\n }\r\n\r\n // Check for main instructions file\r\n const mainFile = path.join(\r\n workspaceRoot,\r\n \".github\",\r\n \"copilot-instructions.md\"\r\n );\r\n if (await fs.pathExists(mainFile)) {\r\n existing.push(\".github/copilot-instructions.md\");\r\n }\r\n\r\n return existing;\r\n }\r\n\r\n async getMemorySeedSource(\r\n workspaceRoot: string\r\n ): Promise<{ path: string; label: string } | null> {\r\n const p = path.join(workspaceRoot, \".github\", \"copilot-instructions.md\");\r\n if (await fs.pathExists(p)) {\r\n return { path: \".github/copilot-instructions.md\", label: \"GitHub Copilot global instructions\" };\r\n }\r\n return null;\r\n }\r\n\r\n getPostInitMessage(): string {\r\n return [\r\n \"\",\r\n \"📋 GitHub Copilot setup complete!\",\r\n \"\",\r\n \" Your sub-agent prompts are in .github/copilot/\",\r\n \"\",\r\n \" How to use:\",\r\n \" 1. Open GitHub Copilot Chat in VS Code\",\r\n \" 2. Sub-agents are available as slash commands — type /prompt_name\",\r\n \" (e.g., /brainstorm, /planner, /feature)\",\r\n \" 3. Files ending in .prompt.md are natively recognized by Copilot\",\r\n \" 4. Customize the Project Context block in each file for your project\",\r\n \"\",\r\n ].join(\"\\n\");\r\n }\r\n}\r\n\r\nconst SPEC_LITE_MARKER_START = \"<!-- spec-lite:start -->\";\r\nconst SPEC_LITE_MARKER_END = \"<!-- spec-lite:end -->\";\r\n\r\n/**\r\n * Generate the spec-lite block to inject into (or create as) copilot-instructions.md.\r\n */\r\nexport function generateSpecLiteBlock(installedPrompts: string[]): string {\r\n const lines = [\r\n SPEC_LITE_MARKER_START,\r\n \"## spec-lite Sub-Agents\",\r\n \"\",\r\n \"This project uses [spec-lite](https://github.com/ranjithab/spec-lite) sub-agent prompts\",\r\n \"for structured software engineering workflows.\",\r\n \"\",\r\n \"The following specialist sub-agents are available in `.github/copilot/`:\",\r\n \"\",\r\n ];\r\n\r\n for (const name of installedPrompts) {\r\n lines.push(`- [${name}](.github/copilot/${name}.prompt.md)`);\r\n }\r\n\r\n lines.push(\r\n \"\",\r\n \"To invoke a sub-agent in Copilot Chat, use the `#` file reference or type `/` to browse prompt files.\",\r\n SPEC_LITE_MARKER_END\r\n );\r\n\r\n return lines.join(\"\\n\");\r\n}\r\n\r\n/**\r\n * Merge the spec-lite block into an existing copilot-instructions.md, or create fresh content.\r\n * If the file already has spec-lite markers, the block between them is replaced.\r\n * Otherwise the block is appended.\r\n */\r\nexport function mergeCopilotInstructions(\r\n existingContent: string | null,\r\n installedPrompts: string[]\r\n): string {\r\n const block = generateSpecLiteBlock(installedPrompts);\r\n\r\n if (!existingContent) {\r\n return block + \"\\n\";\r\n }\r\n\r\n // Replace existing spec-lite block if markers are present\r\n const startIdx = existingContent.indexOf(SPEC_LITE_MARKER_START);\r\n const endIdx = existingContent.indexOf(SPEC_LITE_MARKER_END);\r\n\r\n if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {\r\n return (\r\n existingContent.slice(0, startIdx) +\r\n block +\r\n existingContent.slice(endIdx + SPEC_LITE_MARKER_END.length)\r\n );\r\n }\r\n\r\n // Append the block to existing content (preserving user content)\r\n const separator = existingContent.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\r\n return existingContent + separator + block + \"\\n\";\r\n}\r\n","import path from \"path\";\r\nimport fs from \"fs-extra\";\r\nimport type { Provider, PromptMeta } from \"./base.js\";\r\n\r\n/**\r\n * Claude Code (Anthropic) provider.\r\n *\r\n * Claude Code supports:\r\n * - `CLAUDE.md` at the project root — loaded automatically as project instructions\r\n * - `.claude/` directory for additional configuration\r\n * - Nested `CLAUDE.md` files in subdirectories for scoped instructions\r\n *\r\n * Strategy:\r\n * - Write individual agent files to `.claude/prompts/<name>.md`\r\n * - Create/update a root `CLAUDE.md` that references the spec-lite agent collection\r\n * and provides a high-level overview\r\n */\r\nexport class ClaudeCodeProvider implements Provider {\r\n name = \"Claude Code\";\r\n alias = \"claude-code\";\r\n description = \"Claude Code (Anthropic's coding agent)\";\r\n\r\n getTargetPath(promptName: string): string {\r\n return path.join(\".claude\", \"prompts\", `${promptName}.md`);\r\n }\r\n\r\n transformPrompt(content: string, meta: PromptMeta): string {\r\n // Claude Code reads markdown natively. We add a header comment.\r\n const header = [\r\n `<!-- spec-lite | ${meta.name} | DO NOT EDIT below the project-context block — managed by spec-lite -->`,\r\n `<!-- To update: run \"spec-lite update\" — your Project Context edits will be preserved -->`,\r\n \"\",\r\n ].join(\"\\n\");\r\n\r\n return header + content;\r\n }\r\n\r\n async detectExisting(workspaceRoot: string): Promise<string[]> {\r\n const existing: string[] = [];\r\n\r\n // Check for claude prompts directory\r\n const claudePromptsDir = path.join(\r\n workspaceRoot,\r\n \".claude\",\r\n \"prompts\"\r\n );\r\n if (await fs.pathExists(claudePromptsDir)) {\r\n const files = await fs.readdir(claudePromptsDir);\r\n for (const f of files) {\r\n if (f.endsWith(\".md\")) {\r\n existing.push(path.join(\".claude\", \"prompts\", f));\r\n }\r\n }\r\n }\r\n\r\n // Check for root CLAUDE.md\r\n const rootFile = path.join(workspaceRoot, \"CLAUDE.md\");\r\n if (await fs.pathExists(rootFile)) {\r\n existing.push(\"CLAUDE.md\");\r\n }\r\n\r\n return existing;\r\n }\r\n\r\n async getMemorySeedSource(\r\n workspaceRoot: string\r\n ): Promise<{ path: string; label: string } | null> {\r\n const p = path.join(workspaceRoot, \"CLAUDE.md\");\r\n if (await fs.pathExists(p)) {\r\n return { path: \"CLAUDE.md\", label: \"Claude root instructions (CLAUDE.md)\" };\r\n }\r\n return null;\r\n }\r\n\r\n getPostInitMessage(): string {\r\n return [\r\n \"\",\r\n \"📋 Claude Code setup complete!\",\r\n \"\",\r\n \" Your sub-agent prompts are in .claude/prompts/\",\r\n \" A root CLAUDE.md has been created with references to the sub-agents.\",\r\n \"\",\r\n \" How to use:\",\r\n \" 1. Claude Code automatically reads CLAUDE.md for project context\",\r\n ' 2. Reference specific sub-agents: \"Use the planner from .claude/prompts/planner.md\"',\r\n \" 3. Customize the Project Context block in each file for your project\",\r\n \"\",\r\n ].join(\"\\n\");\r\n }\r\n}\r\n\r\n/**\r\n * Generate the root CLAUDE.md content that references spec-lite sub-agents.\r\n */\r\nexport function generateClaudeRootMd(\r\n installedPrompts: string[]\r\n): string {\r\n const lines = [\r\n \"<!-- spec-lite managed — regenerated on spec-lite init/update -->\",\r\n \"\",\r\n \"# Project Instructions\",\r\n \"\",\r\n \"This project uses [spec-lite](https://github.com/ranjithab/spec-lite) sub-agent prompts\",\r\n \"for structured software engineering workflows.\",\r\n \"\",\r\n \"## Available Sub-Agents\",\r\n \"\",\r\n \"The following specialist sub-agents are available in `.claude/prompts/`:\",\r\n \"\",\r\n ];\r\n\r\n for (const name of installedPrompts) {\r\n lines.push(`- [${name}](.claude/prompts/${name}.md)`);\r\n }\r\n\r\n lines.push(\r\n \"\",\r\n \"## Usage\",\r\n \"\",\r\n \"To use a sub-agent, reference its prompt file in your conversation:\",\r\n \"\",\r\n '```text',\r\n \"Use the planner from .claude/prompts/planner.md to create a technical plan for this project.\",\r\n '```',\r\n \"\",\r\n \"## Output Directory\",\r\n \"\",\r\n \"Sub-agent outputs are written to the `.spec-lite/` directory:\",\r\n \"\",\r\n \"```text\",\r\n \".spec-lite/\",\r\n \"├── brainstorm.md\",\r\n \"├── plan.md # Default plan (simple projects)\",\r\n \"├── plan_<name>.md # Named plans (complex projects)\",\r\n \"├── TODO.md\",\r\n \"├── features/\",\r\n \"└── reviews/\",\r\n \"```\",\r\n \"\"\r\n );\r\n\r\n return lines.join(\"\\n\");\r\n}\r\n","import path from \"path\";\r\nimport fs from \"fs-extra\";\r\nimport type { Provider, PromptMeta } from \"./base.js\";\r\n\r\n/**\r\n * Generic provider — for manual usage or unsupported AI tools.\r\n *\r\n * Writes prompts to `.spec-lite/prompts/` as raw markdown.\r\n * Users can copy-paste these into any LLM chat.\r\n */\r\nexport class GenericProvider implements Provider {\r\n name = \"Generic\";\r\n alias = \"generic\";\r\n description = \"Raw prompts in .spec-lite/prompts/ (copy-paste into any LLM)\";\r\n\r\n getTargetPath(promptName: string): string {\r\n return path.join(\".spec-lite\", \"prompts\", `${promptName}.md`);\r\n }\r\n\r\n transformPrompt(content: string, meta: PromptMeta): string {\r\n // No transformation — copy as-is with a light header\r\n const header = [\r\n `<!-- spec-lite | ${meta.name} | managed by spec-lite -->`,\r\n `<!-- To update: run \"spec-lite update\" -->`,\r\n \"\",\r\n ].join(\"\\n\");\r\n\r\n return header + content;\r\n }\r\n\r\n async detectExisting(workspaceRoot: string): Promise<string[]> {\r\n const existing: string[] = [];\r\n const dir = path.join(workspaceRoot, \".spec-lite\", \"prompts\");\r\n\r\n if (await fs.pathExists(dir)) {\r\n const files = await fs.readdir(dir);\r\n for (const f of files) {\r\n if (f.endsWith(\".md\")) {\r\n existing.push(path.join(\".spec-lite\", \"prompts\", f));\r\n }\r\n }\r\n }\r\n\r\n return existing;\r\n }\r\n\r\n async getMemorySeedSource(\r\n _workspaceRoot: string\r\n ): Promise<{ path: string; label: string } | null> {\r\n // Generic provider has no canonical instruction file to seed from\r\n return null;\r\n }\r\n\r\n getPostInitMessage(): string {\r\n return [\r\n \"\",\r\n \"📋 Generic setup complete!\",\r\n \"\",\r\n \" Your sub-agent prompts are in .spec-lite/prompts/\",\r\n \"\",\r\n \" How to use:\",\r\n \" 1. Open any prompt file and copy its content\",\r\n \" 2. Paste into your LLM of choice (ChatGPT, Claude, Gemini, etc.)\",\r\n \" 3. Fill in the Project Context section for your project\",\r\n \" 4. Start the conversation with your requirements\",\r\n \"\",\r\n ].join(\"\\n\");\r\n }\r\n}\r\n","import type { Provider } from \"./base.js\";\r\nimport { CopilotProvider } from \"./copilot.js\";\r\nimport { ClaudeCodeProvider } from \"./claude-code.js\";\r\nimport { GenericProvider } from \"./generic.js\";\r\n\r\n/**\r\n * Registry of all supported AI provider adapters.\r\n */\r\nconst providers: Provider[] = [\r\n new CopilotProvider(),\r\n new ClaudeCodeProvider(),\r\n new GenericProvider(),\r\n];\r\n\r\n/**\r\n * Get a provider by its CLI alias (e.g., \"copilot\", \"claude-code\", \"generic\").\r\n */\r\nexport function getProvider(alias: string): Provider | undefined {\r\n return providers.find((p) => p.alias === alias);\r\n}\r\n\r\n/**\r\n * Get all registered providers.\r\n */\r\nexport function getAllProviders(): Provider[] {\r\n return [...providers];\r\n}\r\n\r\n/**\r\n * Get a formatted list of provider aliases for display.\r\n */\r\nexport function getProviderAliases(): string[] {\r\n return providers.map((p) => p.alias);\r\n}\r\n\r\n// Re-export types\r\nexport type { Provider, PromptMeta, SpecLiteConfig } from \"./base.js\";\r\n","import path from \"path\";\r\nimport fs from \"fs-extra\";\r\nimport { fileURLToPath } from \"url\";\r\n\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = path.dirname(__filename);\r\n\r\n/** Path to the bundled prompts directory (shipped with the npm package) */\r\nexport function getPromptsDir(): string {\r\n // In the built output (tsup bundles to dist/index.js),\r\n // __dirname resolves to dist/ — prompts/ is one level up at the package root\r\n return path.resolve(__dirname, \"..\", \"prompts\");\r\n}\r\n\r\n/** Metadata extracted from prompt files */\r\nexport interface PromptFile {\r\n /** File name without extension */\r\n name: string;\r\n /** Full file path */\r\n filePath: string;\r\n /** Raw markdown content */\r\n content: string;\r\n /** Extracted title */\r\n title: string;\r\n /** Extracted description */\r\n description: string;\r\n}\r\n\r\n/** Map of prompt names to their human titles and descriptions */\r\nexport const PROMPT_CATALOG: Record<string, { title: string; description: string; output?: string }> = {\r\n spec_help: {\r\n title: \"Spec Help\",\r\n description: \"Lists available sub-agents, their purpose, inputs, and outputs\",\r\n output: \"(interactive guide)\",\r\n },\r\n brainstorm: {\r\n title: \"Brainstorm\",\r\n description: \"Refines a vague idea into a clear, actionable vision\",\r\n output: \".spec-lite/brainstorm.md\",\r\n },\r\n planner: {\r\n title: \"Planner\",\r\n description: \"Creates a detailed technical blueprint from requirements\",\r\n output: \".spec-lite/plan.md or .spec-lite/plan_<name>.md\",\r\n },\r\n feature: {\r\n title: \"Feature\",\r\n description: \"Breaks one feature into granular, verifiable vertical slices\",\r\n output: \".spec-lite/features/feature_<name>.md\",\r\n },\r\n implement: {\r\n title: \"Implement\",\r\n description: \"Picks up a feature spec and executes its tasks with code\",\r\n output: \"Working code + updated feature spec\",\r\n },\r\n code_review: {\r\n title: \"Code Review\",\r\n description: \"Reviews code for correctness, architecture, and readability\",\r\n output: \".spec-lite/reviews/code_review_<name>.md\",\r\n },\r\n security_audit: {\r\n title: \"Security Audit\",\r\n description: \"Scans for vulnerabilities, misconfigurations, and security risks\",\r\n output: \".spec-lite/reviews/security_audit_<scope>.md\",\r\n },\r\n performance_review: {\r\n title: \"Performance Review\",\r\n description: \"Identifies bottlenecks and optimization opportunities\",\r\n output: \".spec-lite/reviews/performance_review_<scope>.md\",\r\n },\r\n integration_tests: {\r\n title: \"Integration Tests\",\r\n description: \"Writes traceable integration test scenarios from feature specs\",\r\n output: \"tests/\",\r\n },\r\n unit_tests: {\r\n title: \"Unit Tests\",\r\n description: \"Generates comprehensive unit tests with edge-case coverage and smart coverage exclusions\",\r\n output: \".spec-lite/features/unit_tests_<name>.md\",\r\n },\r\n devops: {\r\n title: \"DevOps\",\r\n description: \"Sets up Docker, CI/CD, environments, and deployment\",\r\n output: \"Project infrastructure files\",\r\n },\r\n fix: {\r\n title: \"Fix & Refactor\",\r\n description: \"Debugs issues or restructures code safely\",\r\n output: \"Targeted fixes with verification\",\r\n },\r\n memorize: {\r\n title: \"Memorize\",\r\n description:\r\n \"Stores standing instructions that all sub-agents enforce. Use `/memorize bootstrap` to auto-generate from project analysis.\",\r\n output: \".spec-lite/memory.md\",\r\n },\r\n technical_docs: {\r\n title: \"Technical Docs\",\r\n description: \"Creates deep architecture documentation for developers\",\r\n output: \"docs/technical_architecture.md\",\r\n },\r\n readme: {\r\n title: \"README\",\r\n description: \"Writes the project README and optional user guide\",\r\n output: \"README.md + docs/user_guide.md\",\r\n },\r\n architect: {\r\n title: \"Architect\",\r\n description:\r\n \"Designs cloud infrastructure, database strategy, and scaling architecture with Mermaid diagrams\",\r\n output: \".spec-lite/architect_<name>.md\",\r\n },\r\n};\r\n\r\n/** Non-agent files to skip */\r\nconst SKIP_FILES = new Set([\"orchestrator\"]);\r\n\r\n/**\r\n * Load all available prompt files from the bundled prompts directory.\r\n * Excludes non-agent files (orchestrator).\r\n */\r\nexport async function loadPrompts(\r\n exclude: string[] = []\r\n): Promise<PromptFile[]> {\r\n const promptsDir = getPromptsDir();\r\n const excludeSet = new Set([...exclude, ...SKIP_FILES]);\r\n\r\n const files = await fs.readdir(promptsDir);\r\n const prompts: PromptFile[] = [];\r\n\r\n for (const file of files) {\r\n if (!file.endsWith(\".md\")) continue;\r\n\r\n const name = file.replace(\".md\", \"\");\r\n if (excludeSet.has(name)) continue;\r\n\r\n const filePath = path.join(promptsDir, file);\r\n const content = await fs.readFile(filePath, \"utf-8\");\r\n const catalog = PROMPT_CATALOG[name];\r\n\r\n prompts.push({\r\n name,\r\n filePath,\r\n content,\r\n title: catalog?.title ?? name,\r\n description: catalog?.description ?? \"\",\r\n });\r\n }\r\n\r\n return prompts;\r\n}\r\n\r\n/**\r\n * Get the list of all available prompt names.\r\n */\r\nexport function getAvailablePromptNames(): string[] {\r\n return Object.keys(PROMPT_CATALOG);\r\n}\r\n\r\n/**\r\n * Get the full prompt catalog (for display in CLI list command).\r\n */\r\nexport function getPromptCatalog(): Record<string, { title: string; description: string; output?: string }> {\r\n return PROMPT_CATALOG;\r\n}\r\n\r\n/**\r\n * Project Context markers used to preserve user edits during updates.\r\n */\r\nexport const CONTEXT_START_MARKER = \"<!-- project-context-start -->\";\r\nexport const CONTEXT_END_MARKER = \"<!-- project-context-end -->\";\r\n\r\n/**\r\n * Extract the Project Context block from a prompt.\r\n * Returns the content between markers, or null if not found.\r\n */\r\nexport function extractProjectContext(content: string): string | null {\r\n const startIdx = content.indexOf(CONTEXT_START_MARKER);\r\n const endIdx = content.indexOf(CONTEXT_END_MARKER);\r\n\r\n if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) return null;\r\n\r\n return content.substring(\r\n startIdx + CONTEXT_START_MARKER.length,\r\n endIdx\r\n );\r\n}\r\n\r\n/**\r\n * Replace the Project Context block in a prompt with new content.\r\n */\r\nexport function replaceProjectContext(\r\n content: string,\r\n newContext: string\r\n): string {\r\n const startIdx = content.indexOf(CONTEXT_START_MARKER);\r\n const endIdx = content.indexOf(CONTEXT_END_MARKER);\r\n\r\n if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) return content;\r\n\r\n return (\r\n content.substring(0, startIdx + CONTEXT_START_MARKER.length) +\r\n newContext +\r\n content.substring(endIdx)\r\n );\r\n}\r\n","import path from \"path\";\r\nimport fs from \"fs-extra\";\r\nimport { fileURLToPath } from \"url\";\r\n\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = path.dirname(__filename);\r\n\r\n/**\r\n * Path to the bundled stacks directory (shipped with the npm package).\r\n * In the built output (tsup bundles to dist/index.js),\r\n * __dirname resolves to dist/ — stacks/ is copied to dist/stacks/ during build.\r\n */\r\nexport function getStacksDir(): string {\r\n return path.resolve(__dirname, \"stacks\");\r\n}\r\n\r\n/**\r\n * Map of language names (lowercased) to their stack snippet filenames.\r\n * Supports common aliases so the questionnaire answer maps correctly.\r\n */\r\nconst LANGUAGE_MAP: Record<string, string> = {\r\n typescript: \"typescript.md\",\r\n ts: \"typescript.md\",\r\n javascript: \"typescript.md\",\r\n js: \"typescript.md\",\r\n \"node.js\": \"typescript.md\",\r\n node: \"typescript.md\",\r\n react: \"react.md\",\r\n \"react.js\": \"react.md\",\r\n \"next.js\": \"react.md\",\r\n nextjs: \"react.md\",\r\n python: \"python.md\",\r\n py: \"python.md\",\r\n \"c#\": \"dotnet.md\",\r\n csharp: \"dotnet.md\",\r\n \".net\": \"dotnet.md\",\r\n dotnet: \"dotnet.md\",\r\n java: \"java.md\",\r\n \"spring\": \"java.md\",\r\n \"spring boot\": \"java.md\",\r\n \"spring-boot\": \"java.md\",\r\n};\r\n\r\n/**\r\n * Get the bundled best-practice snippet for a given language.\r\n * Returns the markdown content if a matching snippet exists, or null if not.\r\n */\r\nexport function getStackSnippet(language: string): string | null {\r\n const key = language.toLowerCase().trim();\r\n const filename = LANGUAGE_MAP[key];\r\n\r\n if (!filename) return null;\r\n\r\n const filePath = path.join(getStacksDir(), filename);\r\n if (!fs.pathExistsSync(filePath)) return null;\r\n\r\n return fs.readFileSync(filePath, \"utf-8\");\r\n}\r\n\r\n/**\r\n * List all available stack snippet names (for display purposes).\r\n */\r\nexport function listAvailableStacks(): string[] {\r\n const stacksDir = getStacksDir();\r\n if (!fs.pathExistsSync(stacksDir)) return [];\r\n\r\n return fs\r\n .readdirSync(stacksDir)\r\n .filter((f) => f.endsWith(\".md\"))\r\n .map((f) => f.replace(\".md\", \"\"));\r\n}\r\n","import path from \"path\";\r\nimport fs from \"fs-extra\";\r\nimport chalk from \"chalk\";\r\nimport { getProvider } from \"../providers/index.js\";\r\nimport type { SpecLiteConfig } from \"../providers/base.js\";\r\nimport {\r\n loadPrompts,\r\n extractProjectContext,\r\n replaceProjectContext,\r\n} from \"../utils/prompts.js\";\r\nimport { generateClaudeRootMd } from \"../providers/claude-code.js\";\r\nimport { mergeCopilotInstructions } from \"../providers/copilot.js\";\r\n\r\ninterface UpdateOptions {\r\n force?: boolean;\r\n}\r\n\r\nexport async function updateCommand(options: UpdateOptions): Promise<void> {\r\n const cwd = process.cwd();\r\n\r\n console.log(chalk.bold(\"\\n⚡ spec-lite update\\n\"));\r\n\r\n // 1. Read existing config\r\n const configPath = path.join(cwd, \".spec-lite.json\");\r\n if (!(await fs.pathExists(configPath))) {\r\n console.error(\r\n chalk.red(\r\n ' No .spec-lite.json found. Run \"spec-lite init\" first.'\r\n )\r\n );\r\n process.exit(1);\r\n }\r\n\r\n const config: SpecLiteConfig = await fs.readJson(configPath);\r\n const provider = getProvider(config.provider);\r\n\r\n if (!provider) {\r\n console.error(\r\n chalk.red(\r\n ` Unknown provider \"${config.provider}\" in .spec-lite.json. Re-run \"spec-lite init\".`\r\n )\r\n );\r\n process.exit(1);\r\n }\r\n\r\n console.log(chalk.cyan(` Provider: ${provider.name}`));\r\n console.log(\r\n chalk.dim(` Installed: ${config.installedPrompts.length} prompts`)\r\n );\r\n\r\n // 2. Load latest prompts (only the ones that were previously installed)\r\n const allPrompts = await loadPrompts();\r\n const installedSet = new Set(config.installedPrompts);\r\n const prompts = allPrompts.filter((p) => installedSet.has(p.name));\r\n\r\n let updated = 0;\r\n let preserved = 0;\r\n let unchanged = 0;\r\n let migrated = 0;\r\n\r\n for (const prompt of prompts) {\r\n const targetRelPath = provider.getTargetPath(prompt.name);\r\n const targetAbsPath = path.join(cwd, targetRelPath);\r\n\r\n // Migration: if copilot provider, check for old-format .md files and rename to .prompt.md\r\n if (provider.alias === \"copilot\") {\r\n const oldRelPath = path.join(\".github\", \"copilot\", `${prompt.name}.md`);\r\n const oldAbsPath = path.join(cwd, oldRelPath);\r\n if (\r\n targetRelPath !== oldRelPath &&\r\n (await fs.pathExists(oldAbsPath)) &&\r\n !(await fs.pathExists(targetAbsPath))\r\n ) {\r\n await fs.ensureDir(path.dirname(targetAbsPath));\r\n await fs.rename(oldAbsPath, targetAbsPath);\r\n console.log(\r\n chalk.cyan(\r\n ` ↗ ${oldRelPath} → ${targetRelPath} (migrated to .prompt.md)`\r\n )\r\n );\r\n migrated++;\r\n }\r\n }\r\n\r\n // Transform the new prompt content\r\n const newContent = provider.transformPrompt(prompt.content, {\r\n name: prompt.name,\r\n title: prompt.title,\r\n description: prompt.description,\r\n });\r\n\r\n if (!(await fs.pathExists(targetAbsPath))) {\r\n // File was deleted by user — re-create it\r\n await fs.ensureDir(path.dirname(targetAbsPath));\r\n await fs.writeFile(targetAbsPath, newContent, \"utf-8\");\r\n console.log(chalk.green(` ✓ ${targetRelPath} (restored)`));\r\n updated++;\r\n continue;\r\n }\r\n\r\n // Read current installed version\r\n const currentContent = await fs.readFile(targetAbsPath, \"utf-8\");\r\n\r\n // Check if content is identical (no update needed)\r\n if (currentContent === newContent) {\r\n unchanged++;\r\n continue;\r\n }\r\n\r\n // Try to preserve user's Project Context edits\r\n if (!options.force) {\r\n const userContext = extractProjectContext(currentContent);\r\n if (userContext) {\r\n const mergedContent = replaceProjectContext(newContent, userContext);\r\n await fs.writeFile(targetAbsPath, mergedContent, \"utf-8\");\r\n console.log(\r\n chalk.green(\r\n ` ✓ ${targetRelPath} (updated, Project Context preserved)`\r\n )\r\n );\r\n preserved++;\r\n updated++;\r\n continue;\r\n }\r\n }\r\n\r\n // No context block found or --force — full overwrite\r\n await fs.writeFile(targetAbsPath, newContent, \"utf-8\");\r\n console.log(chalk.green(` ✓ ${targetRelPath} (updated)`));\r\n updated++;\r\n }\r\n\r\n // 3. Update provider-specific extras\r\n if (provider.alias === \"claude-code\") {\r\n const claudeMdPath = path.join(cwd, \"CLAUDE.md\");\r\n const claudeMdContent = generateClaudeRootMd(config.installedPrompts);\r\n await fs.writeFile(claudeMdPath, claudeMdContent, \"utf-8\");\r\n console.log(chalk.green(` ✓ CLAUDE.md (regenerated)`));\r\n }\r\n\r\n if (provider.alias === \"copilot\") {\r\n const copilotInstructionsPath = path.join(cwd, \".github\", \"copilot-instructions.md\");\r\n await fs.ensureDir(path.join(cwd, \".github\"));\r\n const existingContent = (await fs.pathExists(copilotInstructionsPath))\r\n ? await fs.readFile(copilotInstructionsPath, \"utf-8\")\r\n : null;\r\n const merged = mergeCopilotInstructions(existingContent, config.installedPrompts);\r\n await fs.writeFile(copilotInstructionsPath, merged, \"utf-8\");\r\n console.log(chalk.green(` ✓ .github/copilot-instructions.md (updated)`));\r\n }\r\n\r\n // 4. Update config timestamp\r\n config.updatedAt = new Date().toISOString();\r\n try {\r\n const { createRequire } = await import(\"module\");\r\n const require = createRequire(import.meta.url);\r\n const pkg = require(\"../../package.json\");\r\n config.version = pkg.version;\r\n } catch {\r\n // Keep existing version\r\n }\r\n await fs.writeJson(configPath, config, { spaces: 2 });\r\n\r\n // 5. Summary\r\n console.log(\r\n chalk.bold(\r\n `\\n Done! ${updated} updated, ${unchanged} unchanged, ${preserved} with preserved edits${migrated > 0 ? `, ${migrated} migrated` : \"\"}.`\r\n )\r\n );\r\n}\r\n","import chalk from \"chalk\";\r\nimport { getPromptCatalog } from \"../utils/prompts.js\";\r\n\r\nexport async function listCommand(): Promise<void> {\r\n const catalog = getPromptCatalog();\r\n\r\n console.log(chalk.bold(\"\\n⚡ spec-lite — Available Sub-Agents\\n\"));\r\n\r\n console.log(\r\n chalk.dim(\r\n \" Each sub-agent is a specialist prompt for one phase of the development lifecycle.\\n\"\r\n )\r\n );\r\n\r\n // Calculate column widths\r\n const entries = Object.entries(catalog);\r\n const maxName = Math.max(...entries.map(([name]) => name.length), 4);\r\n const maxTitle = Math.max(\r\n ...entries.map(([, v]) => v.title.length),\r\n 5\r\n );\r\n\r\n // Header\r\n const header = ` ${\"Name\".padEnd(maxName + 2)}${\"Title\".padEnd(maxTitle + 2)}${\"Description\"}`;\r\n console.log(chalk.cyan(header));\r\n console.log(chalk.dim(` ${\"─\".repeat(header.trim().length + 10)}`));\r\n\r\n // Rows\r\n for (const [name, meta] of entries) {\r\n const nameCol = chalk.green(name.padEnd(maxName + 2));\r\n const titleCol = chalk.white(meta.title.padEnd(maxTitle + 2));\r\n const descCol = chalk.dim(meta.description);\r\n console.log(` ${nameCol}${titleCol}${descCol}`);\r\n if (meta.output) {\r\n console.log(\r\n ` ${\"\".padEnd(maxName + 2)}${\"\".padEnd(maxTitle + 2)}${chalk.dim(`→ ${meta.output}`)}`\r\n );\r\n }\r\n }\r\n\r\n console.log(\r\n chalk.dim(\r\n `\\n ${entries.length} sub-agents available. Run \"spec-lite init\" to install them.\\n`\r\n )\r\n );\r\n\r\n // Pipeline\r\n console.log(chalk.bold(\" Recommended Pipeline:\\n\"));\r\n console.log(\r\n chalk.dim(\r\n \" Brainstorm → Planner → Feature (×N) → Reviews → Tests → DevOps → Docs\"\r\n )\r\n );\r\n console.log(\r\n chalk.dim(\r\n \" (Not every project needs every sub-agent. Start with Planner if you have clear requirements.)\\n\"\r\n )\r\n );\r\n}\r\n"],"mappings":"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","names":["path","fs","path","fs","path","fs","path","fs","path","fs","fileURLToPath","__filename","__dirname","providers","path","fs","pkg","createRequire","require","path","fs","chalk","chalk","path","fs","createRequire","require","pkg","chalk","chalk","require"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/providers/copilot.ts","../src/providers/claude-code.ts","../src/providers/generic.ts","../src/providers/index.ts","../src/utils/prompts.ts","../src/utils/stacks.ts","../src/commands/update.ts","../src/commands/list.ts"],"sourcesContent":["import { Command } from \"commander\";\r\nimport { initCommand } from \"./commands/init.js\";\r\nimport { updateCommand } from \"./commands/update.js\";\r\nimport { listCommand } from \"./commands/list.js\";\r\nimport { createRequire } from \"module\";\r\n\r\nconst require = createRequire(import.meta.url);\r\nconst pkg = require(\"../package.json\");\r\n\r\nconst program = new Command();\r\n\r\nprogram\r\n .name(\"spec-lite\")\r\n .description(\r\n \"Install structured AI sub-agent prompts into your workspace for any AI coding assistant\"\r\n )\r\n .version(pkg.version);\r\n\r\nprogram\r\n .command(\"init\")\r\n .description(\"Initialize spec-lite sub-agent prompts in your workspace\")\r\n .option(\r\n \"--ai <provider>\",\r\n \"AI provider to configure for (copilot, claude-code, generic)\"\r\n )\r\n .option(\r\n \"--exclude <prompts>\",\r\n \"Comma-separated list of prompts to exclude (e.g., brainstorm,readme)\"\r\n )\r\n .option(\"--force\", \"Overwrite existing files without prompting\", false)\r\n .option(\r\n \"--skip-profile\",\r\n \"Skip the project profile questionnaire (for CI/scripting)\"\r\n )\r\n .action(initCommand);\r\n\r\nprogram\r\n .command(\"update\")\r\n .description(\r\n \"Update spec-lite prompts to the latest version, preserving your Project Context edits\"\r\n )\r\n .option(\"--force\", \"Overwrite all files including user-modified ones\", false)\r\n .action(updateCommand);\r\n\r\nprogram\r\n .command(\"list\")\r\n .description(\"List all available spec-lite sub-agents and their purpose\")\r\n .action(listCommand);\r\n\r\nprogram.parse();\r\n","import path from \"path\";\r\nimport fs from \"fs-extra\";\r\nimport chalk from \"chalk\";\r\nimport inquirer from \"inquirer\";\r\nimport { getProvider, getAllProviders } from \"../providers/index.js\";\r\nimport type { SpecLiteConfig, ProjectProfile } from \"../providers/base.js\";\r\nimport { loadPrompts, replaceProjectContext } from \"../utils/prompts.js\";\r\nimport { generateClaudeRootMd } from \"../providers/claude-code.js\";\r\nimport { CopilotProvider, mergeCopilotInstructions } from \"../providers/copilot.js\";\r\nimport { getStackSnippet } from \"../utils/stacks.js\";\r\n\r\ninterface InitOptions {\r\n ai?: string;\r\n exclude?: string;\r\n force?: boolean;\r\n skipProfile?: boolean;\r\n}\r\n\r\nconst LANGUAGE_CHOICES = [\r\n { name: \"TypeScript\", value: \"TypeScript\" },\r\n { name: \"Python\", value: \"Python\" },\r\n { name: \"Java\", value: \"Java\" },\r\n { name: \"C# / .NET\", value: \"C#\" },\r\n { name: \"Go\", value: \"Go\" },\r\n { name: \"Rust\", value: \"Rust\" },\r\n { name: \"Other (specify below)\", value: \"__other__\" },\r\n];\r\n\r\nconst ARCHITECTURE_CHOICES = [\r\n { name: \"Monolith\", value: \"Monolith\" },\r\n { name: \"Microservices\", value: \"Microservices\" },\r\n { name: \"Serverless\", value: \"Serverless\" },\r\n { name: \"Monorepo\", value: \"Monorepo\" },\r\n { name: \"Other (specify below)\", value: \"__other__\" },\r\n];\r\n\r\n/**\r\n * Collect project profile via interactive questionnaire.\r\n * Returns a ProjectProfile with the user's answers.\r\n */\r\nasync function collectProjectProfile(): Promise<ProjectProfile> {\r\n console.log(\r\n chalk.cyan(\r\n \"\\n 📋 Project Profile — a few questions to personalize your setup:\\n\"\r\n )\r\n );\r\n\r\n const answers = await inquirer.prompt([\r\n {\r\n type: \"list\",\r\n name: \"language\",\r\n message: \"Primary programming language?\",\r\n choices: LANGUAGE_CHOICES,\r\n },\r\n {\r\n type: \"input\",\r\n name: \"languageOther\",\r\n message: \"Specify your primary language:\",\r\n when: (prev: Record<string, string>) => prev.language === \"__other__\",\r\n validate: (input: string) =>\r\n input.trim() ? true : \"Please enter a language.\",\r\n },\r\n {\r\n type: \"input\",\r\n name: \"frameworks\",\r\n message:\r\n 'Framework(s) in use? (e.g., \"Express + React\", \"FastAPI\", \"ASP.NET Core\")',\r\n default: \"None / not sure yet\",\r\n },\r\n {\r\n type: \"input\",\r\n name: \"testFramework\",\r\n message:\r\n 'Testing framework? (e.g., \"Jest\", \"Vitest\", \"pytest\", \"xUnit\")',\r\n default: \"Not decided yet\",\r\n },\r\n {\r\n type: \"list\",\r\n name: \"architecture\",\r\n message: \"Architectural pattern?\",\r\n choices: ARCHITECTURE_CHOICES,\r\n },\r\n {\r\n type: \"input\",\r\n name: \"architectureOther\",\r\n message: \"Specify your architectural pattern:\",\r\n when: (prev: Record<string, string>) => prev.architecture === \"__other__\",\r\n validate: (input: string) =>\r\n input.trim() ? true : \"Please enter a pattern.\",\r\n },\r\n {\r\n type: \"input\",\r\n name: \"conventions\",\r\n message:\r\n 'Any specific coding conventions? (e.g., \"Airbnb style guide\", \"PEP 8\") — leave blank if none',\r\n default: \"\",\r\n },\r\n ]);\r\n\r\n return {\r\n language:\r\n answers.language === \"__other__\"\r\n ? answers.languageOther.trim()\r\n : answers.language,\r\n frameworks: answers.frameworks.trim(),\r\n testFramework: answers.testFramework.trim(),\r\n architecture:\r\n answers.architecture === \"__other__\"\r\n ? answers.architectureOther.trim()\r\n : answers.architecture,\r\n conventions: answers.conventions.trim(),\r\n };\r\n}\r\n\r\n/**\r\n * Build a Project Context block string from a ProjectProfile.\r\n * This replaces the placeholder content inside <!-- project-context-start/end --> markers.\r\n */\r\nfunction buildProjectContextBlock(profile: ProjectProfile): string {\r\n const lines = [\r\n \"\",\r\n \"## Project Context (Customize per project)\",\r\n \"\",\r\n \"> Auto-populated by spec-lite init. Edit these values as your project evolves.\",\r\n \"\",\r\n `- **Language(s)**: ${profile.language}`,\r\n `- **Framework(s)**: ${profile.frameworks}`,\r\n `- **Test Framework**: ${profile.testFramework}`,\r\n `- **Architecture**: ${profile.architecture}`,\r\n ];\r\n if (profile.conventions) {\r\n lines.push(`- **Conventions**: ${profile.conventions}`);\r\n }\r\n lines.push(\"\");\r\n return lines.join(\"\\n\");\r\n}\r\n\r\n/**\r\n * Build a seeded .spec-lite/memory.md from raw content scraped from a provider's\r\n * existing instructions file (e.g. copilot-instructions.md, CLAUDE.md).\r\n * The file is intentionally unstructured — /memorize bootstrap will organize it.\r\n */\r\nfunction buildSeededMemory(\r\n sourceContent: string,\r\n sourcePath: string,\r\n version: string\r\n): string {\r\n const date = new Date().toISOString().split(\"T\")[0];\r\n return [\r\n `<!-- Generated by spec-lite v${version} | sub-agent: memorize | seeded-from: ${sourcePath} | updated: ${date} -->`,\r\n \"\",\r\n \"# Memory — Standing Instructions\",\r\n \"\",\r\n `> These instructions were **auto-seeded** from \\`${sourcePath}\\` during \\`spec-lite init\\`.`,\r\n \"> They have not yet been organized into sections.\",\r\n \"> Run \\`/memorize bootstrap\\` in your AI assistant to review, reorganize, and refine them.\",\r\n \">\",\r\n \"> Memory is the **authoritative source** for coding standards, architecture, testing, logging, and security.\",\r\n \"> Plans may contain plan-specific overrides but should not duplicate these rules.\",\r\n \"> Managed by the Memorize sub-agent. Do not edit section headers manually.\",\r\n \"> To add or change instructions, invoke: `/memorize <your instructions>`\",\r\n \"> To override: `/memorize override <your instructions>`\",\r\n \"> To generate from project analysis: `/memorize bootstrap`\",\r\n \"\",\r\n `<!-- seed-start: raw content imported from ${sourcePath} -->`,\r\n \"\",\r\n `## Imported from \\`${sourcePath}\\``,\r\n \"\",\r\n sourceContent.trim(),\r\n \"\",\r\n \"<!-- seed-end -->\",\r\n \"\",\r\n ].join(\"\\n\");\r\n}\r\n\r\nexport async function initCommand(options: InitOptions): Promise<void> {\r\n const cwd = process.cwd();\r\n\r\n console.log(chalk.bold(\"\\n⚡ spec-lite init\\n\"));\r\n\r\n // 1. Resolve provider\r\n let providerAlias = options.ai;\r\n\r\n if (!providerAlias) {\r\n const providers = getAllProviders();\r\n const answer = await inquirer.prompt([\r\n {\r\n type: \"list\",\r\n name: \"provider\",\r\n message: \"Which AI coding assistant are you using?\",\r\n choices: providers.map((p) => ({\r\n name: `${p.name} — ${p.description}`,\r\n value: p.alias,\r\n })),\r\n },\r\n ]);\r\n providerAlias = answer.provider as string;\r\n }\r\n\r\n const provider = getProvider(providerAlias!);\r\n if (!provider) {\r\n console.error(\r\n chalk.red(\r\n `Unknown provider: \"${providerAlias}\". Available: ${getAllProviders()\r\n .map((p) => p.alias)\r\n .join(\", \")}`\r\n )\r\n );\r\n process.exit(1);\r\n }\r\n\r\n console.log(chalk.cyan(` Provider: ${provider.name}`));\r\n\r\n // 2. Collect project profile (unless --skip-profile)\r\n let projectProfile: ProjectProfile | undefined;\r\n if (!options.skipProfile) {\r\n projectProfile = await collectProjectProfile();\r\n console.log(chalk.green(\" ✓ Project profile collected\"));\r\n } else {\r\n console.log(chalk.dim(\" Skipping project profile questionnaire.\"));\r\n }\r\n\r\n // 3. Parse exclusions (split on commas or spaces to handle both bash and PowerShell)\r\n const exclude = options.exclude\r\n ? options.exclude.split(/[,\\s]+/).map((s) => s.trim()).filter(Boolean)\r\n : [];\r\n\r\n if (exclude.length > 0) {\r\n console.log(chalk.dim(` Excluding: ${exclude.join(\", \")}`));\r\n }\r\n\r\n // 3b. Capture pre-existing seed content (before we write anything to the provider's instructions file)\r\n const memorySeedSource = await provider.getMemorySeedSource(cwd);\r\n let preSeedContent: string | null = null;\r\n if (memorySeedSource) {\r\n const seedAbsPath = path.join(cwd, memorySeedSource.path);\r\n if (await fs.pathExists(seedAbsPath)) {\r\n preSeedContent = await fs.readFile(seedAbsPath, \"utf-8\");\r\n }\r\n }\r\n\r\n // 4. Check for existing files\r\n const existingFiles = await provider.detectExisting(cwd);\r\n let globalAction: \"overwrite\" | \"skip\" | null = null;\r\n\r\n if (existingFiles.length > 0 && !options.force) {\r\n console.log(\r\n chalk.yellow(\r\n `\\n Found existing instruction files:\\n${existingFiles\r\n .map((f) => ` - ${f}`)\r\n .join(\"\\n\")}`\r\n )\r\n );\r\n\r\n const answer = await inquirer.prompt([\r\n {\r\n type: \"list\",\r\n name: \"action\",\r\n message: \"How should we handle existing files?\",\r\n choices: [\r\n {\r\n name: \"Overwrite — replace all existing files\",\r\n value: \"overwrite\",\r\n },\r\n {\r\n name: \"Skip — only write files that don't exist yet\",\r\n value: \"skip\",\r\n },\r\n { name: \"Abort — cancel initialization\", value: \"abort\" },\r\n ],\r\n },\r\n ]);\r\n\r\n if (answer.action === \"abort\") {\r\n console.log(chalk.dim(\" Aborted.\"));\r\n return;\r\n }\r\n\r\n globalAction = answer.action as \"overwrite\" | \"skip\";\r\n\r\n if (globalAction === \"skip\") {\r\n console.log(chalk.dim(\" Skipping existing files.\"));\r\n }\r\n }\r\n\r\n // 5. Build project context block (if profile was collected)\r\n const contextBlock = projectProfile\r\n ? buildProjectContextBlock(projectProfile)\r\n : null;\r\n\r\n // 6. Load and write prompts\r\n const prompts = await loadPrompts(exclude);\r\n let written = 0;\r\n let skipped = 0;\r\n const installedPrompts: string[] = [];\r\n\r\n for (const prompt of prompts) {\r\n const targetRelPath = provider.getTargetPath(prompt.name);\r\n const targetAbsPath = path.join(cwd, targetRelPath);\r\n\r\n // Skip if file exists and user chose \"skip\" globally\r\n if (\r\n !options.force &&\r\n existingFiles.includes(targetRelPath) &&\r\n globalAction === \"skip\"\r\n ) {\r\n skipped++;\r\n installedPrompts.push(prompt.name);\r\n continue;\r\n }\r\n\r\n // Inject project context into prompt if profile was collected\r\n let content = prompt.content;\r\n if (contextBlock) {\r\n content = replaceProjectContext(content, contextBlock);\r\n }\r\n\r\n const transformed = provider.transformPrompt(content, {\r\n name: prompt.name,\r\n title: prompt.title,\r\n description: prompt.description,\r\n });\r\n\r\n await fs.ensureDir(path.dirname(targetAbsPath));\r\n await fs.writeFile(targetAbsPath, transformed, \"utf-8\");\r\n written++;\r\n installedPrompts.push(prompt.name);\r\n\r\n console.log(chalk.green(` ✓ ${targetRelPath}`));\r\n }\r\n\r\n // 7. Provider-specific extras\r\n if (provider.alias === \"claude-code\") {\r\n const claudeMdPath = path.join(cwd, \"CLAUDE.md\");\r\n const claudeMdContent = generateClaudeRootMd(installedPrompts);\r\n await fs.writeFile(claudeMdPath, claudeMdContent, \"utf-8\");\r\n console.log(chalk.green(` ✓ CLAUDE.md`));\r\n written++;\r\n }\r\n\r\n if (provider.alias === \"copilot\") {\r\n const copilotProvider = provider as CopilotProvider;\r\n\r\n // Write .github/prompts/<name>.prompt.md (plain prompt files, no agent frontmatter)\r\n for (const prompt of prompts) {\r\n const promptRelPath = copilotProvider.getPromptFilePath(prompt.name);\r\n const promptAbsPath = path.join(cwd, promptRelPath);\r\n\r\n if (\r\n !options.force &&\r\n existingFiles.includes(promptRelPath) &&\r\n globalAction === \"skip\"\r\n ) {\r\n continue;\r\n }\r\n\r\n let content = prompt.content;\r\n if (contextBlock) {\r\n content = replaceProjectContext(content, contextBlock);\r\n }\r\n\r\n const transformed = copilotProvider.transformPromptFile(content, {\r\n name: prompt.name,\r\n title: prompt.title,\r\n description: prompt.description,\r\n });\r\n\r\n await fs.ensureDir(path.dirname(promptAbsPath));\r\n await fs.writeFile(promptAbsPath, transformed, \"utf-8\");\r\n written++;\r\n console.log(chalk.green(` ✓ ${promptRelPath}`));\r\n }\r\n\r\n // Write / update .github/copilot-instructions.md\r\n const copilotInstructionsPath = path.join(cwd, \".github\", \"copilot-instructions.md\");\r\n await fs.ensureDir(path.join(cwd, \".github\"));\r\n const existingContent = (await fs.pathExists(copilotInstructionsPath))\r\n ? await fs.readFile(copilotInstructionsPath, \"utf-8\")\r\n : null;\r\n const merged = mergeCopilotInstructions(existingContent, installedPrompts);\r\n await fs.writeFile(copilotInstructionsPath, merged, \"utf-8\");\r\n if (existingContent) {\r\n console.log(chalk.green(` ✓ .github/copilot-instructions.md (updated with spec-lite block)`));\r\n } else {\r\n console.log(chalk.green(` ✓ .github/copilot-instructions.md`));\r\n }\r\n written++;\r\n }\r\n\r\n // 8. Create .spec-lite/ directory structure for agent outputs\r\n const specDirs = [\r\n path.join(\".spec-lite\", \"features\"),\r\n path.join(\".spec-lite\", \"reviews\"),\r\n ];\r\n for (const dir of specDirs) {\r\n const absDir = path.join(cwd, dir);\r\n if (!(await fs.pathExists(absDir))) {\r\n await fs.ensureDir(absDir);\r\n console.log(chalk.green(` ✓ ${dir}/`));\r\n }\r\n }\r\n\r\n // 8b. Create .spec-lite/TODO.md skeleton\r\n const todoPath = path.join(cwd, \".spec-lite\", \"TODO.md\");\r\n if (!(await fs.pathExists(todoPath))) {\r\n const todoContent = [\r\n \"# TODO — Enhancements & Ideas\",\r\n \"\",\r\n \"> Discovered by sub-agents during planning and development.\",\r\n \"> Items here are out-of-scope for their current task but worth tracking.\",\r\n \"\",\r\n \"## General\",\r\n \"\",\r\n \"## General / Caching\",\r\n \"\",\r\n \"## UI\",\r\n \"\",\r\n \"## Performance\",\r\n \"\",\r\n \"## Security\",\r\n \"\",\r\n \"## DX (Developer Experience)\",\r\n \"\",\r\n ].join(\"\\n\");\r\n await fs.writeFile(todoPath, todoContent, \"utf-8\");\r\n console.log(chalk.green(` ✓ .spec-lite/TODO.md`));\r\n }\r\n\r\n // 9. Copy bundled stack snippet to .spec-lite/stacks/ (if profile was collected)\r\n if (projectProfile) {\r\n const snippet = getStackSnippet(projectProfile.language);\r\n if (snippet) {\r\n const stacksTargetDir = path.join(cwd, \".spec-lite\", \"stacks\");\r\n await fs.ensureDir(stacksTargetDir);\r\n const snippetFileName = `${projectProfile.language.toLowerCase().replace(/[^a-z0-9]/g, \"-\")}.md`;\r\n const snippetPath = path.join(stacksTargetDir, snippetFileName);\r\n\r\n if (await fs.pathExists(snippetPath) && !options.force) {\r\n console.log(\r\n chalk.dim(` – .spec-lite/stacks/${snippetFileName} already exists (kept your edits)`)\r\n );\r\n } else {\r\n await fs.writeFile(snippetPath, snippet, \"utf-8\");\r\n console.log(\r\n chalk.green(` ✓ .spec-lite/stacks/${snippetFileName}`)\r\n );\r\n console.log(\r\n chalk.dim(\" ↳ Edit this file to customize defaults before running /memorize bootstrap\")\r\n );\r\n written++;\r\n }\r\n }\r\n }\r\n\r\n // 9b. Offer to seed .spec-lite/memory.md from pre-existing provider instructions\r\n let memorySeedWritten = false;\r\n const memoryPath = path.join(cwd, \".spec-lite\", \"memory.md\");\r\n if (preSeedContent && memorySeedSource && !(await fs.pathExists(memoryPath))) {\r\n console.log(\r\n chalk.cyan(`\\n 💡 Found existing ${memorySeedSource.label} (${memorySeedSource.path}).`)\r\n );\r\n const seedAnswer = await inquirer.prompt([\r\n {\r\n type: \"confirm\",\r\n name: \"seedMemory\",\r\n message: `Seed .spec-lite/memory.md from it so /memorize bootstrap can refine your existing conventions?`,\r\n default: true,\r\n },\r\n ]);\r\n if (seedAnswer.seedMemory) {\r\n const seedPkg = await loadPackageVersion();\r\n const seededContent = buildSeededMemory(preSeedContent, memorySeedSource.path, seedPkg);\r\n await fs.ensureDir(path.join(cwd, \".spec-lite\"));\r\n await fs.writeFile(memoryPath, seededContent, \"utf-8\");\r\n memorySeedWritten = true;\r\n written++;\r\n console.log(chalk.green(` ✓ .spec-lite/memory.md (seeded from ${memorySeedSource.path})`));\r\n console.log(chalk.dim(\" ↳ Run /memorize bootstrap to organize and refine into standing instructions\"));\r\n }\r\n }\r\n\r\n // 10. Write .spec-lite.json config\r\n const pkg = await loadPackageVersion();\r\n const config: SpecLiteConfig = {\r\n version: pkg,\r\n provider: provider.alias,\r\n installedPrompts,\r\n installedAt: new Date().toISOString(),\r\n updatedAt: new Date().toISOString(),\r\n ...(projectProfile ? { projectProfile } : {}),\r\n };\r\n const configPath = path.join(cwd, \".spec-lite.json\");\r\n await fs.writeJson(configPath, config, { spaces: 2 });\r\n console.log(chalk.green(` ✓ .spec-lite.json`));\r\n\r\n // 11. Summary\r\n console.log(\r\n chalk.bold(\r\n `\\n Done! ${written} files written, ${skipped} skipped.`\r\n )\r\n );\r\n console.log(provider.getPostInitMessage());\r\n\r\n // 12. Bootstrap next-step guidance\r\n if (projectProfile || memorySeedWritten) {\r\n if (memorySeedWritten) {\r\n console.log(\r\n chalk.cyan(\r\n \"\\n 📌 Next step: Run \") +\r\n chalk.bold(\"/memorize bootstrap\") +\r\n chalk.cyan(\r\n \" in your AI assistant.\\n It will see your seeded memory and offer to merge or refine it\\n into properly organized standing instructions.\"\r\n )\r\n );\r\n } else {\r\n console.log(\r\n chalk.cyan(\r\n \"\\n 📌 Next step: Run \") +\r\n chalk.bold(\"/memorize bootstrap\") +\r\n chalk.cyan(\r\n \" in your AI assistant to auto-generate\\n coding standards, architecture guidelines, and best practices\\n for your project based on the profile you just provided.\"\r\n )\r\n );\r\n }\r\n }\r\n}\r\n\r\nasync function loadPackageVersion(): Promise<string> {\r\n try {\r\n const { createRequire } = await import(\"module\");\r\n const require = createRequire(import.meta.url);\r\n const pkg = require(\"../../package.json\");\r\n return pkg.version;\r\n } catch {\r\n return \"0.0.4\";\r\n }\r\n}\r\n","import path from \"path\";\r\nimport fs from \"fs-extra\";\r\nimport type { Provider, PromptMeta } from \"./base.js\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// Handoffs map — derived from the orchestrator pipeline.\r\n// Each key is a prompt name and the value is an ordered list of suggested\r\n// next-step handoffs. Agent identifiers use the \"spec.<name>\" convention\r\n// (matching the file name without the \".agent.md\" suffix).\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface Handoff {\r\n label: string;\r\n agent: string;\r\n prompt: string;\r\n}\r\n\r\nconst AGENT_HANDOFFS: Record<string, Handoff[]> = {\r\n spec_help: [],\r\n brainstorm: [\r\n {\r\n label: \"Create Plan\",\r\n agent: \"spec.planner\",\r\n prompt: \"Create a detailed technical plan based on the brainstorm above.\",\r\n },\r\n {\r\n label: \"Capture Conventions\",\r\n agent: \"spec.memorize\",\r\n prompt: \"Bootstrap memory from the project context established in the brainstorm.\",\r\n },\r\n ],\r\n planner: [\r\n {\r\n label: \"Break Down Features\",\r\n agent: \"spec.feature\",\r\n prompt: \"Break the plan into individual feature specification files.\",\r\n },\r\n {\r\n label: \"Design Architecture\",\r\n agent: \"spec.architect\",\r\n prompt: \"Create a detailed cloud and infrastructure architecture for the plan.\",\r\n },\r\n {\r\n label: \"Capture Conventions\",\r\n agent: \"spec.memorize\",\r\n prompt: \"Bootstrap memory from the plan's tech stack and conventions.\",\r\n },\r\n ],\r\n architect: [\r\n {\r\n label: \"Break Down Features\",\r\n agent: \"spec.feature\",\r\n prompt: \"Break the plan into individual feature specification files.\",\r\n },\r\n {\r\n label: \"Set Up Infrastructure\",\r\n agent: \"spec.devops\",\r\n prompt: \"Set up Docker, CI/CD, and deployment infrastructure based on the architecture.\",\r\n },\r\n ],\r\n feature: [\r\n {\r\n label: \"Implement Feature\",\r\n agent: \"spec.implement\",\r\n prompt: \"Implement the feature spec produced above.\",\r\n },\r\n {\r\n label: \"Write Unit Tests\",\r\n agent: \"spec.unit_tests\",\r\n prompt: \"Write unit tests for the feature spec produced above.\",\r\n },\r\n ],\r\n implement: [\r\n {\r\n label: \"Write Unit Tests\",\r\n agent: \"spec.unit_tests\",\r\n prompt: \"Write comprehensive unit tests for the code just implemented.\",\r\n },\r\n {\r\n label: \"Review Code\",\r\n agent: \"spec.code_review\",\r\n prompt: \"Review the code just implemented for correctness, architecture, and readability.\",\r\n },\r\n {\r\n label: \"Write Integration Tests\",\r\n agent: \"spec.integration_tests\",\r\n prompt: \"Write integration test scenarios for the feature just implemented.\",\r\n },\r\n ],\r\n unit_tests: [\r\n {\r\n label: \"Review Code\",\r\n agent: \"spec.code_review\",\r\n prompt: \"Review the implementation and tests for correctness, architecture, and readability.\",\r\n },\r\n {\r\n label: \"Write Integration Tests\",\r\n agent: \"spec.integration_tests\",\r\n prompt: \"Write integration test scenarios to complement the unit tests.\",\r\n },\r\n ],\r\n code_review: [\r\n {\r\n label: \"Fix Issues\",\r\n agent: \"spec.fix\",\r\n prompt: \"Fix the issues identified in the code review above.\",\r\n },\r\n {\r\n label: \"Security Audit\",\r\n agent: \"spec.security_audit\",\r\n prompt: \"Run a security audit on the code reviewed above.\",\r\n },\r\n {\r\n label: \"Write Technical Docs\",\r\n agent: \"spec.technical_docs\",\r\n prompt: \"Write technical documentation for the reviewed code.\",\r\n },\r\n ],\r\n integration_tests: [\r\n {\r\n label: \"Security Audit\",\r\n agent: \"spec.security_audit\",\r\n prompt: \"Run a security audit on the features covered by integration tests.\",\r\n },\r\n {\r\n label: \"Performance Review\",\r\n agent: \"spec.performance_review\",\r\n prompt: \"Review performance of the features covered by integration tests.\",\r\n },\r\n {\r\n label: \"Write Technical Docs\",\r\n agent: \"spec.technical_docs\",\r\n prompt: \"Write technical documentation for the features covered by integration tests.\",\r\n },\r\n ],\r\n performance_review: [\r\n {\r\n label: \"Fix Critical Issues\",\r\n agent: \"spec.fix\",\r\n prompt: \"Fix the critical performance issues identified in the review above.\",\r\n },\r\n {\r\n label: \"Security Audit\",\r\n agent: \"spec.security_audit\",\r\n prompt: \"Run a security audit alongside the performance improvements.\",\r\n },\r\n {\r\n label: \"Write Technical Docs\",\r\n agent: \"spec.technical_docs\",\r\n prompt: \"Write technical documentation capturing the performance findings and fixes.\",\r\n },\r\n ],\r\n security_audit: [\r\n {\r\n label: \"Fix Vulnerabilities\",\r\n agent: \"spec.fix\",\r\n prompt: \"Fix the vulnerabilities and security issues identified in the audit above.\",\r\n },\r\n {\r\n label: \"Write Technical Docs\",\r\n agent: \"spec.technical_docs\",\r\n prompt: \"Write technical documentation capturing the security findings and mitigations.\",\r\n },\r\n {\r\n label: \"Update README\",\r\n agent: \"spec.readme\",\r\n prompt: \"Update the README to reflect the hardened security posture.\",\r\n },\r\n ],\r\n fix: [\r\n {\r\n label: \"Review Fix\",\r\n agent: \"spec.code_review\",\r\n prompt: \"Review the fix applied above for correctness and regressions.\",\r\n },\r\n {\r\n label: \"Write Regression Tests\",\r\n agent: \"spec.unit_tests\",\r\n prompt: \"Write regression tests to cover the bug fixed above.\",\r\n },\r\n ],\r\n memorize: [\r\n {\r\n label: \"Create Plan\",\r\n agent: \"spec.planner\",\r\n prompt: \"Create a technical plan for the project using the conventions captured in memory.\",\r\n },\r\n {\r\n label: \"Add Feature\",\r\n agent: \"spec.feature\",\r\n prompt: \"Define a feature specification using the conventions captured in memory.\",\r\n },\r\n ],\r\n technical_docs: [\r\n {\r\n label: \"Update README\",\r\n agent: \"spec.readme\",\r\n prompt: \"Write or update the project README based on the technical docs produced above.\",\r\n },\r\n {\r\n label: \"Set Up DevOps\",\r\n agent: \"spec.devops\",\r\n prompt: \"Set up deployment infrastructure to complement the documented architecture.\",\r\n },\r\n ],\r\n readme: [\r\n {\r\n label: \"Set Up DevOps\",\r\n agent: \"spec.devops\",\r\n prompt: \"Set up Docker, CI/CD, and deployment infrastructure for this project.\",\r\n },\r\n {\r\n label: \"Security Audit\",\r\n agent: \"spec.security_audit\",\r\n prompt: \"Run a final security audit before releasing the project.\",\r\n },\r\n ],\r\n devops: [\r\n {\r\n label: \"Security Audit\",\r\n agent: \"spec.security_audit\",\r\n prompt: \"Run a security audit on the infrastructure and deployment configuration.\",\r\n },\r\n {\r\n label: \"Update README\",\r\n agent: \"spec.readme\",\r\n prompt: \"Update the README with deployment and infrastructure instructions.\",\r\n },\r\n {\r\n label: \"Update Technical Docs\",\r\n agent: \"spec.technical_docs\",\r\n prompt: \"Update the technical documentation to include the DevOps setup.\",\r\n },\r\n ],\r\n};\r\n\r\n/**\r\n * Build the YAML frontmatter block for a .agent.md file.\r\n */\r\nfunction buildAgentFrontmatter(meta: PromptMeta): string {\r\n const handoffs = AGENT_HANDOFFS[meta.name] ?? [];\r\n const lines: string[] = [\"---\", `description: ${meta.description}`];\r\n\r\n if (handoffs.length > 0) {\r\n lines.push(\"handoffs:\");\r\n for (const h of handoffs) {\r\n lines.push(` - label: ${h.label}`);\r\n lines.push(` agent: ${h.agent}`);\r\n lines.push(` prompt: ${h.prompt}`);\r\n }\r\n }\r\n\r\n lines.push(\"---\", \"\");\r\n return lines.join(\"\\n\");\r\n}\r\n\r\n/**\r\n * GitHub Copilot provider.\r\n *\r\n * Writes two sets of files per prompt:\r\n * - `.github/agents/spec.<name>.agent.md` — custom agent files (with frontmatter + handoffs)\r\n * - `.github/prompts/<name>.prompt.md` — prompt files (plain markdown, for slash-command use)\r\n *\r\n * Plus a `.github/copilot-instructions.md` that references the prompt files.\r\n */\r\nexport class CopilotProvider implements Provider {\r\n name = \"GitHub Copilot\";\r\n alias = \"copilot\";\r\n description = \"GitHub Copilot (VS Code, JetBrains, Neovim)\";\r\n\r\n /** Primary target: the .agent.md file in .github/agents/ */\r\n getTargetPath(promptName: string): string {\r\n return path.join(\".github\", \"agents\", `spec.${promptName}.agent.md`);\r\n }\r\n\r\n /** Transform content into an agent file: YAML frontmatter + prompt body. */\r\n transformPrompt(content: string, meta: PromptMeta): string {\r\n return buildAgentFrontmatter(meta) + content;\r\n }\r\n\r\n /**\r\n * Transform content into a prompt file (no frontmatter — just the managed-file\r\n * header comment followed by the prompt body).\r\n */\r\n transformPromptFile(content: string, meta: PromptMeta): string {\r\n const header = [\r\n `<!-- spec-lite | ${meta.name} | DO NOT EDIT below the project-context block — managed by spec-lite -->`,\r\n `<!-- To update: run \"spec-lite update\" — your Project Context edits will be preserved -->`,\r\n \"\",\r\n ].join(\"\\n\");\r\n return header + content;\r\n }\r\n\r\n /** Returns the path for the companion .prompt.md file */\r\n getPromptFilePath(promptName: string): string {\r\n return path.join(\".github\", \"prompts\", `${promptName}.prompt.md`);\r\n }\r\n\r\n async detectExisting(workspaceRoot: string): Promise<string[]> {\r\n const existing: string[] = [];\r\n\r\n // Check for agent files in .github/agents/\r\n const agentsDir = path.join(workspaceRoot, \".github\", \"agents\");\r\n if (await fs.pathExists(agentsDir)) {\r\n const files = await fs.readdir(agentsDir);\r\n for (const f of files) {\r\n if (f.startsWith(\"spec.\") && f.endsWith(\".agent.md\")) {\r\n existing.push(path.join(\".github\", \"agents\", f));\r\n }\r\n }\r\n }\r\n\r\n // Check for prompt files in .github/prompts/\r\n const promptsDir = path.join(workspaceRoot, \".github\", \"prompts\");\r\n if (await fs.pathExists(promptsDir)) {\r\n const files = await fs.readdir(promptsDir);\r\n for (const f of files) {\r\n if (f.endsWith(\".prompt.md\")) {\r\n existing.push(path.join(\".github\", \"prompts\", f));\r\n }\r\n }\r\n }\r\n\r\n // Check for main instructions file\r\n const mainFile = path.join(workspaceRoot, \".github\", \"copilot-instructions.md\");\r\n if (await fs.pathExists(mainFile)) {\r\n existing.push(\".github/copilot-instructions.md\");\r\n }\r\n\r\n return existing;\r\n }\r\n\r\n async getMemorySeedSource(\r\n workspaceRoot: string\r\n ): Promise<{ path: string; label: string } | null> {\r\n const p = path.join(workspaceRoot, \".github\", \"copilot-instructions.md\");\r\n if (await fs.pathExists(p)) {\r\n return { path: \".github/copilot-instructions.md\", label: \"GitHub Copilot global instructions\" };\r\n }\r\n return null;\r\n }\r\n\r\n getPostInitMessage(): string {\r\n return [\r\n \"\",\r\n \"📋 GitHub Copilot setup complete!\",\r\n \"\",\r\n \" Agent files : .github/agents/spec.<name>.agent.md\",\r\n \" Prompt files : .github/prompts/<name>.prompt.md\",\r\n \"\",\r\n \" How to use:\",\r\n \" 1. Open GitHub Copilot Chat in VS Code\",\r\n \" 2. Select a sub-agent from the agents dropdown (e.g., spec.planner)\",\r\n \" — or — reference a prompt file with #file or type / to browse\",\r\n \" 3. Agent files include handoff buttons to guide you through the pipeline\",\r\n \" 4. Customize the Project Context block in each file for your project\",\r\n \"\",\r\n ].join(\"\\n\");\r\n }\r\n}\r\n\r\nconst SPEC_LITE_MARKER_START = \"<!-- spec-lite:start -->\";\r\nconst SPEC_LITE_MARKER_END = \"<!-- spec-lite:end -->\";\r\n\r\n/**\r\n * Generate the spec-lite block to inject into (or create as) copilot-instructions.md.\r\n * Links point to the prompt files in .github/prompts/.\r\n */\r\nexport function generateSpecLiteBlock(installedPrompts: string[]): string {\r\n const lines = [\r\n SPEC_LITE_MARKER_START,\r\n \"## spec-lite Sub-Agents\",\r\n \"\",\r\n \"This project uses [spec-lite](https://github.com/abranjith/spec-lite) sub-agent prompts\",\r\n \"for structured software engineering workflows.\",\r\n \"\",\r\n \"The following specialist sub-agents are available:\",\r\n \"\",\r\n \"**Agent files** (`.github/agents/`) — select from the agents dropdown in Copilot Chat:\",\r\n \"\",\r\n ];\r\n\r\n for (const name of installedPrompts) {\r\n lines.push(`- [spec.${name}](.github/agents/spec.${name}.agent.md)`);\r\n }\r\n\r\n lines.push(\r\n \"\",\r\n \"**Prompt files** (`.github/prompts/`) — reference with `#file` or browse with `/`:\",\r\n \"\",\r\n );\r\n\r\n for (const name of installedPrompts) {\r\n lines.push(`- [${name}](.github/prompts/${name}.prompt.md)`);\r\n }\r\n\r\n lines.push(\r\n \"\",\r\n \"To invoke a sub-agent, select it from the agents dropdown or use `#file` to reference a prompt file.\",\r\n SPEC_LITE_MARKER_END\r\n );\r\n\r\n return lines.join(\"\\n\");\r\n}\r\n\r\n/**\r\n * Merge the spec-lite block into an existing copilot-instructions.md, or create fresh content.\r\n * If the file already has spec-lite markers, the block between them is replaced.\r\n * Otherwise the block is appended.\r\n */\r\nexport function mergeCopilotInstructions(\r\n existingContent: string | null,\r\n installedPrompts: string[]\r\n): string {\r\n const block = generateSpecLiteBlock(installedPrompts);\r\n\r\n if (!existingContent) {\r\n return block + \"\\n\";\r\n }\r\n\r\n // Replace existing spec-lite block if markers are present\r\n const startIdx = existingContent.indexOf(SPEC_LITE_MARKER_START);\r\n const endIdx = existingContent.indexOf(SPEC_LITE_MARKER_END);\r\n\r\n if (startIdx !== -1 && endIdx !== -1 && endIdx > startIdx) {\r\n return (\r\n existingContent.slice(0, startIdx) +\r\n block +\r\n existingContent.slice(endIdx + SPEC_LITE_MARKER_END.length)\r\n );\r\n }\r\n\r\n // Append the block to existing content (preserving user content)\r\n const separator = existingContent.endsWith(\"\\n\") ? \"\\n\" : \"\\n\\n\";\r\n return existingContent + separator + block + \"\\n\";\r\n}\r\n","import path from \"path\";\r\nimport fs from \"fs-extra\";\r\nimport type { Provider, PromptMeta } from \"./base.js\";\r\n\r\n/**\r\n * Claude Code (Anthropic) provider.\r\n *\r\n * Claude Code supports:\r\n * - `CLAUDE.md` at the project root — loaded automatically as project instructions\r\n * - `.claude/` directory for additional configuration\r\n * - Nested `CLAUDE.md` files in subdirectories for scoped instructions\r\n *\r\n * Strategy:\r\n * - Write individual agent files to `.claude/prompts/<name>.md`\r\n * - Create/update a root `CLAUDE.md` that references the spec-lite agent collection\r\n * and provides a high-level overview\r\n */\r\nexport class ClaudeCodeProvider implements Provider {\r\n name = \"Claude Code\";\r\n alias = \"claude-code\";\r\n description = \"Claude Code (Anthropic's coding agent)\";\r\n\r\n getTargetPath(promptName: string): string {\r\n return path.join(\".claude\", \"prompts\", `${promptName}.md`);\r\n }\r\n\r\n transformPrompt(content: string, meta: PromptMeta): string {\r\n // Claude Code reads markdown natively. We add a header comment.\r\n const header = [\r\n `<!-- spec-lite | ${meta.name} | DO NOT EDIT below the project-context block — managed by spec-lite -->`,\r\n `<!-- To update: run \"spec-lite update\" — your Project Context edits will be preserved -->`,\r\n \"\",\r\n ].join(\"\\n\");\r\n\r\n return header + content;\r\n }\r\n\r\n async detectExisting(workspaceRoot: string): Promise<string[]> {\r\n const existing: string[] = [];\r\n\r\n // Check for claude prompts directory\r\n const claudePromptsDir = path.join(\r\n workspaceRoot,\r\n \".claude\",\r\n \"prompts\"\r\n );\r\n if (await fs.pathExists(claudePromptsDir)) {\r\n const files = await fs.readdir(claudePromptsDir);\r\n for (const f of files) {\r\n if (f.endsWith(\".md\")) {\r\n existing.push(path.join(\".claude\", \"prompts\", f));\r\n }\r\n }\r\n }\r\n\r\n // Check for root CLAUDE.md\r\n const rootFile = path.join(workspaceRoot, \"CLAUDE.md\");\r\n if (await fs.pathExists(rootFile)) {\r\n existing.push(\"CLAUDE.md\");\r\n }\r\n\r\n return existing;\r\n }\r\n\r\n async getMemorySeedSource(\r\n workspaceRoot: string\r\n ): Promise<{ path: string; label: string } | null> {\r\n const p = path.join(workspaceRoot, \"CLAUDE.md\");\r\n if (await fs.pathExists(p)) {\r\n return { path: \"CLAUDE.md\", label: \"Claude root instructions (CLAUDE.md)\" };\r\n }\r\n return null;\r\n }\r\n\r\n getPostInitMessage(): string {\r\n return [\r\n \"\",\r\n \"📋 Claude Code setup complete!\",\r\n \"\",\r\n \" Your sub-agent prompts are in .claude/prompts/\",\r\n \" A root CLAUDE.md has been created with references to the sub-agents.\",\r\n \"\",\r\n \" How to use:\",\r\n \" 1. Claude Code automatically reads CLAUDE.md for project context\",\r\n ' 2. Reference specific sub-agents: \"Use the planner from .claude/prompts/planner.md\"',\r\n \" 3. Customize the Project Context block in each file for your project\",\r\n \"\",\r\n ].join(\"\\n\");\r\n }\r\n}\r\n\r\n/**\r\n * Generate the root CLAUDE.md content that references spec-lite sub-agents.\r\n */\r\nexport function generateClaudeRootMd(\r\n installedPrompts: string[]\r\n): string {\r\n const lines = [\r\n \"<!-- spec-lite managed — regenerated on spec-lite init/update -->\",\r\n \"\",\r\n \"# Project Instructions\",\r\n \"\",\r\n \"This project uses [spec-lite](https://github.com/abranjith/spec-lite) sub-agent prompts\",\r\n \"for structured software engineering workflows.\",\r\n \"\",\r\n \"## Available Sub-Agents\",\r\n \"\",\r\n \"The following specialist sub-agents are available in `.claude/prompts/`:\",\r\n \"\",\r\n ];\r\n\r\n for (const name of installedPrompts) {\r\n lines.push(`- [${name}](.claude/prompts/${name}.md)`);\r\n }\r\n\r\n lines.push(\r\n \"\",\r\n \"## Usage\",\r\n \"\",\r\n \"To use a sub-agent, reference its prompt file in your conversation:\",\r\n \"\",\r\n '```text',\r\n \"Use the planner from .claude/prompts/planner.md to create a technical plan for this project.\",\r\n '```',\r\n \"\",\r\n \"## Output Directory\",\r\n \"\",\r\n \"Sub-agent outputs are written to the `.spec-lite/` directory:\",\r\n \"\",\r\n \"```text\",\r\n \".spec-lite/\",\r\n \"├── brainstorm.md\",\r\n \"├── plan.md # Default plan (simple projects)\",\r\n \"├── plan_<name>.md # Named plans (complex projects)\",\r\n \"├── TODO.md\",\r\n \"├── features/\",\r\n \"└── reviews/\",\r\n \"```\",\r\n \"\"\r\n );\r\n\r\n return lines.join(\"\\n\");\r\n}\r\n","import path from \"path\";\r\nimport fs from \"fs-extra\";\r\nimport type { Provider, PromptMeta } from \"./base.js\";\r\n\r\n/**\r\n * Generic provider — for manual usage or unsupported AI tools.\r\n *\r\n * Writes prompts to `.spec-lite/prompts/` as raw markdown.\r\n * Users can copy-paste these into any LLM chat.\r\n */\r\nexport class GenericProvider implements Provider {\r\n name = \"Generic\";\r\n alias = \"generic\";\r\n description = \"Raw prompts in .spec-lite/prompts/ (copy-paste into any LLM)\";\r\n\r\n getTargetPath(promptName: string): string {\r\n return path.join(\".spec-lite\", \"prompts\", `${promptName}.md`);\r\n }\r\n\r\n transformPrompt(content: string, meta: PromptMeta): string {\r\n // No transformation — copy as-is with a light header\r\n const header = [\r\n `<!-- spec-lite | ${meta.name} | managed by spec-lite -->`,\r\n `<!-- To update: run \"spec-lite update\" -->`,\r\n \"\",\r\n ].join(\"\\n\");\r\n\r\n return header + content;\r\n }\r\n\r\n async detectExisting(workspaceRoot: string): Promise<string[]> {\r\n const existing: string[] = [];\r\n const dir = path.join(workspaceRoot, \".spec-lite\", \"prompts\");\r\n\r\n if (await fs.pathExists(dir)) {\r\n const files = await fs.readdir(dir);\r\n for (const f of files) {\r\n if (f.endsWith(\".md\")) {\r\n existing.push(path.join(\".spec-lite\", \"prompts\", f));\r\n }\r\n }\r\n }\r\n\r\n return existing;\r\n }\r\n\r\n async getMemorySeedSource(\r\n _workspaceRoot: string\r\n ): Promise<{ path: string; label: string } | null> {\r\n // Generic provider has no canonical instruction file to seed from\r\n return null;\r\n }\r\n\r\n getPostInitMessage(): string {\r\n return [\r\n \"\",\r\n \"📋 Generic setup complete!\",\r\n \"\",\r\n \" Your sub-agent prompts are in .spec-lite/prompts/\",\r\n \"\",\r\n \" How to use:\",\r\n \" 1. Open any prompt file and copy its content\",\r\n \" 2. Paste into your LLM of choice (ChatGPT, Claude, Gemini, etc.)\",\r\n \" 3. Fill in the Project Context section for your project\",\r\n \" 4. Start the conversation with your requirements\",\r\n \"\",\r\n ].join(\"\\n\");\r\n }\r\n}\r\n","import type { Provider } from \"./base.js\";\r\nimport { CopilotProvider } from \"./copilot.js\";\r\nimport { ClaudeCodeProvider } from \"./claude-code.js\";\r\nimport { GenericProvider } from \"./generic.js\";\r\n\r\n/**\r\n * Registry of all supported AI provider adapters.\r\n */\r\nconst providers: Provider[] = [\r\n new CopilotProvider(),\r\n new ClaudeCodeProvider(),\r\n new GenericProvider(),\r\n];\r\n\r\n/**\r\n * Get a provider by its CLI alias (e.g., \"copilot\", \"claude-code\", \"generic\").\r\n */\r\nexport function getProvider(alias: string): Provider | undefined {\r\n return providers.find((p) => p.alias === alias);\r\n}\r\n\r\n/**\r\n * Get all registered providers.\r\n */\r\nexport function getAllProviders(): Provider[] {\r\n return [...providers];\r\n}\r\n\r\n/**\r\n * Get a formatted list of provider aliases for display.\r\n */\r\nexport function getProviderAliases(): string[] {\r\n return providers.map((p) => p.alias);\r\n}\r\n\r\n// Re-export types\r\nexport type { Provider, PromptMeta, SpecLiteConfig } from \"./base.js\";\r\n","import path from \"path\";\r\nimport fs from \"fs-extra\";\r\nimport { fileURLToPath } from \"url\";\r\n\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = path.dirname(__filename);\r\n\r\n/** Path to the bundled prompts directory (shipped with the npm package) */\r\nexport function getPromptsDir(): string {\r\n // In the built output (tsup bundles to dist/index.js),\r\n // __dirname resolves to dist/ — prompts/ is one level up at the package root\r\n return path.resolve(__dirname, \"..\", \"prompts\");\r\n}\r\n\r\n/** Metadata extracted from prompt files */\r\nexport interface PromptFile {\r\n /** File name without extension */\r\n name: string;\r\n /** Full file path */\r\n filePath: string;\r\n /** Raw markdown content */\r\n content: string;\r\n /** Extracted title */\r\n title: string;\r\n /** Extracted description */\r\n description: string;\r\n}\r\n\r\n/** Map of prompt names to their human titles and descriptions */\r\nexport const PROMPT_CATALOG: Record<string, { title: string; description: string; output?: string }> = {\r\n spec_help: {\r\n title: \"Spec Help\",\r\n description: \"Lists available sub-agents, their purpose, inputs, and outputs\",\r\n output: \"(interactive guide)\",\r\n },\r\n brainstorm: {\r\n title: \"Brainstorm\",\r\n description: \"Refines a vague idea into a clear, actionable vision\",\r\n output: \".spec-lite/brainstorm.md\",\r\n },\r\n planner: {\r\n title: \"Planner\",\r\n description: \"Creates a detailed technical blueprint from requirements\",\r\n output: \".spec-lite/plan.md or .spec-lite/plan_<name>.md\",\r\n },\r\n feature: {\r\n title: \"Feature\",\r\n description: \"Breaks one feature into granular, verifiable vertical slices\",\r\n output: \".spec-lite/features/feature_<name>.md\",\r\n },\r\n implement: {\r\n title: \"Implement\",\r\n description: \"Picks up a feature spec and executes its tasks with code\",\r\n output: \"Working code + updated feature spec\",\r\n },\r\n code_review: {\r\n title: \"Code Review\",\r\n description: \"Reviews code for correctness, architecture, and readability\",\r\n output: \".spec-lite/reviews/code_review_<name>.md\",\r\n },\r\n security_audit: {\r\n title: \"Security Audit\",\r\n description: \"Scans for vulnerabilities, misconfigurations, and security risks\",\r\n output: \".spec-lite/reviews/security_audit_<scope>.md\",\r\n },\r\n performance_review: {\r\n title: \"Performance Review\",\r\n description: \"Identifies bottlenecks and optimization opportunities\",\r\n output: \".spec-lite/reviews/performance_review_<scope>.md\",\r\n },\r\n integration_tests: {\r\n title: \"Integration Tests\",\r\n description: \"Writes traceable integration test scenarios from feature specs\",\r\n output: \"tests/\",\r\n },\r\n unit_tests: {\r\n title: \"Unit Tests\",\r\n description: \"Generates comprehensive unit tests with edge-case coverage and smart coverage exclusions\",\r\n output: \".spec-lite/features/unit_tests_<name>.md\",\r\n },\r\n devops: {\r\n title: \"DevOps\",\r\n description: \"Sets up Docker, CI/CD, environments, and deployment\",\r\n output: \"Project infrastructure files\",\r\n },\r\n fix: {\r\n title: \"Fix & Refactor\",\r\n description: \"Debugs issues or restructures code safely\",\r\n output: \"Targeted fixes with verification\",\r\n },\r\n memorize: {\r\n title: \"Memorize\",\r\n description:\r\n \"Stores standing instructions that all sub-agents enforce. Use `/memorize bootstrap` to auto-generate from project analysis.\",\r\n output: \".spec-lite/memory.md\",\r\n },\r\n technical_docs: {\r\n title: \"Technical Docs\",\r\n description: \"Creates deep architecture documentation for developers\",\r\n output: \"docs/technical_architecture.md\",\r\n },\r\n readme: {\r\n title: \"README\",\r\n description: \"Writes the project README and optional user guide\",\r\n output: \"README.md + docs/user_guide.md\",\r\n },\r\n architect: {\r\n title: \"Architect\",\r\n description:\r\n \"Designs cloud infrastructure, database strategy, and scaling architecture with Mermaid diagrams\",\r\n output: \".spec-lite/architect_<name>.md\",\r\n },\r\n};\r\n\r\n/** Non-agent files to skip */\r\nconst SKIP_FILES = new Set([\"orchestrator\"]);\r\n\r\n/**\r\n * Load all available prompt files from the bundled prompts directory.\r\n * Excludes non-agent files (orchestrator).\r\n */\r\nexport async function loadPrompts(\r\n exclude: string[] = []\r\n): Promise<PromptFile[]> {\r\n const promptsDir = getPromptsDir();\r\n const excludeSet = new Set([...exclude, ...SKIP_FILES]);\r\n\r\n const files = await fs.readdir(promptsDir);\r\n const prompts: PromptFile[] = [];\r\n\r\n for (const file of files) {\r\n if (!file.endsWith(\".md\")) continue;\r\n\r\n const name = file.replace(\".md\", \"\");\r\n if (excludeSet.has(name)) continue;\r\n\r\n const filePath = path.join(promptsDir, file);\r\n const content = await fs.readFile(filePath, \"utf-8\");\r\n const catalog = PROMPT_CATALOG[name];\r\n\r\n prompts.push({\r\n name,\r\n filePath,\r\n content,\r\n title: catalog?.title ?? name,\r\n description: catalog?.description ?? \"\",\r\n });\r\n }\r\n\r\n return prompts;\r\n}\r\n\r\n/**\r\n * Get the list of all available prompt names.\r\n */\r\nexport function getAvailablePromptNames(): string[] {\r\n return Object.keys(PROMPT_CATALOG);\r\n}\r\n\r\n/**\r\n * Get the full prompt catalog (for display in CLI list command).\r\n */\r\nexport function getPromptCatalog(): Record<string, { title: string; description: string; output?: string }> {\r\n return PROMPT_CATALOG;\r\n}\r\n\r\n/**\r\n * Project Context markers used to preserve user edits during updates.\r\n */\r\nexport const CONTEXT_START_MARKER = \"<!-- project-context-start -->\";\r\nexport const CONTEXT_END_MARKER = \"<!-- project-context-end -->\";\r\n\r\n/**\r\n * Extract the Project Context block from a prompt.\r\n * Returns the content between markers, or null if not found.\r\n */\r\nexport function extractProjectContext(content: string): string | null {\r\n const startIdx = content.indexOf(CONTEXT_START_MARKER);\r\n const endIdx = content.indexOf(CONTEXT_END_MARKER);\r\n\r\n if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) return null;\r\n\r\n return content.substring(\r\n startIdx + CONTEXT_START_MARKER.length,\r\n endIdx\r\n );\r\n}\r\n\r\n/**\r\n * Replace the Project Context block in a prompt with new content.\r\n */\r\nexport function replaceProjectContext(\r\n content: string,\r\n newContext: string\r\n): string {\r\n const startIdx = content.indexOf(CONTEXT_START_MARKER);\r\n const endIdx = content.indexOf(CONTEXT_END_MARKER);\r\n\r\n if (startIdx === -1 || endIdx === -1 || endIdx <= startIdx) return content;\r\n\r\n return (\r\n content.substring(0, startIdx + CONTEXT_START_MARKER.length) +\r\n newContext +\r\n content.substring(endIdx)\r\n );\r\n}\r\n","import path from \"path\";\r\nimport fs from \"fs-extra\";\r\nimport { fileURLToPath } from \"url\";\r\n\r\nconst __filename = fileURLToPath(import.meta.url);\r\nconst __dirname = path.dirname(__filename);\r\n\r\n/**\r\n * Path to the bundled stacks directory (shipped with the npm package).\r\n * In the built output (tsup bundles to dist/index.js),\r\n * __dirname resolves to dist/ — stacks/ is copied to dist/stacks/ during build.\r\n */\r\nexport function getStacksDir(): string {\r\n return path.resolve(__dirname, \"stacks\");\r\n}\r\n\r\n/**\r\n * Map of language names (lowercased) to their stack snippet filenames.\r\n * Supports common aliases so the questionnaire answer maps correctly.\r\n */\r\nconst LANGUAGE_MAP: Record<string, string> = {\r\n typescript: \"typescript.md\",\r\n ts: \"typescript.md\",\r\n javascript: \"typescript.md\",\r\n js: \"typescript.md\",\r\n \"node.js\": \"typescript.md\",\r\n node: \"typescript.md\",\r\n react: \"react.md\",\r\n \"react.js\": \"react.md\",\r\n \"next.js\": \"react.md\",\r\n nextjs: \"react.md\",\r\n python: \"python.md\",\r\n py: \"python.md\",\r\n \"c#\": \"dotnet.md\",\r\n csharp: \"dotnet.md\",\r\n \".net\": \"dotnet.md\",\r\n dotnet: \"dotnet.md\",\r\n java: \"java.md\",\r\n \"spring\": \"java.md\",\r\n \"spring boot\": \"java.md\",\r\n \"spring-boot\": \"java.md\",\r\n};\r\n\r\n/**\r\n * Get the bundled best-practice snippet for a given language.\r\n * Returns the markdown content if a matching snippet exists, or null if not.\r\n */\r\nexport function getStackSnippet(language: string): string | null {\r\n const key = language.toLowerCase().trim();\r\n const filename = LANGUAGE_MAP[key];\r\n\r\n if (!filename) return null;\r\n\r\n const filePath = path.join(getStacksDir(), filename);\r\n if (!fs.pathExistsSync(filePath)) return null;\r\n\r\n return fs.readFileSync(filePath, \"utf-8\");\r\n}\r\n\r\n/**\r\n * List all available stack snippet names (for display purposes).\r\n */\r\nexport function listAvailableStacks(): string[] {\r\n const stacksDir = getStacksDir();\r\n if (!fs.pathExistsSync(stacksDir)) return [];\r\n\r\n return fs\r\n .readdirSync(stacksDir)\r\n .filter((f) => f.endsWith(\".md\"))\r\n .map((f) => f.replace(\".md\", \"\"));\r\n}\r\n","import path from \"path\";\r\nimport fs from \"fs-extra\";\r\nimport chalk from \"chalk\";\r\nimport { getProvider } from \"../providers/index.js\";\r\nimport type { SpecLiteConfig } from \"../providers/base.js\";\r\nimport {\r\n loadPrompts,\r\n extractProjectContext,\r\n replaceProjectContext,\r\n} from \"../utils/prompts.js\";\r\nimport { generateClaudeRootMd } from \"../providers/claude-code.js\";\r\nimport { CopilotProvider, mergeCopilotInstructions } from \"../providers/copilot.js\";\r\n\r\ninterface UpdateOptions {\r\n force?: boolean;\r\n}\r\n\r\nexport async function updateCommand(options: UpdateOptions): Promise<void> {\r\n const cwd = process.cwd();\r\n\r\n console.log(chalk.bold(\"\\n⚡ spec-lite update\\n\"));\r\n\r\n // 1. Read existing config\r\n const configPath = path.join(cwd, \".spec-lite.json\");\r\n if (!(await fs.pathExists(configPath))) {\r\n console.error(\r\n chalk.red(\r\n ' No .spec-lite.json found. Run \"spec-lite init\" first.'\r\n )\r\n );\r\n process.exit(1);\r\n }\r\n\r\n const config: SpecLiteConfig = await fs.readJson(configPath);\r\n const provider = getProvider(config.provider);\r\n\r\n if (!provider) {\r\n console.error(\r\n chalk.red(\r\n ` Unknown provider \"${config.provider}\" in .spec-lite.json. Re-run \"spec-lite init\".`\r\n )\r\n );\r\n process.exit(1);\r\n }\r\n\r\n console.log(chalk.cyan(` Provider: ${provider.name}`));\r\n console.log(\r\n chalk.dim(` Installed: ${config.installedPrompts.length} prompts`)\r\n );\r\n\r\n // 2. Load latest prompts (only the ones that were previously installed)\r\n const allPrompts = await loadPrompts();\r\n const installedSet = new Set(config.installedPrompts);\r\n const prompts = allPrompts.filter((p) => installedSet.has(p.name));\r\n\r\n let updated = 0;\r\n let preserved = 0;\r\n let unchanged = 0;\r\n\r\n for (const prompt of prompts) {\r\n const targetRelPath = provider.getTargetPath(prompt.name);\r\n const targetAbsPath = path.join(cwd, targetRelPath);\r\n\r\n // Transform the new prompt content\r\n const newContent = provider.transformPrompt(prompt.content, {\r\n name: prompt.name,\r\n title: prompt.title,\r\n description: prompt.description,\r\n });\r\n\r\n if (!(await fs.pathExists(targetAbsPath))) {\r\n // File was deleted by user — re-create it\r\n await fs.ensureDir(path.dirname(targetAbsPath));\r\n await fs.writeFile(targetAbsPath, newContent, \"utf-8\");\r\n console.log(chalk.green(` ✓ ${targetRelPath} (restored)`));\r\n updated++;\r\n continue;\r\n }\r\n\r\n // Read current installed version\r\n const currentContent = await fs.readFile(targetAbsPath, \"utf-8\");\r\n\r\n // Check if content is identical (no update needed)\r\n if (currentContent === newContent) {\r\n unchanged++;\r\n continue;\r\n }\r\n\r\n // Try to preserve user's Project Context edits\r\n if (!options.force) {\r\n const userContext = extractProjectContext(currentContent);\r\n if (userContext) {\r\n const mergedContent = replaceProjectContext(newContent, userContext);\r\n await fs.writeFile(targetAbsPath, mergedContent, \"utf-8\");\r\n console.log(\r\n chalk.green(\r\n ` ✓ ${targetRelPath} (updated, Project Context preserved)`\r\n )\r\n );\r\n preserved++;\r\n updated++;\r\n continue;\r\n }\r\n }\r\n\r\n // No context block found or --force — full overwrite\r\n await fs.writeFile(targetAbsPath, newContent, \"utf-8\");\r\n console.log(chalk.green(` ✓ ${targetRelPath} (updated)`));\r\n updated++;\r\n }\r\n\r\n // 3. Update provider-specific extras\r\n if (provider.alias === \"claude-code\") {\r\n const claudeMdPath = path.join(cwd, \"CLAUDE.md\");\r\n const claudeMdContent = generateClaudeRootMd(config.installedPrompts);\r\n await fs.writeFile(claudeMdPath, claudeMdContent, \"utf-8\");\r\n console.log(chalk.green(` ✓ CLAUDE.md (regenerated)`));\r\n }\r\n\r\n if (provider.alias === \"copilot\") {\r\n const copilotProvider = provider as CopilotProvider;\r\n\r\n // Update .github/prompts/<name>.prompt.md (plain prompt files, no agent frontmatter)\r\n for (const prompt of prompts) {\r\n const promptRelPath = copilotProvider.getPromptFilePath(prompt.name);\r\n const promptAbsPath = path.join(cwd, promptRelPath);\r\n\r\n const newContent = copilotProvider.transformPromptFile(prompt.content, {\r\n name: prompt.name,\r\n title: prompt.title,\r\n description: prompt.description,\r\n });\r\n\r\n if (!(await fs.pathExists(promptAbsPath))) {\r\n // File was deleted by user — re-create it\r\n await fs.ensureDir(path.dirname(promptAbsPath));\r\n await fs.writeFile(promptAbsPath, newContent, \"utf-8\");\r\n console.log(chalk.green(` ✓ ${promptRelPath} (restored)`));\r\n updated++;\r\n continue;\r\n }\r\n\r\n const currentContent = await fs.readFile(promptAbsPath, \"utf-8\");\r\n\r\n if (currentContent === newContent) {\r\n unchanged++;\r\n continue;\r\n }\r\n\r\n // Preserve user's Project Context edits\r\n if (!options.force) {\r\n const userContext = extractProjectContext(currentContent);\r\n if (userContext) {\r\n const mergedContent = replaceProjectContext(newContent, userContext);\r\n await fs.writeFile(promptAbsPath, mergedContent, \"utf-8\");\r\n console.log(chalk.green(` ✓ ${promptRelPath} (updated, Project Context preserved)`));\r\n preserved++;\r\n updated++;\r\n continue;\r\n }\r\n }\r\n\r\n await fs.writeFile(promptAbsPath, newContent, \"utf-8\");\r\n console.log(chalk.green(` ✓ ${promptRelPath} (updated)`));\r\n updated++;\r\n }\r\n\r\n // Update .github/copilot-instructions.md\r\n const copilotInstructionsPath = path.join(cwd, \".github\", \"copilot-instructions.md\");\r\n await fs.ensureDir(path.join(cwd, \".github\"));\r\n const existingContent = (await fs.pathExists(copilotInstructionsPath))\r\n ? await fs.readFile(copilotInstructionsPath, \"utf-8\")\r\n : null;\r\n const merged = mergeCopilotInstructions(existingContent, config.installedPrompts);\r\n await fs.writeFile(copilotInstructionsPath, merged, \"utf-8\");\r\n console.log(chalk.green(` ✓ .github/copilot-instructions.md (updated)`));\r\n }\r\n\r\n // 4. Update config timestamp\r\n config.updatedAt = new Date().toISOString();\r\n try {\r\n const { createRequire } = await import(\"module\");\r\n const require = createRequire(import.meta.url);\r\n const pkg = require(\"../../package.json\");\r\n config.version = pkg.version;\r\n } catch {\r\n // Keep existing version\r\n }\r\n await fs.writeJson(configPath, config, { spaces: 2 });\r\n\r\n // 5. Summary\r\n console.log(\r\n chalk.bold(\r\n `\\n Done! ${updated} updated, ${unchanged} unchanged, ${preserved} with preserved edits.`\r\n )\r\n );\r\n}\r\n","import chalk from \"chalk\";\r\nimport { getPromptCatalog } from \"../utils/prompts.js\";\r\n\r\nexport async function listCommand(): Promise<void> {\r\n const catalog = getPromptCatalog();\r\n\r\n console.log(chalk.bold(\"\\n⚡ spec-lite — Available Sub-Agents\\n\"));\r\n\r\n console.log(\r\n chalk.dim(\r\n \" Each sub-agent is a specialist prompt for one phase of the development lifecycle.\\n\"\r\n )\r\n );\r\n\r\n // Calculate column widths\r\n const entries = Object.entries(catalog);\r\n const maxName = Math.max(...entries.map(([name]) => name.length), 4);\r\n const maxTitle = Math.max(\r\n ...entries.map(([, v]) => v.title.length),\r\n 5\r\n );\r\n\r\n // Header\r\n const header = ` ${\"Name\".padEnd(maxName + 2)}${\"Title\".padEnd(maxTitle + 2)}${\"Description\"}`;\r\n console.log(chalk.cyan(header));\r\n console.log(chalk.dim(` ${\"─\".repeat(header.trim().length + 10)}`));\r\n\r\n // Rows\r\n for (const [name, meta] of entries) {\r\n const nameCol = chalk.green(name.padEnd(maxName + 2));\r\n const titleCol = chalk.white(meta.title.padEnd(maxTitle + 2));\r\n const descCol = chalk.dim(meta.description);\r\n console.log(` ${nameCol}${titleCol}${descCol}`);\r\n if (meta.output) {\r\n console.log(\r\n ` ${\"\".padEnd(maxName + 2)}${\"\".padEnd(maxTitle + 2)}${chalk.dim(`→ ${meta.output}`)}`\r\n );\r\n }\r\n }\r\n\r\n console.log(\r\n chalk.dim(\r\n `\\n ${entries.length} sub-agents available. Run \"spec-lite init\" to install them.\\n`\r\n )\r\n );\r\n\r\n // Pipeline\r\n console.log(chalk.bold(\" Recommended Pipeline:\\n\"));\r\n console.log(\r\n chalk.dim(\r\n \" Brainstorm → Planner → Feature (×N) → Reviews → Tests → DevOps → Docs\"\r\n )\r\n );\r\n console.log(\r\n chalk.dim(\r\n \" (Not every project needs every sub-agent. Start with Planner if you have clear requirements.)\\n\"\r\n )\r\n );\r\n}\r\n"],"mappings":"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","names":["path","fs","path","fs","path","fs","path","fs","path","fs","fileURLToPath","__filename","__dirname","providers","path","fs","pkg","createRequire","require","path","fs","chalk","chalk","path","fs","createRequire","require","pkg","chalk","chalk","require"]}
|
package/package.json
CHANGED
package/prompts/architect.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- spec-lite v0.0.
|
|
1
|
+
<!-- spec-lite v0.0.4 | prompt: architect | updated: 2026-02-21 -->
|
|
2
2
|
|
|
3
3
|
# PERSONA: Architect Sub-Agent
|
|
4
4
|
|
|
@@ -186,7 +186,7 @@ Always use a descriptive name: `.spec-lite/architect_<snake_case_name>.md` (e.g.
|
|
|
186
186
|
Fill in this template when producing your final output:
|
|
187
187
|
|
|
188
188
|
```markdown
|
|
189
|
-
<!-- Generated by spec-lite v0.0.
|
|
189
|
+
<!-- Generated by spec-lite v0.0.4 | sub-agent: architect | date: {{date}} -->
|
|
190
190
|
|
|
191
191
|
# Architecture: {{system_name}}
|
|
192
192
|
|
package/prompts/brainstorm.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- spec-lite v0.0.
|
|
1
|
+
<!-- spec-lite v0.0.4 | prompt: brainstorm | updated: 2026-02-19 -->
|
|
2
2
|
|
|
3
3
|
# PERSONA: Brainstorm Sub-Agent
|
|
4
4
|
|
|
@@ -130,7 +130,7 @@ Your final output is a markdown file at `.spec-lite/brainstorm.md`. This is the
|
|
|
130
130
|
Fill in this template when producing your final output:
|
|
131
131
|
|
|
132
132
|
```markdown
|
|
133
|
-
<!-- Generated by spec-lite v0.0.
|
|
133
|
+
<!-- Generated by spec-lite v0.0.4 | sub-agent: brainstorm | date: {{date}} -->
|
|
134
134
|
|
|
135
135
|
# Brainstorm: {{project_name}}
|
|
136
136
|
|
package/prompts/code_review.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- spec-lite v0.0.
|
|
1
|
+
<!-- spec-lite v0.0.4 | prompt: code_review | updated: 2026-02-19 -->
|
|
2
2
|
|
|
3
3
|
# PERSONA: Code Review Sub-Agent
|
|
4
4
|
|
|
@@ -89,7 +89,7 @@ Categorize findings by severity:
|
|
|
89
89
|
### Output Template
|
|
90
90
|
|
|
91
91
|
```markdown
|
|
92
|
-
<!-- Generated by spec-lite v0.0.
|
|
92
|
+
<!-- Generated by spec-lite v0.0.4 | sub-agent: code_review | date: {{date}} -->
|
|
93
93
|
|
|
94
94
|
# Code Review: {{feature_name}}
|
|
95
95
|
|
package/prompts/devops.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- spec-lite v0.0.
|
|
1
|
+
<!-- spec-lite v0.0.4 | prompt: devops | updated: 2026-02-19 -->
|
|
2
2
|
|
|
3
3
|
# PERSONA: DevOps Sub-Agent
|
|
4
4
|
|
|
@@ -87,7 +87,7 @@ Produce actual files, not descriptions of files. Every artifact should be copy-p
|
|
|
87
87
|
### Output Template
|
|
88
88
|
|
|
89
89
|
```markdown
|
|
90
|
-
<!-- Generated by spec-lite v0.0.
|
|
90
|
+
<!-- Generated by spec-lite v0.0.4 | sub-agent: devops | date: {{date}} -->
|
|
91
91
|
|
|
92
92
|
# DevOps Configuration
|
|
93
93
|
|
package/prompts/feature.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- spec-lite v0.0.
|
|
1
|
+
<!-- spec-lite v0.0.4 | prompt: feature | updated: 2026-02-19 -->
|
|
2
2
|
|
|
3
3
|
# PERSONA: Feature Sub-Agent
|
|
4
4
|
|
|
@@ -161,7 +161,7 @@ Your output is a markdown file at `.spec-lite/features/feature_<name>.md` (e.g.,
|
|
|
161
161
|
Fill in this template when producing your final output:
|
|
162
162
|
|
|
163
163
|
```markdown
|
|
164
|
-
<!-- Generated by spec-lite v0.0.
|
|
164
|
+
<!-- Generated by spec-lite v0.0.4 | sub-agent: feature | date: {{date}} -->
|
|
165
165
|
|
|
166
166
|
# Feature: {{feature_name}}
|
|
167
167
|
|
package/prompts/fix.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- spec-lite v0.0.
|
|
1
|
+
<!-- spec-lite v0.0.4 | prompt: fix | updated: 2026-02-19 -->
|
|
2
2
|
|
|
3
3
|
# PERSONA: Fix Sub-Agent
|
|
4
4
|
|
|
@@ -99,7 +99,7 @@ Add a brief entry to `.spec-lite/TODO.md` or the relevant feature spec if the bu
|
|
|
99
99
|
### Output Template
|
|
100
100
|
|
|
101
101
|
```markdown
|
|
102
|
-
<!-- Generated by spec-lite v0.0.
|
|
102
|
+
<!-- Generated by spec-lite v0.0.4 | sub-agent: fix | date: {{date}} -->
|
|
103
103
|
|
|
104
104
|
# Fix Report: {{issue_title}}
|
|
105
105
|
|
package/prompts/implement.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- spec-lite v0.0.
|
|
1
|
+
<!-- spec-lite v0.0.4 | prompt: integration_test | updated: 2026-02-19 -->
|
|
2
2
|
|
|
3
3
|
# PERSONA: Integration Test Sub-Agent
|
|
4
4
|
|
|
@@ -106,7 +106,7 @@ test("should update user profile and persist to database", async () => { ... });
|
|
|
106
106
|
### Output Template
|
|
107
107
|
|
|
108
108
|
```markdown
|
|
109
|
-
<!-- Generated by spec-lite v0.0.
|
|
109
|
+
<!-- Generated by spec-lite v0.0.4 | sub-agent: integration_tests | date: {{date}} -->
|
|
110
110
|
|
|
111
111
|
# Integration Tests: {{feature_name}}
|
|
112
112
|
|
package/prompts/memorize.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- spec-lite v0.0.
|
|
1
|
+
<!-- spec-lite v0.0.4 | prompt: memorize | updated: 2026-02-19 -->
|
|
2
2
|
|
|
3
3
|
# PERSONA: Memorize Sub-Agent
|
|
4
4
|
|
|
@@ -119,7 +119,7 @@ Use these standard sections. Only create a new section if an instruction truly d
|
|
|
119
119
|
### Output Template
|
|
120
120
|
|
|
121
121
|
```markdown
|
|
122
|
-
<!-- Generated by spec-lite v0.0.
|
|
122
|
+
<!-- Generated by spec-lite v0.0.4 | sub-agent: memorize | updated: {{date}} -->
|
|
123
123
|
|
|
124
124
|
# Memory — Standing Instructions
|
|
125
125
|
|
package/prompts/orchestrator.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- spec-lite v0.0.
|
|
1
|
+
<!-- spec-lite v0.0.4 | prompt: orchestrator | updated: 2026-02-19 -->
|
|
2
2
|
|
|
3
3
|
# PERSONA: Orchestrator — Sub-Agent Pipeline Reference
|
|
4
4
|
|
|
@@ -288,7 +288,7 @@ spec_help (anytime — no prerequisites)
|
|
|
288
288
|
Every generated artifact should include:
|
|
289
289
|
|
|
290
290
|
```markdown
|
|
291
|
-
<!-- Generated by spec-lite v0.0.
|
|
291
|
+
<!-- Generated by spec-lite v0.0.4 | sub-agent: {{name}} | date: {{date}} -->
|
|
292
292
|
```
|
|
293
293
|
|
|
294
294
|
### Plan References
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- spec-lite v0.0.
|
|
1
|
+
<!-- spec-lite v0.0.4 | prompt: performance_review | updated: 2026-02-19 -->
|
|
2
2
|
|
|
3
3
|
# PERSONA: Performance Review Sub-Agent
|
|
4
4
|
|
|
@@ -93,7 +93,7 @@ Before profiling anything, identify:
|
|
|
93
93
|
### Output Template
|
|
94
94
|
|
|
95
95
|
```markdown
|
|
96
|
-
<!-- Generated by spec-lite v0.0.
|
|
96
|
+
<!-- Generated by spec-lite v0.0.4 | sub-agent: performance_review | date: {{date}} -->
|
|
97
97
|
|
|
98
98
|
# Performance Review
|
|
99
99
|
|
package/prompts/planner.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
<!-- spec-lite v0.0.
|
|
1
|
+
<!-- spec-lite v0.0.4 | prompt: planner | updated: 2026-02-19 -->
|
|
2
2
|
|
|
3
3
|
# PERSONA: Planner Sub-Agent
|
|
4
4
|
|
|
5
|
-
You are the **Planner Sub-Agent**, the formidable architect and strategist of the development team. You take the creative vision (from the Brainstorm sub-agent or directly from the user) and transform it into a rigorous, actionable
|
|
5
|
+
You are the **Planner Sub-Agent**, the formidable architect and strategist of the development team. You take the creative vision (from the Brainstorm sub-agent or directly from the user) and transform it into a rigorous, actionable plan into vertical slices/ features. You bridge the gap between "I have an idea" and "Here is exactly how we build it."
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -125,7 +125,7 @@ Multiple plans can coexist in `.spec-lite/` — each represents an independent a
|
|
|
125
125
|
Fill in this template when producing your final output:
|
|
126
126
|
|
|
127
127
|
```markdown
|
|
128
|
-
<!-- Generated by spec-lite v0.0.
|
|
128
|
+
<!-- Generated by spec-lite v0.0.4 | sub-agent: planner | date: {{date}} -->
|
|
129
129
|
|
|
130
130
|
# Plan: {{project_name}}
|
|
131
131
|
|
package/prompts/readme.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- spec-lite v0.0.
|
|
1
|
+
<!-- spec-lite v0.0.4 | prompt: security_audit | updated: 2026-02-19 -->
|
|
2
2
|
|
|
3
3
|
# PERSONA: Security Audit Sub-Agent
|
|
4
4
|
|
|
@@ -97,7 +97,7 @@ For each finding:
|
|
|
97
97
|
### Output Template
|
|
98
98
|
|
|
99
99
|
```markdown
|
|
100
|
-
<!-- Generated by spec-lite v0.0.
|
|
100
|
+
<!-- Generated by spec-lite v0.0.4 | sub-agent: security_audit | date: {{date}} -->
|
|
101
101
|
|
|
102
102
|
# Security Audit Report
|
|
103
103
|
|
package/prompts/spec_help.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- spec-lite v0.0.
|
|
1
|
+
<!-- spec-lite v0.0.4 | prompt: technical_docs | updated: 2026-02-19 -->
|
|
2
2
|
|
|
3
3
|
# PERSONA: Technical Documentation Sub-Agent
|
|
4
4
|
|
|
@@ -91,7 +91,7 @@ Determine which documentation types are needed based on the project and audience
|
|
|
91
91
|
### Output Template
|
|
92
92
|
|
|
93
93
|
```markdown
|
|
94
|
-
<!-- Generated by spec-lite v0.0.
|
|
94
|
+
<!-- Generated by spec-lite v0.0.4 | sub-agent: technical_docs | date: {{date}} -->
|
|
95
95
|
|
|
96
96
|
# {{Document Title}}
|
|
97
97
|
|
package/prompts/unit_tests.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<!-- spec-lite v0.0.
|
|
1
|
+
<!-- spec-lite v0.0.4 | prompt: unit_tests | updated: 2026-02-19 -->
|
|
2
2
|
|
|
3
3
|
# PERSONA: Unit Test Sub-Agent
|
|
4
4
|
|
|
@@ -180,7 +180,7 @@ After classifying files:
|
|
|
180
180
|
### Output Template
|
|
181
181
|
|
|
182
182
|
```markdown
|
|
183
|
-
<!-- Generated by spec-lite v0.0.
|
|
183
|
+
<!-- Generated by spec-lite v0.0.4 | sub-agent: unit_tests | date: {{date}} -->
|
|
184
184
|
|
|
185
185
|
# Unit Tests: {{feature_name}}
|
|
186
186
|
|