bmad-method 6.0.0-alpha.10 → 6.0.0-alpha.12

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 (107) hide show
  1. package/CHANGELOG.md +219 -1105
  2. package/README.md +129 -359
  3. package/docs/custom-agent-installation.md +169 -0
  4. package/{v6-open-items.md → docs/v6-open-items.md} +1 -1
  5. package/package.json +4 -2
  6. package/src/core/resources/excalidraw/README.md +160 -0
  7. package/src/core/resources/excalidraw/library-loader.md +50 -0
  8. package/src/modules/bmb/docs/agent-compilation.md +340 -0
  9. package/src/modules/bmb/docs/agent-menu-patterns.md +524 -0
  10. package/src/modules/bmb/docs/expert-agent-architecture.md +364 -0
  11. package/src/modules/bmb/docs/index.md +55 -0
  12. package/src/modules/bmb/docs/module-agent-architecture.md +367 -0
  13. package/src/modules/bmb/docs/simple-agent-architecture.md +288 -0
  14. package/src/modules/bmb/docs/understanding-agent-types.md +184 -0
  15. package/src/modules/bmb/reference/agents/expert-examples/journal-keeper/README.md +242 -0
  16. package/src/modules/bmb/reference/agents/expert-examples/journal-keeper/journal-keeper-sidecar/breakthroughs.md +24 -0
  17. package/src/modules/bmb/reference/agents/expert-examples/journal-keeper/journal-keeper-sidecar/instructions.md +108 -0
  18. package/src/modules/bmb/reference/agents/expert-examples/journal-keeper/journal-keeper-sidecar/memories.md +46 -0
  19. package/src/modules/bmb/reference/agents/expert-examples/journal-keeper/journal-keeper-sidecar/mood-patterns.md +39 -0
  20. package/src/modules/bmb/reference/agents/expert-examples/journal-keeper/journal-keeper.agent.yaml +152 -0
  21. package/src/modules/bmb/reference/agents/module-examples/README.md +50 -0
  22. package/src/modules/bmb/reference/agents/module-examples/security-engineer.agent.yaml +53 -0
  23. package/src/modules/bmb/reference/agents/module-examples/trend-analyst.agent.yaml +57 -0
  24. package/src/modules/bmb/reference/agents/simple-examples/README.md +223 -0
  25. package/src/modules/bmb/reference/agents/simple-examples/commit-poet.agent.yaml +126 -0
  26. package/src/modules/bmb/reference/readme.md +3 -0
  27. package/src/modules/bmb/workflows/create-agent/agent-validation-checklist.md +174 -0
  28. package/src/modules/bmb/workflows/create-agent/brainstorm-context.md +99 -120
  29. package/src/modules/bmb/workflows/create-agent/communication-presets.csv +61 -0
  30. package/src/modules/bmb/workflows/create-agent/instructions.md +126 -65
  31. package/src/modules/bmb/workflows/create-agent/workflow.yaml +19 -12
  32. package/src/modules/bmb/workflows/edit-agent/README.md +174 -47
  33. package/src/modules/bmb/workflows/edit-agent/instructions.md +397 -33
  34. package/src/modules/bmb/workflows/edit-agent/workflow.yaml +24 -8
  35. package/src/modules/bmgd/workflows/4-production/story-context/workflow.yaml +1 -1
  36. package/src/modules/bmm/agents/analyst.agent.yaml +2 -2
  37. package/src/modules/bmm/agents/architect.agent.yaml +10 -2
  38. package/src/modules/bmm/agents/dev.agent.yaml +2 -2
  39. package/src/modules/bmm/agents/pm.agent.yaml +7 -3
  40. package/src/modules/bmm/agents/sm.agent.yaml +2 -2
  41. package/src/modules/bmm/agents/tea.agent.yaml +2 -2
  42. package/src/modules/bmm/agents/tech-writer.agent.yaml +15 -3
  43. package/src/modules/bmm/agents/ux-designer.agent.yaml +6 -2
  44. package/src/modules/bmm/docs/README.md +4 -0
  45. package/src/modules/bmm/docs/images/workflow-method-greenfield.excalidraw +5919 -0
  46. package/src/modules/bmm/docs/images/workflow-method-greenfield.svg +2 -0
  47. package/src/modules/bmm/docs/quick-start.md +6 -0
  48. package/src/modules/bmm/docs/scale-adaptive-system.md +6 -0
  49. package/src/modules/bmm/docs/workflows-implementation.md +10 -0
  50. package/src/modules/bmm/workflows/2-plan-workflows/prd/workflow.yaml +4 -4
  51. package/src/modules/bmm/workflows/{2-plan-workflows → 3-solutioning}/create-epics-and-stories/workflow.yaml +5 -5
  52. package/src/modules/bmm/workflows/4-implementation/story-context/workflow.yaml +1 -1
  53. package/src/modules/bmm/workflows/{frame-expert → diagrams}/create-dataflow/instructions.md +7 -8
  54. package/src/modules/bmm/workflows/diagrams/create-dataflow/workflow.yaml +27 -0
  55. package/src/modules/bmm/workflows/{frame-expert → diagrams}/create-diagram/instructions.md +9 -10
  56. package/src/modules/bmm/workflows/diagrams/create-diagram/workflow.yaml +27 -0
  57. package/src/modules/bmm/workflows/{frame-expert → diagrams}/create-flowchart/instructions.md +4 -5
  58. package/src/modules/bmm/workflows/diagrams/create-flowchart/workflow.yaml +27 -0
  59. package/src/modules/bmm/workflows/{frame-expert → diagrams}/create-wireframe/instructions.md +3 -3
  60. package/src/modules/bmm/workflows/diagrams/create-wireframe/workflow.yaml +27 -0
  61. package/src/modules/bmm/workflows/workflow-status/paths/enterprise-brownfield.yaml +18 -30
  62. package/src/modules/bmm/workflows/workflow-status/paths/enterprise-greenfield.yaml +2 -14
  63. package/src/modules/bmm/workflows/workflow-status/paths/method-brownfield.yaml +2 -14
  64. package/src/modules/bmm/workflows/workflow-status/paths/method-greenfield.yaml +2 -14
  65. package/src/modules/cis/agents/presentation-master.agent.yaml +60 -0
  66. package/tools/cli/commands/agent-install.js +409 -0
  67. package/tools/cli/installers/lib/core/installer.js +119 -0
  68. package/tools/cli/installers/lib/ide/_base-ide.js +25 -0
  69. package/tools/cli/installers/lib/ide/antigravity.js +463 -0
  70. package/tools/cli/installers/lib/ide/claude-code.js +43 -0
  71. package/tools/cli/installers/lib/ide/codex.js +217 -32
  72. package/tools/cli/installers/lib/ide/cursor.js +48 -0
  73. package/tools/cli/installers/lib/ide/github-copilot.js +74 -0
  74. package/tools/cli/installers/lib/ide/manager.js +35 -0
  75. package/tools/cli/installers/lib/ide/opencode.js +45 -0
  76. package/tools/cli/installers/lib/ide/windsurf.js +47 -0
  77. package/tools/cli/lib/agent/compiler.js +390 -0
  78. package/tools/cli/lib/agent/installer.js +725 -0
  79. package/tools/cli/lib/agent/template-engine.js +152 -0
  80. package/docs/installers-bundlers/web-bundler-usage.md +0 -54
  81. package/src/modules/bmb/workflows/create-agent/README.md +0 -203
  82. package/src/modules/bmb/workflows/create-agent/agent-architecture.md +0 -415
  83. package/src/modules/bmb/workflows/create-agent/agent-command-patterns.md +0 -759
  84. package/src/modules/bmb/workflows/create-agent/agent-types.md +0 -292
  85. package/src/modules/bmb/workflows/create-agent/checklist.md +0 -62
  86. package/src/modules/bmb/workflows/create-agent/communication-styles.md +0 -202
  87. package/src/modules/bmb/workflows/edit-agent/checklist.md +0 -112
  88. package/src/modules/bmb/workflows/redoc/README.md +0 -87
  89. package/src/modules/bmb/workflows/redoc/checklist.md +0 -99
  90. package/src/modules/bmb/workflows/redoc/instructions.md +0 -265
  91. package/src/modules/bmb/workflows/redoc/workflow.yaml +0 -34
  92. package/src/modules/bmm/agents/frame-expert.agent.yaml +0 -42
  93. package/src/modules/bmm/workflows/frame-expert/create-dataflow/workflow.yaml +0 -24
  94. package/src/modules/bmm/workflows/frame-expert/create-diagram/workflow.yaml +0 -25
  95. package/src/modules/bmm/workflows/frame-expert/create-flowchart/workflow.yaml +0 -28
  96. package/src/modules/bmm/workflows/frame-expert/create-wireframe/workflow.yaml +0 -24
  97. package/src/modules/bmm/workflows/workflow-status/paths/game-design.yaml +0 -52
  98. /package/src/{modules/bmm/workflows/frame-expert/_shared → core/resources/excalidraw}/excalidraw-helpers.md +0 -0
  99. /package/src/{modules/bmm/workflows/frame-expert/_shared → core/resources/excalidraw}/validate-json-instructions.md +0 -0
  100. /package/src/modules/bmm/workflows/{2-plan-workflows → 3-solutioning}/create-epics-and-stories/epics-template.md +0 -0
  101. /package/src/modules/bmm/workflows/{2-plan-workflows → 3-solutioning}/create-epics-and-stories/instructions.md +0 -0
  102. /package/src/modules/bmm/workflows/{frame-expert → diagrams}/_shared/excalidraw-library.json +0 -0
  103. /package/src/modules/bmm/workflows/{frame-expert → diagrams}/_shared/excalidraw-templates.yaml +0 -0
  104. /package/src/modules/bmm/workflows/{frame-expert → diagrams}/create-dataflow/checklist.md +0 -0
  105. /package/src/modules/bmm/workflows/{frame-expert → diagrams}/create-diagram/checklist.md +0 -0
  106. /package/src/modules/bmm/workflows/{frame-expert → diagrams}/create-flowchart/checklist.md +0 -0
  107. /package/src/modules/bmm/workflows/{frame-expert → diagrams}/create-wireframe/checklist.md +0 -0
