@dedesfr/prompter 0.9.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (216) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +105 -77
  3. package/dist/cli/index.js +25 -1
  4. package/dist/cli/index.js.map +1 -1
  5. package/dist/commands/init.d.ts.map +1 -1
  6. package/dist/commands/init.js +32 -9
  7. package/dist/commands/init.js.map +1 -1
  8. package/dist/commands/login.d.ts +4 -0
  9. package/dist/commands/login.d.ts.map +1 -0
  10. package/dist/commands/login.js +56 -0
  11. package/dist/commands/login.js.map +1 -0
  12. package/dist/commands/logout.d.ts +4 -0
  13. package/dist/commands/logout.d.ts.map +1 -0
  14. package/dist/commands/logout.js +14 -0
  15. package/dist/commands/logout.js.map +1 -0
  16. package/dist/commands/update.d.ts.map +1 -1
  17. package/dist/commands/update.js +18 -5
  18. package/dist/commands/update.js.map +1 -1
  19. package/dist/commands/whoami.d.ts +4 -0
  20. package/dist/commands/whoami.d.ts.map +1 -0
  21. package/dist/commands/whoami.js +42 -0
  22. package/dist/commands/whoami.js.map +1 -0
  23. package/dist/core/auth-store.d.ts +10 -0
  24. package/dist/core/auth-store.d.ts.map +1 -0
  25. package/dist/core/auth-store.js +39 -0
  26. package/dist/core/auth-store.js.map +1 -0
  27. package/dist/core/registry.d.ts +18 -0
  28. package/dist/core/registry.d.ts.map +1 -0
  29. package/dist/core/registry.js +94 -0
  30. package/dist/core/registry.js.map +1 -0
  31. package/package.json +7 -1
  32. package/AGENTS.md +0 -123
  33. package/CLAUDE.md +0 -17
  34. package/build.js +0 -20
  35. package/convex-setup.md +0 -403
  36. package/prompt/ai-humanizer.md +0 -45
  37. package/prompt/api-contract-generator.md +0 -234
  38. package/prompt/apply.md +0 -17
  39. package/prompt/archive.md +0 -21
  40. package/prompt/design-system.md +0 -210
  41. package/prompt/document-explainer.md +0 -149
  42. package/prompt/epic-generator.md +0 -198
  43. package/prompt/epic-single.md +0 -47
  44. package/prompt/erd-generator.md +0 -130
  45. package/prompt/fsd-generator.md +0 -157
  46. package/prompt/prd-agent-generator.md +0 -147
  47. package/prompt/prd-generator.md +0 -195
  48. package/prompt/product-brief.md +0 -289
  49. package/prompt/proposal.md +0 -22
  50. package/prompt/qa-test-scenario.md +0 -133
  51. package/prompt/skill-creator.md +0 -350
  52. package/prompt/story-generator.md +0 -278
  53. package/prompt/story-single.md +0 -70
  54. package/prompt/tdd-generator.md +0 -294
  55. package/prompt/tdd-lite-generator.md +0 -224
  56. package/prompt/wireframe-generator.md +0 -219
  57. package/skills/ai-context-generator/SKILL.md +0 -54
  58. package/skills/ai-context-generator/references/AGENTS.template.md +0 -83
  59. package/skills/ai-context-generator/references/CLAUDE.template.md +0 -39
  60. package/skills/ai-context-generator/references/behavioral-guidelines.md +0 -71
  61. package/skills/ai-context-generator/references/discovery-checklist.md +0 -40
  62. package/skills/ai-context-generator/references/examples/AGENTS.good.md +0 -103
  63. package/skills/ai-context-generator/references/extraction-checklist.md +0 -23
  64. package/skills/ai-context-generator/references/overlays/laravel.md +0 -44
  65. package/skills/ai-humanizer/SKILL.md +0 -50
  66. package/skills/api-contract-generator/SKILL.md +0 -243
  67. package/skills/apply/SKILL.md +0 -23
  68. package/skills/archive/SKILL.md +0 -27
  69. package/skills/cerebro/SKILL.md +0 -187
  70. package/skills/cerebro/references/agents.md +0 -213
  71. package/skills/code-review/SKILL.md +0 -373
  72. package/skills/code-review/assets/report-template-agent.md +0 -212
  73. package/skills/code-review/assets/report-template-compact.md +0 -81
  74. package/skills/code-review/assets/report-template-full.md +0 -264
  75. package/skills/code-review/assets/report-template-human.md +0 -168
  76. package/skills/code-review/references/universal-patterns.md +0 -495
  77. package/skills/design-md/README.md +0 -34
  78. package/skills/design-md/SKILL.md +0 -172
  79. package/skills/design-md/examples/DESIGN.md +0 -154
  80. package/skills/design-system/SKILL.md +0 -216
  81. package/skills/design-system-generator/SKILL.md +0 -324
  82. package/skills/design-system-generator/assets/design-system-template.md +0 -348
  83. package/skills/design-system-generator/references/extraction-patterns.md +0 -321
  84. package/skills/doc-builder/SKILL.md +0 -115
  85. package/skills/doc-builder/references/ui-patterns.md +0 -394
  86. package/skills/document-explainer/SKILL.md +0 -155
  87. package/skills/document-translator/SKILL.md +0 -58
  88. package/skills/enhance/SKILL.md +0 -47
  89. package/skills/enhance-prompt/README.md +0 -34
  90. package/skills/enhance-prompt/SKILL.md +0 -204
  91. package/skills/enhance-prompt/references/KEYWORDS.md +0 -114
  92. package/skills/epic-generator/SKILL.md +0 -204
  93. package/skills/epic-single/SKILL.md +0 -63
  94. package/skills/erd-generator/SKILL.md +0 -138
  95. package/skills/feature-planner/SKILL.md +0 -305
  96. package/skills/feature-planner/assets/implementation-plan-template.md +0 -85
  97. package/skills/frontend-design/LICENSE.txt +0 -177
  98. package/skills/frontend-design/SKILL.md +0 -42
  99. package/skills/fsd-generator/SKILL.md +0 -163
  100. package/skills/gamma-builder/SKILL.md +0 -134
  101. package/skills/laravel-code-review/SKILL.md +0 -383
  102. package/skills/laravel-code-review/assets/report-template-agent.md +0 -195
  103. package/skills/laravel-code-review/assets/report-template-compact.md +0 -79
  104. package/skills/laravel-code-review/assets/report-template-full.md +0 -253
  105. package/skills/laravel-code-review/assets/report-template-human.md +0 -159
  106. package/skills/laravel-code-review/references/laravel-patterns.md +0 -571
  107. package/skills/laravel-code-review/references/php84-features.md +0 -442
  108. package/skills/mcp-builder/LICENSE.txt +0 -202
  109. package/skills/mcp-builder/SKILL.md +0 -236
  110. package/skills/mcp-builder/reference/evaluation.md +0 -602
  111. package/skills/mcp-builder/reference/mcp_best_practices.md +0 -249
  112. package/skills/mcp-builder/reference/node_mcp_server.md +0 -970
  113. package/skills/mcp-builder/reference/python_mcp_server.md +0 -719
  114. package/skills/mcp-builder/scripts/connections.py +0 -151
  115. package/skills/mcp-builder/scripts/evaluation.py +0 -373
  116. package/skills/mcp-builder/scripts/example_evaluation.xml +0 -22
  117. package/skills/mcp-builder/scripts/requirements.txt +0 -2
  118. package/skills/meeting-notes/SKILL.md +0 -159
  119. package/skills/meeting-notes/evals/evals.json +0 -23
  120. package/skills/prd-agent-generator/SKILL.md +0 -132
  121. package/skills/prd-generator/SKILL.md +0 -211
  122. package/skills/product-brief/SKILL.md +0 -141
  123. package/skills/project-orchestrator/SKILL.md +0 -487
  124. package/skills/project-orchestrator/assets/caddy-vps-setup.md +0 -180
  125. package/skills/project-orchestrator/assets/plan-summary-template.md +0 -159
  126. package/skills/prompter-specs/SKILL.md +0 -115
  127. package/skills/prompter-workflow/SKILL.md +0 -166
  128. package/skills/prompter-workflow/evals/evals.json +0 -89
  129. package/skills/proposal/SKILL.md +0 -28
  130. package/skills/qa-test-scenario/SKILL.md +0 -149
  131. package/skills/skill-creator/SKILL.md +0 -173
  132. package/skills/sph-generator/SKILL.md +0 -488
  133. package/skills/story-generator/SKILL.md +0 -285
  134. package/skills/story-single/SKILL.md +0 -86
  135. package/skills/tdd-generator/SKILL.md +0 -300
  136. package/skills/tdd-lite-generator/SKILL.md +0 -230
  137. package/skills/ui-ux-pro/SKILL.md +0 -199
  138. package/skills/ui-ux-pro/assets/design-spec-template.md +0 -173
  139. package/skills/ui-ux-pro/references/component-patterns.md +0 -255
  140. package/skills/ui-ux-pro/references/design-principles.md +0 -167
  141. package/skills/wireframe-generator/SKILL.md +0 -227
  142. package/src/cli/index.ts +0 -223
  143. package/src/commands/archive.ts +0 -302
  144. package/src/commands/change.ts +0 -292
  145. package/src/commands/config.ts +0 -233
  146. package/src/commands/guide.ts +0 -50
  147. package/src/commands/init.ts +0 -597
  148. package/src/commands/list.ts +0 -194
  149. package/src/commands/show.ts +0 -138
  150. package/src/commands/spec.ts +0 -251
  151. package/src/commands/update.ts +0 -129
  152. package/src/commands/upgrade.ts +0 -30
  153. package/src/commands/validate.ts +0 -326
  154. package/src/core/artifact-graph/graph.ts +0 -167
  155. package/src/core/artifact-graph/index.ts +0 -44
  156. package/src/core/artifact-graph/instruction-loader.ts +0 -302
  157. package/src/core/artifact-graph/resolver.ts +0 -226
  158. package/src/core/artifact-graph/schema.ts +0 -124
  159. package/src/core/artifact-graph/state.ts +0 -64
  160. package/src/core/artifact-graph/types.ts +0 -65
  161. package/src/core/completions/command-registry.ts +0 -382
  162. package/src/core/completions/completion-provider.ts +0 -128
  163. package/src/core/completions/generators/bash-generator.ts +0 -191
  164. package/src/core/completions/generators/fish-generator.ts +0 -188
  165. package/src/core/completions/generators/powershell-generator.ts +0 -223
  166. package/src/core/completions/generators/zsh-generator.ts +0 -281
  167. package/src/core/completions/templates/bash-templates.ts +0 -24
  168. package/src/core/completions/templates/fish-templates.ts +0 -40
  169. package/src/core/completions/templates/powershell-templates.ts +0 -25
  170. package/src/core/completions/templates/zsh-templates.ts +0 -36
  171. package/src/core/completions/types.ts +0 -90
  172. package/src/core/config-schema.ts +0 -230
  173. package/src/core/config.ts +0 -181
  174. package/src/core/configurators/slash/antigravity.ts +0 -10
  175. package/src/core/configurators/slash/base.ts +0 -109
  176. package/src/core/configurators/slash/claude.ts +0 -10
  177. package/src/core/configurators/slash/codex.ts +0 -10
  178. package/src/core/configurators/slash/droid.ts +0 -10
  179. package/src/core/configurators/slash/forge.ts +0 -10
  180. package/src/core/configurators/slash/github-copilot.ts +0 -10
  181. package/src/core/configurators/slash/index.ts +0 -10
  182. package/src/core/configurators/slash/kilocode.ts +0 -10
  183. package/src/core/configurators/slash/opencode.ts +0 -10
  184. package/src/core/configurators/slash/registry.ts +0 -51
  185. package/src/core/converters/json-converter.ts +0 -62
  186. package/src/core/global-config.ts +0 -136
  187. package/src/core/parsers/change-parser.ts +0 -234
  188. package/src/core/parsers/markdown-parser.ts +0 -237
  189. package/src/core/parsers/requirement-blocks.ts +0 -234
  190. package/src/core/prompt-templates.ts +0 -3504
  191. package/src/core/schemas/base.schema.ts +0 -20
  192. package/src/core/schemas/change.schema.ts +0 -42
  193. package/src/core/schemas/index.ts +0 -20
  194. package/src/core/schemas/spec.schema.ts +0 -17
  195. package/src/core/skill-discovery.ts +0 -68
  196. package/src/core/specs-apply.ts +0 -483
  197. package/src/core/styles/palette.ts +0 -8
  198. package/src/core/templates/agents-template.ts +0 -459
  199. package/src/core/templates/claude-template.ts +0 -2
  200. package/src/core/templates/index.ts +0 -3
  201. package/src/core/templates/project-template.ts +0 -32
  202. package/src/core/validation/constants.ts +0 -48
  203. package/src/core/validation/types.ts +0 -19
  204. package/src/core/validation/validator.ts +0 -449
  205. package/src/core/view.ts +0 -219
  206. package/src/index.ts +0 -1
  207. package/src/utils/change-metadata.ts +0 -171
  208. package/src/utils/change-utils.ts +0 -131
  209. package/src/utils/file-system.ts +0 -252
  210. package/src/utils/index.ts +0 -12
  211. package/src/utils/interactive.ts +0 -29
  212. package/src/utils/item-discovery.ts +0 -66
  213. package/src/utils/match.ts +0 -26
  214. package/src/utils/shell-detection.ts +0 -62
  215. package/src/utils/task-progress.ts +0 -43
  216. package/tsconfig.json +0 -28
