bmad-method 6.0.0-alpha.10 → 6.0.0-alpha.11
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/CHANGELOG.md +215 -1109
- package/README.md +129 -359
- package/docs/custom-agent-installation.md +169 -0
- package/{v6-open-items.md → docs/v6-open-items.md} +1 -1
- package/package.json +2 -1
- package/src/core/resources/excalidraw/README.md +160 -0
- package/src/core/resources/excalidraw/library-loader.md +50 -0
- package/src/modules/bmb/docs/agent-compilation.md +340 -0
- package/src/modules/bmb/docs/agent-menu-patterns.md +524 -0
- package/src/modules/bmb/docs/expert-agent-architecture.md +364 -0
- package/src/modules/bmb/docs/index.md +55 -0
- package/src/modules/bmb/docs/module-agent-architecture.md +367 -0
- package/src/modules/bmb/docs/simple-agent-architecture.md +288 -0
- package/src/modules/bmb/docs/understanding-agent-types.md +184 -0
- package/src/modules/bmb/reference/agents/expert-examples/journal-keeper/README.md +242 -0
- package/src/modules/bmb/reference/agents/expert-examples/journal-keeper/journal-keeper-sidecar/breakthroughs.md +24 -0
- package/src/modules/bmb/reference/agents/expert-examples/journal-keeper/journal-keeper-sidecar/instructions.md +108 -0
- package/src/modules/bmb/reference/agents/expert-examples/journal-keeper/journal-keeper-sidecar/memories.md +46 -0
- package/src/modules/bmb/reference/agents/expert-examples/journal-keeper/journal-keeper-sidecar/mood-patterns.md +39 -0
- package/src/modules/bmb/reference/agents/expert-examples/journal-keeper/journal-keeper.agent.yaml +152 -0
- package/src/modules/bmb/reference/agents/module-examples/README.md +50 -0
- package/src/modules/bmb/reference/agents/module-examples/security-engineer.agent.yaml +53 -0
- package/src/modules/bmb/reference/agents/module-examples/trend-analyst.agent.yaml +57 -0
- package/src/modules/bmb/reference/agents/simple-examples/README.md +223 -0
- package/src/modules/bmb/reference/agents/simple-examples/commit-poet.agent.yaml +126 -0
- package/src/modules/bmb/reference/readme.md +3 -0
- package/src/modules/bmb/workflows/create-agent/agent-validation-checklist.md +174 -0
- package/src/modules/bmb/workflows/create-agent/brainstorm-context.md +99 -120
- package/src/modules/bmb/workflows/create-agent/communication-presets.csv +61 -0
- package/src/modules/bmb/workflows/create-agent/instructions.md +126 -65
- package/src/modules/bmb/workflows/create-agent/workflow.yaml +19 -12
- package/src/modules/bmb/workflows/edit-agent/README.md +174 -47
- package/src/modules/bmb/workflows/edit-agent/instructions.md +397 -33
- package/src/modules/bmb/workflows/edit-agent/workflow.yaml +24 -8
- package/src/modules/bmgd/workflows/4-production/story-context/workflow.yaml +1 -1
- package/src/modules/bmm/agents/analyst.agent.yaml +2 -2
- package/src/modules/bmm/agents/architect.agent.yaml +10 -2
- package/src/modules/bmm/agents/dev.agent.yaml +2 -2
- package/src/modules/bmm/agents/pm.agent.yaml +7 -3
- package/src/modules/bmm/agents/sm.agent.yaml +2 -2
- package/src/modules/bmm/agents/tea.agent.yaml +2 -2
- package/src/modules/bmm/agents/tech-writer.agent.yaml +15 -3
- package/src/modules/bmm/agents/ux-designer.agent.yaml +6 -2
- package/src/modules/bmm/docs/README.md +4 -0
- package/src/modules/bmm/docs/images/workflow-method-greenfield.excalidraw +5919 -0
- package/src/modules/bmm/docs/images/workflow-method-greenfield.svg +2 -0
- package/src/modules/bmm/docs/quick-start.md +6 -0
- package/src/modules/bmm/docs/scale-adaptive-system.md +6 -0
- package/src/modules/bmm/docs/workflows-implementation.md +10 -0
- package/src/modules/bmm/workflows/2-plan-workflows/prd/workflow.yaml +4 -4
- package/src/modules/bmm/workflows/{2-plan-workflows → 3-solutioning}/create-epics-and-stories/workflow.yaml +5 -5
- package/src/modules/bmm/workflows/4-implementation/story-context/workflow.yaml +1 -1
- package/src/modules/bmm/workflows/{frame-expert → diagrams}/create-dataflow/instructions.md +7 -8
- package/src/modules/bmm/workflows/diagrams/create-dataflow/workflow.yaml +27 -0
- package/src/modules/bmm/workflows/{frame-expert → diagrams}/create-diagram/instructions.md +9 -10
- package/src/modules/bmm/workflows/diagrams/create-diagram/workflow.yaml +27 -0
- package/src/modules/bmm/workflows/{frame-expert → diagrams}/create-flowchart/instructions.md +4 -5
- package/src/modules/bmm/workflows/diagrams/create-flowchart/workflow.yaml +27 -0
- package/src/modules/bmm/workflows/{frame-expert → diagrams}/create-wireframe/instructions.md +3 -3
- package/src/modules/bmm/workflows/diagrams/create-wireframe/workflow.yaml +27 -0
- package/src/modules/bmm/workflows/workflow-status/paths/enterprise-brownfield.yaml +18 -30
- package/src/modules/bmm/workflows/workflow-status/paths/enterprise-greenfield.yaml +2 -14
- package/src/modules/bmm/workflows/workflow-status/paths/method-brownfield.yaml +2 -14
- package/src/modules/bmm/workflows/workflow-status/paths/method-greenfield.yaml +2 -14
- package/src/modules/cis/agents/presentation-master.agent.yaml +60 -0
- package/tools/cli/commands/agent-install.js +409 -0
- package/tools/cli/installers/lib/core/installer.js +119 -0
- package/tools/cli/installers/lib/ide/_base-ide.js +25 -0
- package/tools/cli/installers/lib/ide/antigravity.js +463 -0
- package/tools/cli/installers/lib/ide/claude-code.js +43 -0
- package/tools/cli/installers/lib/ide/codex.js +217 -32
- package/tools/cli/installers/lib/ide/cursor.js +48 -0
- package/tools/cli/installers/lib/ide/github-copilot.js +74 -0
- package/tools/cli/installers/lib/ide/manager.js +35 -0
- package/tools/cli/installers/lib/ide/opencode.js +45 -0
- package/tools/cli/installers/lib/ide/windsurf.js +47 -0
- package/tools/cli/lib/agent/compiler.js +390 -0
- package/tools/cli/lib/agent/installer.js +725 -0
- package/tools/cli/lib/agent/template-engine.js +152 -0
- package/docs/installers-bundlers/web-bundler-usage.md +0 -54
- package/src/modules/bmb/workflows/create-agent/README.md +0 -203
- package/src/modules/bmb/workflows/create-agent/agent-architecture.md +0 -415
- package/src/modules/bmb/workflows/create-agent/agent-command-patterns.md +0 -759
- package/src/modules/bmb/workflows/create-agent/agent-types.md +0 -292
- package/src/modules/bmb/workflows/create-agent/checklist.md +0 -62
- package/src/modules/bmb/workflows/create-agent/communication-styles.md +0 -202
- package/src/modules/bmb/workflows/edit-agent/checklist.md +0 -112
- package/src/modules/bmb/workflows/redoc/README.md +0 -87
- package/src/modules/bmb/workflows/redoc/checklist.md +0 -99
- package/src/modules/bmb/workflows/redoc/instructions.md +0 -265
- package/src/modules/bmb/workflows/redoc/workflow.yaml +0 -34
- package/src/modules/bmm/agents/frame-expert.agent.yaml +0 -42
- package/src/modules/bmm/workflows/frame-expert/create-dataflow/workflow.yaml +0 -24
- package/src/modules/bmm/workflows/frame-expert/create-diagram/workflow.yaml +0 -25
- package/src/modules/bmm/workflows/frame-expert/create-flowchart/workflow.yaml +0 -28
- package/src/modules/bmm/workflows/frame-expert/create-wireframe/workflow.yaml +0 -24
- package/src/modules/bmm/workflows/workflow-status/paths/game-design.yaml +0 -52
- /package/src/{modules/bmm/workflows/frame-expert/_shared → core/resources/excalidraw}/excalidraw-helpers.md +0 -0
- /package/src/{modules/bmm/workflows/frame-expert/_shared → core/resources/excalidraw}/validate-json-instructions.md +0 -0
- /package/src/modules/bmm/workflows/{2-plan-workflows → 3-solutioning}/create-epics-and-stories/epics-template.md +0 -0
- /package/src/modules/bmm/workflows/{2-plan-workflows → 3-solutioning}/create-epics-and-stories/instructions.md +0 -0
- /package/src/modules/bmm/workflows/{frame-expert → diagrams}/_shared/excalidraw-library.json +0 -0
- /package/src/modules/bmm/workflows/{frame-expert → diagrams}/_shared/excalidraw-templates.yaml +0 -0
- /package/src/modules/bmm/workflows/{frame-expert → diagrams}/create-dataflow/checklist.md +0 -0
- /package/src/modules/bmm/workflows/{frame-expert → diagrams}/create-diagram/checklist.md +0 -0
- /package/src/modules/bmm/workflows/{frame-expert → diagrams}/create-flowchart/checklist.md +0 -0
- /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(
|
|
78
|
-
|
|
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
|
-
|
|
81
|
-
|
|
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
|
-
|
|
85
|
-
|
|
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
|
-
*
|
|
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
|
|
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 };
|