@@ -15,6 +15,67 @@ class CodexSetup extends BaseIdeSetup {
15
15
  super('codex', 'Codex', true); // preferred IDE
16
16
  }
17
17
 
18
+ /**
19
+ * Collect configuration choices before installation
20
+ * @param {Object} options - Configuration options
21
+ * @returns {Object} Collected configuration
22
+ */
23
+ async collectConfiguration(options = {}) {
24
+ const inquirer = require('inquirer');
25
+
26
+ let confirmed = false;
27
+ let installLocation = 'global';
28
+
29
+ while (!confirmed) {
30
+ const { location } = await inquirer.prompt([
31
+ {
32
+ type: 'list',
33
+ name: 'location',
34
+ message: 'Where would you like to install Codex CLI prompts?',
35
+ choices: [
36
+ {
37
+ name: 'Global - Simple for single project ' + '(~/.codex/prompts, but references THIS project only)',
38
+ value: 'global',
39
+ },
40
+ {
41
+ name: `Project-specific - Recommended for real work (requires CODEX_HOME=<project-dir>${path.sep}.codex)`,
42
+ value: 'project',
43
+ },
44
+ ],
45
+ default: 'global',
46
+ },
47
+ ]);
48
+
49
+ installLocation = location;
50
+
51
+ // Display detailed instructions for the chosen option
52
+ console.log('');
53
+ if (installLocation === 'project') {
54
+ console.log(this.getProjectSpecificInstructions());
55
+ } else {
56
+ console.log(this.getGlobalInstructions());
57
+ }
58
+
59
+ // Confirm the choice
60
+ const { proceed } = await inquirer.prompt([
61
+ {
62
+ type: 'confirm',
63
+ name: 'proceed',
64
+ message: 'Proceed with this installation option?',
65
+ default: true,
66
+ },
67
+ ]);
68
+
69
+ confirmed = proceed;
70
+
71
+ if (!confirmed) {
72
+ console.log(chalk.yellow("\n Let's choose a different installation option.\n"));
73
+ }
74
+ }
75
+
76
+ return { installLocation };
77
+ }
78
+
18
79
  /**
19
80
  * Setup Codex configuration
20
81
  * @param {string} projectDir - Project directory
@@ -27,9 +88,12 @@ class CodexSetup extends BaseIdeSetup {
27
88
  // Always use CLI mode
28
89
  const mode = 'cli';
29
90
 
91
+ // Get installation location from pre-collected config or default to global
92
+ const installLocation = options.preCollectedConfig?.installLocation || 'global';
93
+
30
94
  const { artifacts, counts } = await this.collectClaudeArtifacts(projectDir, bmadDir, options);
31
95
 
32
- const destDir = this.getCodexPromptDir();
96
+ const destDir = this.getCodexPromptDir(projectDir, installLocation);
33
97
  await fs.ensureDir(destDir);
34
98
  await this.clearOldBmadFiles(destDir);
35
99
  const written = await this.flattenAndWriteArtifacts(artifacts, destDir);
@@ -45,22 +109,6 @@ class CodexSetup extends BaseIdeSetup {
45
109
  console.log(chalk.dim(` - ${written} Codex prompt files written`));
46
110
  console.log(chalk.dim(` - Destination: ${destDir}`));
47
111
 
48
- // Prominent notice about home directory installation
49
- console.log('');
50
- console.log(chalk.bold.cyan('═'.repeat(70)));
51
- console.log(chalk.bold.yellow(' IMPORTANT: Codex Configuration'));
52
- console.log(chalk.bold.cyan('═'.repeat(70)));
53
- console.log('');
54
- console.log(chalk.white(' Prompts have been installed to your HOME DIRECTORY, not this project.'));
55
- console.log(chalk.white(' No .codex file was created in the project root.'));
56
- console.log('');
57
- console.log(chalk.green(' ✓ You can now use slash commands (/) in Codex CLI'));
58
- console.log(chalk.dim(' Example: /bmad-bmm-agents-pm'));
59
- console.log(chalk.dim(' Type / to see all available commands'));
60
- console.log('');
61
- console.log(chalk.bold.cyan('═'.repeat(70)));
62
- console.log('');
63
-
64
112
  return {
65
113
  success: true,
66
114
  mode,
@@ -68,21 +116,36 @@ class CodexSetup extends BaseIdeSetup {
68
116
  counts,
69
117
  destination: destDir,
70
118
  written,
119
+ installLocation,
71
120
  };
72
121
  }
73
122
 
74
123
  /**
75
124
  * Detect Codex installation by checking for BMAD prompt exports
76
125
  */