@@ -1,597 +0,0 @@
1
- import { promises as fs } from 'fs';
2
- import path from 'path';
3
- import { fileURLToPath } from 'url';
4
- import chalk from 'chalk';
5
- import { checkbox, Separator } from '@inquirer/prompts';
6
- import { PROMPTER_DIR, SUPPORTED_TOOLS, PrompterConfig } from '../core/config.js';
7
- import { projectTemplate, agentsTemplate, claudeTemplate } from '../core/templates/index.js';
8
- import { registry } from '../core/configurators/slash/index.js';
9
- import { discoverSkills, SkillMetadata } from '../core/skill-discovery.js';
10
-
11
- interface InitOptions {
12
- tools?: string[];
13
- skills?: string[];
14
- noInteractive?: boolean;
15
- }
16
-
17
- export class InitCommand {
18
- private truncateDescription(desc: string, max = 72): string {
19
- return desc.length > max ? desc.slice(0, max - 1) + '…' : desc;
20
- }
21
-
22
- private getCategorizedSkillChoices(availableSkills: SkillMetadata[], currentSkillNames: string[]): any[] {
23
- const categories = [
24
- {
25
- name: 'šŸ“‹ Planning & Strategy',
26
- skills: ['project-orchestrator', 'feature-planner', 'prd-generator', 'prd-agent-generator', 'product-brief']
27
- },
28
- {
29
- name: 'šŸŽÆ Agile & Backlog',
30
- skills: ['epic-single', 'epic-generator', 'story-single', 'story-generator']
31
- },
32
- {
33
- name: 'šŸ“ Specification & Architecture',
34
- skills: ['fsd-generator', 'tdd-generator', 'tdd-lite-generator', 'erd-generator', 'api-contract-generator']
35
- },
36
- {
37
- name: 'šŸŽØ Design & UI/UX',
38
- skills: ['ui-ux-pro', 'design-system-generator', 'design-system', 'wireframe-generator', 'design-md', 'frontend-design']
39
- },
40
- {
41
- name: 'āš™ļø Development & Code Review',
42
- skills: ['code-review', 'laravel-code-review', 'mcp-builder', 'skill-creator']
43
- },
44
- {
45
- name: 'āœ… Testing & QA',
46
- skills: ['qa-test-scenario']
47
- },
48
- {
49
- name: '⚔ Prompter Workflow',
50
- skills: ['prompter-workflow', 'prompter-specs', 'proposal', 'apply', 'archive']
51
- },
52
- {
53
- name: 'šŸ“ Documentation',
54
- skills: ['doc-builder', 'document-translator', 'document-explainer', 'ai-context-generator', 'meeting-notes', 'sph-generator']
55
- },
56
- {
57
- name: '✨ Content & Productivity',
58
- skills: ['enhance', 'enhance-prompt', 'ai-humanizer', 'gamma-builder', 'cerebro']
59
- }
60
- ];
61
-
62
- const categorized = new Set<string>();
63
- const choices: any[] = [];
64
-
65
- for (const category of categories) {
66
- const skillsInCategory = category.skills
67
- .map(name => availableSkills.find(s => s.name === name))
68
- .filter((s): s is SkillMetadata => !!s);
69
-
70
- if (skillsInCategory.length === 0) continue;
71
-
72
- choices.push(new Separator(chalk.bold.cyan(category.name)));
73
- for (const skill of skillsInCategory) {
74
- categorized.add(skill.name);
75
- choices.push({
76
- name: ` ${skill.name} ${chalk.gray('- ' + this.truncateDescription(skill.description))}`,
77
- value: skill.name,
78
- checked: currentSkillNames.includes(skill.name)
79
- });
80
- }
81
- }
82
-
83
- // Uncategorized skills
84
- const uncategorized = availableSkills.filter(s => !categorized.has(s.name));
85
- if (uncategorized.length > 0) {
86
- choices.push(new Separator(chalk.bold.cyan('šŸ”§ Other')));
87
- for (const skill of uncategorized) {
88
- choices.push({
89
- name: ` ${skill.name} ${chalk.gray('- ' + this.truncateDescription(skill.description))}`,
90
- value: skill.name,
91
- checked: currentSkillNames.includes(skill.name)
92
- });
93
- }
94
- }
95
-
96
- return choices;
97
- }
98
-
99
- async execute(options: InitOptions = {}): Promise<void> {
100
- const projectPath = process.cwd();
101
- const isReInitialization = await PrompterConfig.prompterDirExists(projectPath);
102
-
103
- // Display ASCII art banner for initial setup
104
- if (!isReInitialization) {
105
- console.log(chalk.cyan(`
106
- ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆ ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆ ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆ ā–ˆā–ˆā–ˆ ā–ˆā–ˆā–ˆ ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆ ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆ ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆ ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆ
107
- ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆā–ˆā–ˆ ā–ˆā–ˆā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ
108
- ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆ ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆā–ˆā–ˆā–ˆ ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆ
109
- ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ
110
- ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆā–ˆ ā–ˆā–ˆ ā–ˆā–ˆ
111
- `));
112
- console.log(chalk.white.bold('Welcome to Prompter!\n'));
113
- }
114
-
115
- if (isReInitialization) {
116
- console.log(chalk.blue('\nšŸ”„ Re-configuring Prompter tools...\n'));
117
- } else {
118
- console.log(chalk.blue('šŸš€ Initializing Prompter...\n'));
119
- }
120
-
121
- // Detect currently configured tools if re-initializing
122
- let currentTools: string[] = [];
123
- if (isReInitialization) {
124
- currentTools = await this.detectConfiguredTools(projectPath);
125
- if (currentTools.length > 0) {
126
- console.log(chalk.gray('Currently configured tools: ') + chalk.cyan(currentTools.map(t => {
127
- const tool = SUPPORTED_TOOLS.find(st => st.value === t);
128
- return tool ? tool.name : t;
129
- }).join(', ')));
130
- console.log();
131
- }
132
- }
133
-
134
- // Select tools
135
- let selectedTools: string[] = [];
136
-
137
- if (options.tools && options.tools.length > 0) {
138
- // Handle comma-separated values in a single string or array of strings
139
- selectedTools = options.tools.flatMap(tool => tool.split(',').map(t => t.trim()));
140
- } else if (!options.noInteractive) {
141
- try {
142
- const message = isReInitialization
143
- ? 'Select AI tools to configure (check/uncheck to add/remove):'
144
- : 'Select AI tools to configure:';
145
-
146
- selectedTools = await checkbox({
147
- message,
148
- choices: SUPPORTED_TOOLS.map(tool => ({
149
- name: tool.name,
150
- value: tool.value,
151
- checked: isReInitialization
152
- ? currentTools.includes(tool.value)
153
- : tool.value === 'antigravity' // Default check Antigravity for new init
154
- }))
155
- });
156
- } catch (error) {
157
- // User cancelled
158
- console.log(chalk.yellow(isReInitialization ? '\nRe-configuration cancelled.' : '\nInitialization cancelled.'));
159
- return;
160
- }
161
- } else if (isReInitialization && selectedTools.length === 0) {
162
- // In non-interactive re-init without tools specified, keep current tools
163
- selectedTools = currentTools;
164
- }
165
-
166
- // Select skills — resolve from the package directory, not the user's project
167
- // dist/commands/init.js → go up two levels to reach the package root
168
- const packageDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../..');
169
- const availableSkills = await discoverSkills(path.join(packageDir, 'skills'));
170
- let selectedSkills: SkillMetadata[] = [];
171
-
172
- if (options.skills && options.skills.length > 0) {
173
- const requestedNames = options.skills.flatMap(s => s.split(',').map(s => s.trim()));
174
- selectedSkills = availableSkills.filter(s => requestedNames.includes(s.name));
175
- } else if (!options.noInteractive && availableSkills.length > 0) {
176
- try {
177
- const prompterPathForDetection = path.join(projectPath, PROMPTER_DIR);
178
- const currentSkillNames = await this.detectInstalledSkills(prompterPathForDetection);
179
-
180
- const selectedSkillNames = await checkbox({
181
- message: 'Select skills to install:',
182
- choices: this.getCategorizedSkillChoices(availableSkills, currentSkillNames),
183
- pageSize: 20
184
- });
185
- selectedSkills = availableSkills.filter(s => selectedSkillNames.includes(s.name));
186
- } catch (error) {
187
- // User cancelled
188
- console.log(chalk.yellow(isReInitialization ? '\nRe-configuration cancelled.' : '\nInitialization cancelled.'));
189
- return;
190
- }
191
- }
192
-
193
- // Create or ensure prompter directory
194
- const prompterPath = await PrompterConfig.ensurePrompterDir(projectPath);
195
- if (!isReInitialization) {
196
- console.log(chalk.green('āœ“') + ` Created ${chalk.cyan(PROMPTER_DIR + '/')}`);
197
- }
198
-
199
- // Create project.md if not exists
200
- const projectMdPath = path.join(prompterPath, 'project.md');
201
- const projectMdExists = await this.fileExists(projectMdPath);
202
- if (!projectMdExists) {
203
- try {
204
- if (!projectTemplate) {
205
- throw new Error('project.md template is undefined');
206
- }
207
- await fs.writeFile(projectMdPath, projectTemplate, 'utf-8');
208
- console.log(chalk.green('āœ“') + ` Created ${chalk.cyan(PROMPTER_DIR + '/project.md')}`);
209
- } catch (error) {
210
- console.error(chalk.red('āœ—') + ` Failed to create project.md: ${error}`);
211
- }
212
- } else if (isReInitialization) {
213
- console.log(chalk.gray(' project.md already exists, keeping it'));
214
- }
215
-
216
- // Create or update AGENTS.md for universal support
217
- const agentsMdPath = path.join(prompterPath, 'AGENTS.md');
218
- const agentsExists = await this.fileExists(agentsMdPath);
219
- try {
220
- if (!agentsTemplate) {
221
- throw new Error('AGENTS.md template is undefined');
222
- }
223
- await fs.writeFile(agentsMdPath, agentsTemplate, 'utf-8');
224
- if (!agentsExists) {
225
- console.log(chalk.green('āœ“') + ` Created ${chalk.cyan(PROMPTER_DIR + '/AGENTS.md')}`);
226
- } else if (isReInitialization) {
227
- console.log(chalk.green('āœ“') + ` Updated ${chalk.cyan(PROMPTER_DIR + '/AGENTS.md')}`);
228
- }
229
- } catch (error) {
230
- console.error(chalk.red('āœ—') + ` Failed to ${agentsExists ? 'update' : 'create'} AGENTS.md: ${error}`);
231
- }
232
-
233
- // Create or update CLAUDE.md for Claude Code support
234
- const claudeMdPath = path.join(prompterPath, 'CLAUDE.md');
235
- const claudeExists = await this.fileExists(claudeMdPath);
236
- try {
237
- if (!claudeTemplate) {
238
- throw new Error('CLAUDE.md template is undefined');
239
- }
240
- await fs.writeFile(claudeMdPath, claudeTemplate, 'utf-8');
241
- if (!claudeExists) {
242
- console.log(chalk.green('āœ“') + ` Created ${chalk.cyan(PROMPTER_DIR + '/CLAUDE.md')}`);
243
- } else if (isReInitialization) {
244
- console.log(chalk.green('āœ“') + ` Updated ${chalk.cyan(PROMPTER_DIR + '/CLAUDE.md')}`);
245
- }
246
- } catch (error) {
247
- console.error(chalk.red('āœ—') + ` Failed to ${claudeExists ? 'update' : 'create'} CLAUDE.md: ${error}`);
248
- }
249
-
250
- // Ensure root AGENTS.md has Prompter instructions
251
- await this.ensureRootAgentsFile(projectPath);
252
-
253
- // Ensure root CLAUDE.md has Prompter instructions
254
- await this.ensureRootClaudeFile(projectPath);
255
-
256
- // Handle tool changes
257
- const toolsToAdd = selectedTools.filter(t => !currentTools.includes(t));
258
- const toolsToRemove = currentTools.filter(t => !selectedTools.includes(t));
259
- const toolsToKeep = selectedTools.filter(t => currentTools.includes(t));
260
-
261
- // Remove old tool files
262
- if (toolsToRemove.length > 0) {
263
- console.log(chalk.blue('\nšŸ—‘ļø Removing workflow files...\n'));
264
- for (const toolId of toolsToRemove) {
265
- const configurator = registry.get(toolId);
266
- if (configurator) {
267
- try {
268
- const files = await this.removeToolFiles(projectPath, configurator);
269
- for (const file of files) {
270
- console.log(chalk.yellow('āœ“') + ` Removed ${chalk.cyan(file)}`);
271
- }
272
- } catch (error) {
273
- console.log(chalk.red('āœ—') + ` Failed to remove files for ${toolId}: ${error}`);
274
- }
275
- }
276
- }
277
- }
278
-
279
- // Show kept tools
280
- if (isReInitialization && toolsToKeep.length > 0 && (toolsToAdd.length > 0 || toolsToRemove.length > 0)) {
281
- console.log(chalk.blue('\n✨ Keeping existing tools:\n'));
282
- for (const toolId of toolsToKeep) {
283
- const tool = SUPPORTED_TOOLS.find(t => t.value === toolId);
284
- if (tool) {
285
- console.log(chalk.gray(' • ') + chalk.cyan(tool.name));
286
- }
287
- }
288
- }
289
-
290
- // --- Skills setup ---
291
- const skillChanges = await this.setupSkills(projectPath, prompterPath, selectedTools, selectedSkills);
292
-
293
- // Success message
294
- if (isReInitialization) {
295
- console.log(chalk.green('\nāœ… Prompter tools updated successfully!\n'));
296
- if (toolsToAdd.length > 0 || toolsToRemove.length > 0 || skillChanges.added.length > 0 || skillChanges.removed.length > 0) {
297
- console.log(chalk.blue('Summary:'));
298
- if (toolsToAdd.length > 0) {
299
- console.log(chalk.green(' Tools Added: ') + toolsToAdd.map(t => {
300
- const tool = SUPPORTED_TOOLS.find(st => st.value === t);
301
- return tool ? tool.name : t;
302
- }).join(', '));
303
- }
304
- if (toolsToRemove.length > 0) {
305
- console.log(chalk.yellow(' Tools Removed: ') + toolsToRemove.map(t => {
306
- const tool = SUPPORTED_TOOLS.find(st => st.value === t);
307
- return tool ? tool.name : t;
308
- }).join(', '));
309
- }
310
- if (skillChanges.added.length > 0) {
311
- console.log(chalk.green(' Skills Added: ') + skillChanges.added.join(', '));
312
- }
313
- if (skillChanges.removed.length > 0) {
314
- console.log(chalk.yellow(' Skills Removed: ') + skillChanges.removed.join(', '));
315
- }
316
- console.log();
317
- } else {
318
- console.log(chalk.gray(' No changes made.\n'));
319
- }
320
- } else {
321
- console.log(chalk.green('\nāœ… Prompter initialized successfully!\n'));
322
- if (skillChanges.added.length > 0) {
323
- console.log(chalk.gray(`Installed ${skillChanges.added.length} skill(s).\n`));
324
- }
325
- console.log(chalk.gray('Run `prompter guide` for next steps.\n'));
326
- }
327
- }
328
-
329
- private async fileExists(filePath: string): Promise<boolean> {
330
- try {
331
- await fs.access(filePath);
332
- return true;
333
- } catch {
334
- return false;
335
- }
336
- }
337
-
338
- private async detectConfiguredTools(projectPath: string): Promise<string[]> {
339
- const configuredTools: string[] = [];
340
- const allConfigurators = registry.getAll();
341
-
342
- for (const configurator of allConfigurators) {
343
- const skillsRoot = path.join(projectPath, configurator.getSkillsRootDir());
344
- try {
345
- const stat = await fs.stat(skillsRoot);
346
- if (stat.isDirectory()) configuredTools.push(configurator.toolId);
347
- } catch {
348
- // directory doesn't exist — tool not configured
349
- }
350
- }
351
-
352
- return configuredTools;
353
- }
354
-
355
- private async removeToolFiles(projectPath: string, configurator: any): Promise<string[]> {
356
- await configurator.removeAllDeployedSkills(projectPath);
357
- return [configurator.getSkillsRootDir() + '/'];
358
- }
359
-
360
-
361
-
362
- private async ensureRootClaudeFile(projectPath: string): Promise<void> {
363
- const rootClaudePath = path.join(projectPath, 'CLAUDE.md');
364
- const instructionsBlock = `<!-- PROMPTER:START -->
365
- # Prompter Instructions
366
-
367
- These instructions are for AI assistants working in this project.
368
-
369
- Always open \`@/prompter/CLAUDE.md\` when the request:
370
- - Mentions planning or proposals (words like proposal, spec, change, plan)
371
- - Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work
372
- - Sounds ambiguous and you need the authoritative spec before coding
373
-
374
- Use \`@/prompter/CLAUDE.md\` to learn:
375
- - How to create and apply change proposals
376
- - Spec format and conventions
377
- - Project structure and guidelines
378
- - Show Remaining Tasks
379
-
380
- <!-- PROMPTER:END -->`;
381
-
382
- const rootClaudeExists = await this.fileExists(rootClaudePath);
383
-
384
- if (!rootClaudeExists) {
385
- await fs.writeFile(rootClaudePath, instructionsBlock + '\n', 'utf-8');
386
- console.log(chalk.green('āœ“') + ` Created ${chalk.cyan('CLAUDE.md')} in root`);
387
- } else {
388
- const content = await fs.readFile(rootClaudePath, 'utf-8');
389
- const startMarker = '<!-- PROMPTER:START -->';
390
- const endMarker = '<!-- PROMPTER:END -->';
391
- const startIndex = content.indexOf(startMarker);
392
- const endIndex = content.indexOf(endMarker);
393
-
394
- if (startIndex === -1 || endIndex === -1) {
395
- const updatedContent = instructionsBlock + '\n\n' + content;
396
- await fs.writeFile(rootClaudePath, updatedContent, 'utf-8');
397
- console.log(chalk.green('āœ“') + ` Added Prompter instructions to ${chalk.cyan('CLAUDE.md')}`);
398
- } else {
399
- const before = content.substring(0, startIndex);
400
- const after = content.substring(endIndex + endMarker.length);
401
- const updatedContent = before + instructionsBlock + after;
402
- await fs.writeFile(rootClaudePath, updatedContent, 'utf-8');
403
- console.log(chalk.gray(' CLAUDE.md instructions block already exists, updated'));
404
- }
405
- }
406
- }
407
-
408
- private async setupSkills(
409
- projectPath: string,
410
- prompterPath: string,
411
- selectedTools: string[],
412
- selectedSkills: SkillMetadata[]
413
- ): Promise<{ added: string[]; removed: string[] }> {
414
- const result = { added: [] as string[], removed: [] as string[] };
415
-
416
- const installedSkillNames = await this.detectInstalledSkills(prompterPath);
417
- const selectedSkillNames = selectedSkills.map(s => s.name);
418
-
419
- const skillsToAdd = selectedSkills.filter(s => !installedSkillNames.includes(s.name));
420
- const skillsToRemove = installedSkillNames.filter(n => !selectedSkillNames.includes(n));
421
- const skillsToKeep = selectedSkills.filter(s => installedSkillNames.includes(s.name));
422
-
423
- const skillsTargetDir = path.join(prompterPath, 'skills');
424
-
425
- // Remove deselected skills
426
- if (skillsToRemove.length > 0) {
427
- console.log(chalk.blue('\nšŸ—‘ļø Removing skills...\n'));
428
-
429
- for (const skillName of skillsToRemove) {
430
- const staleDir = path.join(skillsTargetDir, skillName);
431
- try {
432
- await fs.rm(staleDir, { recursive: true, force: true });
433
- console.log(chalk.yellow('āœ“') + ` Removed skill ${chalk.cyan(skillName)}`);
434
- result.removed.push(skillName);
435
- } catch {
436
- // ignore
437
- }
438
-
439
- for (const toolId of selectedTools) {
440
- const configurator = registry.get(toolId);
441
- if (!configurator) continue;
442
- const removed = await configurator.removeSkillFiles(projectPath, [skillName]);
443
- for (const file of removed) {
444
- console.log(chalk.yellow('āœ“') + ` Removed ${chalk.cyan(file)}`);
445
- }
446
- }
447
- }
448
- }
449
-
450
- // Install new skills
451
- if (skillsToAdd.length > 0) {
452
- console.log(chalk.blue('\n🧩 Installing skills...\n'));
453
- await fs.mkdir(skillsTargetDir, { recursive: true });
454
-
455
- for (const skill of skillsToAdd) {
456
- const targetDir = path.join(skillsTargetDir, skill.name);
457
- try {
458
- await this.copyDirectory(skill.sourcePath, targetDir);
459
- console.log(chalk.green('āœ“') + ` Installed skill ${chalk.cyan(skill.name)}`);
460
- result.added.push(skill.name);
461
- } catch (error) {
462
- console.log(chalk.red('āœ—') + ` Failed to install skill ${skill.name}: ${error}`);
463
- }
464
- }
465
-
466
- if (selectedTools.length > 0) {
467
- console.log(chalk.blue('\nšŸ“ Creating skill workflow files...\n'));
468
- for (const toolId of selectedTools) {
469
- const configurator = registry.get(toolId);
470
- if (!configurator) continue;
471
- try {
472
- const files = await configurator.generateSkills(projectPath, skillsToAdd);
473
- for (const file of files) {
474
- console.log(chalk.green('āœ“') + ` Created ${chalk.cyan(file)}`);
475
- }
476
- } catch (error) {
477
- console.log(chalk.red('āœ—') + ` Failed to create skill files for ${toolId}: ${error}`);
478
- }
479
- }
480
- }
481
- }
482
-
483
- // Update kept skills
484
- if (skillsToKeep.length > 0) {
485
- await fs.mkdir(skillsTargetDir, { recursive: true });
486
-
487
- for (const skill of skillsToKeep) {
488
- const targetDir = path.join(skillsTargetDir, skill.name);
489
- try {
490
- await this.copyDirectory(skill.sourcePath, targetDir);
491
- } catch {
492
- // ignore update errors
493
- }
494
- }
495
-
496
- for (const toolId of selectedTools) {
497
- const configurator = registry.get(toolId);
498
- if (!configurator) continue;
499
- try {
500
- await configurator.generateSkills(projectPath, skillsToKeep);
501
- } catch {
502
- // ignore
503
- }
504
- }
505
- }
506
-
507
- return result;
508
- }
509
-
510
- private async detectInstalledSkills(prompterPath: string): Promise<string[]> {
511
- const skillsDir = path.join(prompterPath, 'skills');
512
- const names: string[] = [];
513
-
514
- try {
515
- const entries = await fs.readdir(skillsDir, { withFileTypes: true });
516
- for (const entry of entries) {
517
- if (!entry.isDirectory()) continue;
518
- const skillMdPath = path.join(skillsDir, entry.name, 'SKILL.md');
519
- if (await this.fileExists(skillMdPath)) {
520
- names.push(entry.name);
521
- }
522
- }
523
- } catch {
524
- // skills directory doesn't exist yet
525
- }
526
-
527
- return names;
528
- }
529
-
530
- private async copyDirectory(src: string, dest: string): Promise<void> {
531
- await fs.mkdir(dest, { recursive: true });
532
- const entries = await fs.readdir(src, { withFileTypes: true });
533
-
534
- for (const entry of entries) {
535
- const srcPath = path.join(src, entry.name);
536
- const destPath = path.join(dest, entry.name);
537
-
538
- if (entry.isDirectory()) {
539
- await this.copyDirectory(srcPath, destPath);
540
- } else {
541
- await fs.copyFile(srcPath, destPath);
542
- }
543
- }
544
- }
545
-
546
- private async ensureRootAgentsFile(projectPath: string): Promise<void> {
547
- const rootAgentsPath = path.join(projectPath, 'AGENTS.md');
548
- const instructionsBlock = `<!-- PROMPTER:START -->
549
- # Prompter Instructions
550
-
551
- These instructions are for AI assistants working in this project.
552
-
553
- Always open \`@/prompter/AGENTS.md\` when the request:
554
- - Mentions planning or proposals (words like proposal, spec, change, plan)
555
- - Introduces new capabilities, breaking changes, architecture shifts, or big performance/security work
556
- - Sounds ambiguous and you need the authoritative spec before coding
557
-
558
- Use \`@/prompter/AGENTS.md\` to learn:
559
- - How to create and apply change proposals
560
- - Spec format and conventions
561
- - Project structure and guidelines
562
- - Show Remaining Tasks
563
-
564
- <!-- PROMPTER:END -->`;
565
-
566
- const rootAgentsExists = await this.fileExists(rootAgentsPath);
567
-
568
- if (!rootAgentsExists) {
569
- // Create new file with instructions block
570
- await fs.writeFile(rootAgentsPath, instructionsBlock + '\n', 'utf-8');
571
- console.log(chalk.green('āœ“') + ` Created ${chalk.cyan('AGENTS.md')} in root`);
572
- } else {
573
- // Read existing file
574
- const content = await fs.readFile(rootAgentsPath, 'utf-8');
575
-
576
- // Check if instructions block already exists
577
- const startMarker = '<!-- PROMPTER:START -->';
578
- const endMarker = '<!-- PROMPTER:END -->';
579
- const startIndex = content.indexOf(startMarker);
580
- const endIndex = content.indexOf(endMarker);
581
-
582
- if (startIndex === -1 || endIndex === -1) {
583
- // Add instructions block at the top
584
- const updatedContent = instructionsBlock + '\n\n' + content;
585
- await fs.writeFile(rootAgentsPath, updatedContent, 'utf-8');
586
- console.log(chalk.green('āœ“') + ` Added Prompter instructions to ${chalk.cyan('AGENTS.md')}`);
587
- } else {
588
- // Replace existing block
589
- const before = content.substring(0, startIndex);
590
- const after = content.substring(endIndex + endMarker.length);
591
- const updatedContent = before + instructionsBlock + after;
592
- await fs.writeFile(rootAgentsPath, updatedContent, 'utf-8');
593
- console.log(chalk.gray(' AGENTS.md instructions block already exists, updated'));
594
- }
595
- }
596
- }
597
- }