77
- async detect(_projectDir) {
78
- const destDir = this.getCodexPromptDir();
126
+ async detect(projectDir) {
127
+ // Check both global and project-specific locations
128
+ const globalDir = this.getCodexPromptDir(null, 'global');
129
+ const projectDir_local = projectDir || process.cwd();
130
+ const projectSpecificDir = this.getCodexPromptDir(projectDir_local, 'project');
79
131
 
80
- if (!(await fs.pathExists(destDir))) {
81
- return false;
132
+ // Check global location
133
+ if (await fs.pathExists(globalDir)) {
134
+ const entries = await fs.readdir(globalDir);
135
+ if (entries.some((entry) => entry.startsWith('bmad-'))) {
136
+ return true;
137
+ }
82
138
  }
83
139
 
84
- const entries = await fs.readdir(destDir);
85
- return entries.some((entry) => entry.startsWith('bmad-'));
140
+ // Check project-specific location
141
+ if (await fs.pathExists(projectSpecificDir)) {
142
+ const entries = await fs.readdir(projectSpecificDir);
143
+ if (entries.some((entry) => entry.startsWith('bmad-'))) {
144
+ return true;
145
+ }
146
+ }
147
+
148
+ return false;
86
149
  }
87
150
 
88
151
  /**
@@ -142,15 +205,13 @@ class CodexSetup extends BaseIdeSetup {
142
205
  };
143
206
  }
144
207
 
145
- getCodexPromptDir() {
208
+ getCodexPromptDir(projectDir = null, location = 'global') {
209
+ if (location === 'project' && projectDir) {
210
+ return path.join(projectDir, '.codex', 'prompts');
211
+ }
146
212
  return path.join(os.homedir(), '.codex', 'prompts');
147
213
  }
148
214
 
149
- flattenFilename(relativePath) {
150
- const sanitized = relativePath.replaceAll(/[\\/]/g, '-');
151
- return `bmad-${sanitized}`;
152
- }
153
-
154
215
  async flattenAndWriteArtifacts(artifacts, destDir) {
155
216
  let written = 0;
156
217
 
@@ -192,11 +253,135 @@ class CodexSetup extends BaseIdeSetup {
192
253
  }
193
254
 
194
255
  /**
195
- * Cleanup Codex configuration (no-op until export destination is finalized)
256
+ * Get instructions for global installation
257
+ * @returns {string} Instructions text
258
+ */
259
+ getGlobalInstructions(destDir) {
260
+ const lines = [
261
+ '',
262
+ chalk.bold.cyan('═'.repeat(70)),
263
+ chalk.bold.yellow(' IMPORTANT: Codex Configuration'),
264
+ chalk.bold.cyan('═'.repeat(70)),
265
+ '',
266
+ chalk.white(' /prompts installed globally to your HOME DIRECTORY.'),
267
+ '',
268
+ chalk.yellow(' ⚠️ These prompts reference a specific .bmad path'),
269
+ chalk.dim(" To use with other projects, you'd need to copy the .bmad dir"),
270
+ '',
271
+ chalk.green(' ✓ You can now use /commands in Codex CLI'),
272
+ chalk.dim(' Example: /bmad-bmm-agents-pm'),
273
+ chalk.dim(' Type / to see all available commands'),
274
+ '',
275
+ chalk.bold.cyan('═'.repeat(70)),
276
+ '',
277
+ ];
278
+ return lines.join('\n');
279
+ }
280
+
281
+ /**
282
+ * Get instructions for project-specific installation
283
+ * @param {string} projectDir - Optional project directory
284
+ * @param {string} destDir - Optional destination directory
285
+ * @returns {string} Instructions text
286
+ */
287
+ getProjectSpecificInstructions(projectDir = null, destDir = null) {
288
+ const isWindows = os.platform() === 'win32';
289
+
290
+ const commonLines = [
291
+ '',
292
+ chalk.bold.cyan('═'.repeat(70)),
293
+ chalk.bold.yellow(' Project-Specific Codex Configuration'),
294
+ chalk.bold.cyan('═'.repeat(70)),
295
+ '',
296
+ chalk.white(' Prompts will be installed to: ') + chalk.cyan(destDir || '<project>/.codex/prompts'),
297
+ '',
298
+ chalk.bold.yellow(' ⚠️ REQUIRED: You must set CODEX_HOME to use these prompts'),
299
+ '',
300
+ ];
301
+
302
+ const windowsLines = [
303
+ chalk.bold(' Create a codex.cmd file in your project root:'),
304
+ '',
305
+ chalk.green(' @echo off'),
306
+ chalk.green(' set CODEX_HOME=%~dp0.codex'),
307
+ chalk.green(' codex %*'),
308
+ '',
309
+ chalk.dim(String.raw` Then run: .\codex instead of codex`),
310
+ chalk.dim(' (The %~dp0 gets the directory of the .cmd file)'),
311
+ ];
312
+
313
+ const unixLines = [
314
+ chalk.bold(' Add this alias to your ~/.bashrc or ~/.zshrc:'),
315
+ '',
316
+ chalk.green(' alias codex=\'CODEX_HOME="$PWD/.codex" codex\''),
317
+ '',
318
+ chalk.dim(' After adding, run: source ~/.bashrc (or source ~/.zshrc)'),
319
+ chalk.dim(' (The $PWD uses your current working directory)'),
320
+ ];
321
+ const closingLines = [
322
+ '',
323
+ chalk.dim(' This tells Codex CLI to use prompts from this project instead of ~/.codex'),
324
+ '',
325
+ chalk.bold.cyan('═'.repeat(70)),
326
+ '',
327
+ ];
328
+
329
+ const lines = [...commonLines, ...(isWindows ? windowsLines : unixLines), ...closingLines];
330
+
331
+ return lines.join('\n');
332
+ }
333
+
334
+ /**
335
+ * Cleanup Codex configuration
196
336
  */
197
- async cleanup() {
337
+ async cleanup(projectDir = null) {
338
+ // Clean both global and project-specific locations
339
+ const globalDir = this.getCodexPromptDir(null, 'global');
340
+ await this.clearOldBmadFiles(globalDir);
341
+
342
+ if (projectDir) {
343
+ const projectSpecificDir = this.getCodexPromptDir(projectDir, 'project');
344
+ await this.clearOldBmadFiles(projectSpecificDir);
345
+ }
346
+ }
347
+
348
+ /**
349
+ * Install a custom agent launcher for Codex
350
+ * @param {string} projectDir - Project directory (not used, Codex installs to home)
351
+ * @param {string} agentName - Agent name (e.g., "fred-commit-poet")
352
+ * @param {string} agentPath - Path to compiled agent (relative to project root)
353
+ * @param {Object} metadata - Agent metadata
354
+ * @returns {Object|null} Info about created command
355
+ */
356
+ async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) {
198
357
  const destDir = this.getCodexPromptDir();
199
- await this.clearOldBmadFiles(destDir);
358
+ await fs.ensureDir(destDir);
359
+
360
+ const launcherContent = `---
361
+ name: '${agentName}'
362
+ description: '${agentName} agent'
363
+ ---
364
+
365
+ You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
366
+
367
+ <agent-activation CRITICAL="TRUE">
368
+ 1. LOAD the FULL agent file from @${agentPath}
369
+ 2. READ its entire contents - this contains the complete agent persona, menu, and instructions
370
+ 3. FOLLOW every step in the <activation> section precisely
371
+ 4. DISPLAY the welcome/greeting as instructed
372
+ 5. PRESENT the numbered menu
373
+ 6. WAIT for user input before proceeding
374
+ </agent-activation>
375
+ `;
376
+
377
+ const fileName = `bmad-custom-agents-${agentName}.md`;
378
+ const launcherPath = path.join(destDir, fileName);
379
+ await fs.writeFile(launcherPath, launcherContent, 'utf8');
380
+
381
+ return {
382
+ path: launcherPath,
383
+ command: `/${fileName.replace('.md', '')}`,
384
+ };
200
385
  }
201
386
  }
202
387
 
@@ -347,6 +347,54 @@ alwaysApply: false
347
347
  // Return MDC header + launcher content (without its original frontmatter)
348
348
  return mdcHeader + contentWithoutFrontmatter;
349
349
  }
350
+
351
+ /**
352
+ * Install a custom agent launcher for Cursor
353
+ * @param {string} projectDir - Project directory
354
+ * @param {string} agentName - Agent name (e.g., "fred-commit-poet")
355
+ * @param {string} agentPath - Path to compiled agent (relative to project root)
356
+ * @param {Object} metadata - Agent metadata
357
+ * @returns {Object|null} Info about created command
358
+ */
359
+ async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) {
360
+ const customAgentsDir = path.join(projectDir, this.configDir, this.rulesDir, 'bmad', 'custom', 'agents');
361
+
362
+ if (!(await this.exists(path.join(projectDir, this.configDir)))) {
363
+ return null; // IDE not configured for this project
364
+ }
365
+
366
+ await this.ensureDir(customAgentsDir);
367
+
368
+ const launcherContent = `You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
369
+
370
+ <agent-activation CRITICAL="TRUE">
371
+ 1. LOAD the FULL agent file from @${agentPath}
372
+ 2. READ its entire contents - this contains the complete agent persona, menu, and instructions
373
+ 3. FOLLOW every step in the <activation> section precisely
374
+ 4. DISPLAY the welcome/greeting as instructed
375
+ 5. PRESENT the numbered menu
376
+ 6. WAIT for user input before proceeding
377
+ </agent-activation>
378
+ `;
379
+
380
+ // Cursor uses MDC format with metadata header
381
+ const mdcContent = `---
382
+ description: "${agentName} agent"
383
+ globs:
384
+ alwaysApply: false
385
+ ---
386
+
387
+ ${launcherContent}
388
+ `;
389
+
390
+ const launcherPath = path.join(customAgentsDir, `${agentName}.mdc`);
391
+ await this.writeFile(launcherPath, mdcContent);
392
+
393
+ return {
394
+ path: launcherPath,
395
+ command: `@${agentName}`,
396
+ };
397
+ }
350
398
  }
351
399
 
352
400
  module.exports = { CursorSetup };
@@ -297,6 +297,80 @@ ${cleanContent}
297
297
  }
298
298
  }
299
299
  }
300
+
301
+ /**
302
+ * Install a custom agent launcher for GitHub Copilot
303
+ * @param {string} projectDir - Project directory
304
+ * @param {string} agentName - Agent name (e.g., "fred-commit-poet")
305
+ * @param {string} agentPath - Path to compiled agent (relative to project root)
306
+ * @param {Object} metadata - Agent metadata
307
+ * @returns {Object|null} Info about created command
308
+ */
309
+ async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) {
310
+ const chatmodesDir = path.join(projectDir, this.configDir, this.chatmodesDir);
311
+
312
+ if (!(await this.exists(path.join(projectDir, this.configDir)))) {
313
+ return null; // IDE not configured for this project
314
+ }
315
+
316
+ await this.ensureDir(chatmodesDir);
317
+
318
+ const launcherContent = `You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
319
+
320
+ <agent-activation CRITICAL="TRUE">
321
+ 1. LOAD the FULL agent file from @${agentPath}
322
+ 2. READ its entire contents - this contains the complete agent persona, menu, and instructions
323
+ 3. FOLLOW every step in the <activation> section precisely
324
+ 4. DISPLAY the welcome/greeting as instructed
325
+ 5. PRESENT the numbered menu
326
+ 6. WAIT for user input before proceeding
327
+ </agent-activation>
328
+ `;
329
+
330
+ // GitHub Copilot needs specific tools in frontmatter
331
+ const copilotTools = [
332
+ 'changes',
333
+ 'codebase',
334
+ 'createDirectory',
335
+ 'createFile',
336
+ 'editFiles',
337
+ 'fetch',
338
+ 'fileSearch',
339
+ 'githubRepo',
340
+ 'listDirectory',
341
+ 'problems',
342
+ 'readFile',
343
+ 'runInTerminal',
344
+ 'runTask',
345
+ 'runTests',
346
+ 'runVscodeCommand',
347
+ 'search',
348
+ 'searchResults',
349
+ 'terminalLastCommand',
350
+ 'terminalSelection',
351
+ 'testFailure',
352
+ 'textSearch',
353
+ 'usages',
354
+ ];
355
+
356
+ const chatmodeContent = `---
357
+ description: "Activates the ${metadata.title || agentName} agent persona."
358
+ tools: ${JSON.stringify(copilotTools)}
359
+ ---
360
+
361
+ # ${metadata.title || agentName} Agent
362
+
363
+ ${launcherContent}
364
+ `;
365
+
366
+ const chatmodePath = path.join(chatmodesDir, `bmad-agent-custom-${agentName}.chatmode.md`);
367
+ await this.writeFile(chatmodePath, chatmodeContent);
368
+
369
+ return {
370
+ path: chatmodePath,
371
+ command: `bmad-agent-custom-${agentName}`,
372
+ };
373
+ }
300
374
  }
301
375
 
302
376
  module.exports = { GitHubCopilotSetup };
@@ -204,6 +204,41 @@ class IdeManager {
204
204
 
205
205
  return detected;
206
206
  }
207
+
208
+ /**
209
+ * Install custom agent launchers for specified IDEs
210
+ * @param {Array} ides - List of IDE names to install for
211
+ * @param {string} projectDir - Project directory
212
+ * @param {string} agentName - Agent name (e.g., "fred-commit-poet")
213
+ * @param {string} agentPath - Path to compiled agent (relative to project root)
214
+ * @param {Object} metadata - Agent metadata
215
+ * @returns {Object} Results for each IDE
216
+ */
217
+ async installCustomAgentLaunchers(ides, projectDir, agentName, agentPath, metadata) {
218
+ const results = {};
219
+
220
+ for (const ideName of ides) {
221
+ const handler = this.handlers.get(ideName.toLowerCase());
222
+
223
+ if (!handler) {
224
+ console.warn(chalk.yellow(`⚠️ IDE '${ideName}' is not yet supported for custom agent installation`));
225
+ continue;
226
+ }
227
+
228
+ try {
229
+ if (typeof handler.installCustomAgentLauncher === 'function') {
230
+ const result = await handler.installCustomAgentLauncher(projectDir, agentName, agentPath, metadata);
231
+ if (result) {
232
+ results[ideName] = result;
233
+ }
234
+ }
235
+ } catch (error) {
236
+ console.warn(chalk.yellow(`⚠️ Failed to install ${ideName} launcher: ${error.message}`));
237
+ }
238
+ }
239
+
240
+ return results;
241
+ }
207
242
  }
208
243
 
209
244
  module.exports = { IdeManager };
@@ -207,6 +207,51 @@ class OpenCodeSetup extends BaseIdeSetup {
207
207
  console.log(chalk.dim(` Cleaned up ${removed} existing BMAD files`));
208
208
  }
209
209
  }
210
+
211
+ /**
212
+ * Install a custom agent launcher for OpenCode
213
+ * @param {string} projectDir - Project directory
214
+ * @param {string} agentName - Agent name (e.g., "fred-commit-poet")
215
+ * @param {string} agentPath - Path to compiled agent (relative to project root)
216
+ * @param {Object} metadata - Agent metadata
217
+ * @returns {Object|null} Info about created command
218
+ */
219
+ async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) {
220
+ const agentsDir = path.join(projectDir, this.configDir, this.agentsDir);
221
+
222
+ if (!(await this.exists(path.join(projectDir, this.configDir)))) {
223
+ return null; // IDE not configured for this project
224
+ }
225
+
226
+ await this.ensureDir(agentsDir);
227
+
228
+ const launcherContent = `---
229
+ name: '${agentName}'
230
+ description: '${metadata.title || agentName} agent'
231
+ mode: 'primary'
232
+ ---
233
+
234
+ You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
235
+
236
+ <agent-activation CRITICAL="TRUE">
237
+ 1. LOAD the FULL agent file from @${agentPath}
238
+ 2. READ its entire contents - this contains the complete agent persona, menu, and instructions
239
+ 3. FOLLOW every step in the <activation> section precisely
240
+ 4. DISPLAY the welcome/greeting as instructed
241
+ 5. PRESENT the numbered menu
242
+ 6. WAIT for user input before proceeding
243
+ </agent-activation>
244
+ `;
245
+
246
+ // OpenCode uses flat naming: bmad-agent-custom-{name}.md
247
+ const launcherPath = path.join(agentsDir, `bmad-agent-custom-${agentName}.md`);
248
+ await this.writeFile(launcherPath, launcherContent);
249
+
250
+ return {
251
+ path: launcherPath,
252
+ command: `bmad-agent-custom-${agentName}`,
253
+ };
254
+ }
210
255
  }
211
256
 
212
257
  module.exports = { OpenCodeSetup };
@@ -206,6 +206,53 @@ ${content}`;
206
206
  console.log(chalk.dim(` Cleaned up existing BMAD workflows`));
207
207
  }
208
208
  }
209
+
210
+ /**
211
+ * Install a custom agent launcher for Windsurf
212
+ * @param {string} projectDir - Project directory
213
+ * @param {string} agentName - Agent name (e.g., "fred-commit-poet")
214
+ * @param {string} agentPath - Path to compiled agent (relative to project root)
215
+ * @param {Object} metadata - Agent metadata
216
+ * @returns {Object|null} Info about created command
217
+ */
218
+ async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) {
219
+ const fs = require('fs-extra');
220
+ const customAgentsDir = path.join(projectDir, this.configDir, this.workflowsDir, 'bmad', 'custom', 'agents');
221
+
222
+ if (!(await this.exists(path.join(projectDir, this.configDir)))) {
223
+ return null; // IDE not configured for this project
224
+ }
225
+
226
+ await this.ensureDir(customAgentsDir);
227
+
228
+ const launcherContent = `You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
229
+
230
+ <agent-activation CRITICAL="TRUE">
231
+ 1. LOAD the FULL agent file from @${agentPath}
232
+ 2. READ its entire contents - this contains the complete agent persona, menu, and instructions
233
+ 3. FOLLOW every step in the <activation> section precisely
234
+ 4. DISPLAY the welcome/greeting as instructed
235
+ 5. PRESENT the numbered menu
236
+ 6. WAIT for user input before proceeding
237
+ </agent-activation>
238
+ `;
239
+
240
+ // Windsurf uses workflow format with frontmatter
241
+ const workflowContent = `---
242
+ description: ${metadata.title || agentName}
243
+ auto_execution_mode: 3
244
+ ---
245
+
246
+ ${launcherContent}`;
247
+
248
+ const launcherPath = path.join(customAgentsDir, `${agentName}.md`);
249
+ await fs.writeFile(launcherPath, workflowContent);
250
+
251
+ return {
252
+ path: launcherPath,
253
+ command: `bmad/custom/agents/${agentName}`,
254
+ };
255
+ }
209
256
  }
210
257
 
211
258
  module.exports = { WindsurfSetup };