bmad-method 4.27.6 → 5.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.
- package/.bmad-core/agent-teams/team-all.yml +16 -0
- package/.bmad-core/agent-teams/team-fullstack.yml +26 -0
- package/.bmad-core/agent-teams/team-no-ui.yml +15 -0
- package/{bmad-core → .bmad-core}/agents/analyst.md +23 -29
- package/.bmad-core/agents/architect.md +66 -0
- package/.bmad-core/agents/bmad-master.md +104 -0
- package/.bmad-core/agents/bmad-orchestrator.md +81 -0
- package/.bmad-core/agents/dev.md +70 -0
- package/{bmad-core → .bmad-core}/agents/pm.md +24 -24
- package/{bmad-core → .bmad-core}/agents/po.md +24 -27
- package/.bmad-core/agents/qa.md +52 -0
- package/.bmad-core/agents/sm.md +55 -0
- package/.bmad-core/agents/ux-expert.md +66 -0
- package/{bmad-core → .bmad-core}/checklists/change-checklist.md +2 -2
- package/{bmad-core → .bmad-core}/checklists/story-draft-checklist.md +1 -1
- package/.bmad-core/data/bmad-kb.md +47 -0
- package/.bmad-core/schemas/agent-team-schema.yml +153 -0
- package/.bmad-core/tasks/advanced-elicitation.md +92 -0
- package/.bmad-core/tasks/brainstorming-techniques.md +238 -0
- package/.bmad-core/tasks/core-dump.md +74 -0
- package/{expansion-packs/bmad-creator-tools → .bmad-core}/tasks/create-agent.md +11 -9
- package/.bmad-core/tasks/create-doc.md +74 -0
- package/.bmad-core/tasks/create-expansion-pack.md +425 -0
- package/.bmad-core/tasks/create-next-story.md +206 -0
- package/.bmad-core/tasks/create-team.md +229 -0
- package/{bmad-core → .bmad-core}/tasks/doc-migration-task.md +9 -9
- package/{common → .bmad-core}/tasks/execute-checklist.md +6 -2
- package/.bmad-core/tasks/generate-ai-frontend-prompt.md +58 -0
- package/{bmad-core → .bmad-core}/tasks/index-docs.md +7 -3
- package/{bmad-core → .bmad-core}/tasks/shard-doc.md +7 -25
- package/.bmad-core/templates/agent-tmpl.md +58 -0
- package/.bmad-core/templates/architecture-tmpl.md +771 -0
- package/.bmad-core/templates/brownfield-architecture-tmpl.md +542 -0
- package/.bmad-core/templates/brownfield-prd-tmpl.md +240 -0
- package/.bmad-core/templates/competitor-analysis-tmpl.md +289 -0
- package/.bmad-core/templates/expansion-pack-plan-tmpl.md +91 -0
- package/.bmad-core/templates/front-end-architecture-tmpl.md +173 -0
- package/.bmad-core/templates/front-end-spec-tmpl.md +411 -0
- package/.bmad-core/templates/fullstack-architecture-tmpl.md +1016 -0
- package/.bmad-core/templates/market-research-tmpl.md +261 -0
- package/.bmad-core/templates/prd-tmpl.md +200 -0
- package/.bmad-core/templates/project-brief-tmpl.md +228 -0
- package/.bmad-core/templates/simple-project-prd-tmpl.md +461 -0
- package/.bmad-core/templates/story-tmpl.md +61 -0
- package/.bmad-core/templates/web-agent-startup-instructions-template.md +39 -0
- package/.bmad-core/utils/agent-switcher.ide.md +112 -0
- package/.bmad-core/utils/template-format.md +26 -0
- package/.bmad-core/utils/workflow-management.md +224 -0
- package/.bmad-core/web-bundles/agents/analyst.txt +1684 -0
- package/.bmad-core/web-bundles/agents/architect.txt +3584 -0
- package/.bmad-core/web-bundles/agents/bmad-master.txt +9491 -0
- package/.bmad-core/web-bundles/agents/bmad-orchestrator.txt +1466 -0
- package/{dist → .bmad-core/web-bundles}/agents/dev.txt +71 -179
- package/{dist → .bmad-core/web-bundles}/agents/pm.txt +1058 -624
- package/{dist → .bmad-core/web-bundles}/agents/po.txt +138 -337
- package/.bmad-core/web-bundles/agents/qa.txt +129 -0
- package/.bmad-core/web-bundles/agents/sm.txt +658 -0
- package/.bmad-core/web-bundles/agents/ux-expert.txt +1099 -0
- package/.bmad-core/web-bundles/teams/team-all.txt +10757 -0
- package/.bmad-core/web-bundles/teams/team-fullstack.txt +10109 -0
- package/.bmad-core/web-bundles/teams/team-no-ui.txt +8950 -0
- package/.bmad-core/workflows/brownfield-fullstack.yml +116 -0
- package/.bmad-core/workflows/brownfield-service.yml +117 -0
- package/.bmad-core/workflows/brownfield-ui.yml +127 -0
- package/.bmad-core/workflows/greenfield-fullstack.yml +177 -0
- package/.bmad-core/workflows/greenfield-service.yml +143 -0
- package/.bmad-core/workflows/greenfield-ui.yml +172 -0
- package/.claude/commands/analyst.md +63 -0
- package/.claude/commands/architect.md +70 -0
- package/.claude/commands/bmad-master.md +108 -0
- package/.claude/commands/bmad-orchestrator.md +85 -0
- package/.claude/commands/dev.md +74 -0
- package/.claude/commands/pm.md +63 -0
- package/.claude/commands/po.md +64 -0
- package/.claude/commands/qa.md +56 -0
- package/.claude/commands/sm.md +59 -0
- package/.claude/commands/ux-expert.md +70 -0
- package/.cursor/rules/analyst.mdc +77 -0
- package/.cursor/rules/architect.mdc +84 -0
- package/.cursor/rules/bmad-master.mdc +122 -0
- package/.cursor/rules/bmad-orchestrator.mdc +99 -0
- package/.cursor/rules/dev.mdc +88 -0
- package/.cursor/rules/pm.mdc +77 -0
- package/.cursor/rules/po.mdc +78 -0
- package/.cursor/rules/qa.mdc +70 -0
- package/.cursor/rules/sm.mdc +73 -0
- package/.cursor/rules/ux-expert.mdc +84 -0
- package/.roo/.roomodes +95 -0
- package/.roo/README.md +38 -0
- package/.vscode/extensions.json +6 -0
- package/.vscode/settings.json +75 -49
- package/.windsurf/rules/analyst.md +71 -0
- package/.windsurf/rules/architect.md +78 -0
- package/.windsurf/rules/bmad-master.md +116 -0
- package/.windsurf/rules/bmad-orchestrator.md +93 -0
- package/.windsurf/rules/dev.md +82 -0
- package/.windsurf/rules/pm.md +71 -0
- package/.windsurf/rules/po.md +72 -0
- package/.windsurf/rules/qa.md +64 -0
- package/.windsurf/rules/sm.md +67 -0
- package/.windsurf/rules/ux-expert.md +78 -0
- package/CHANGELOG.md +16 -459
- package/CONTRIBUTING.md +5 -168
- package/LICENSE +1 -1
- package/README.md +230 -77
- package/docs/bmad-workflow-guide.md +15 -19
- package/docs/claude-code-guide.md +119 -0
- package/docs/cursor-guide.md +127 -0
- package/docs/roo-code-guide.md +140 -0
- package/docs/sample-output/simple-fullstack-greenfield/prd.md +42 -0
- package/docs/versioning-and-releases.md +16 -8
- package/docs/versions.md +5 -4
- package/docs/windsurf-guide.md +127 -0
- package/expansion-packs/README.md +112 -2
- package/expansion-packs/{bmad-infrastructure-devops → infrastructure-devops}/README.md +9 -9
- package/expansion-packs/{bmad-infrastructure-devops → infrastructure-devops}/agents/infra-devops-platform.md +15 -14
- package/expansion-packs/{bmad-infrastructure-devops → infrastructure-devops}/checklists/infrastructure-checklist.md +1 -1
- package/expansion-packs/infrastructure-devops/manifest.yml +38 -0
- package/expansion-packs/{bmad-infrastructure-devops → infrastructure-devops}/tasks/review-infrastructure.md +4 -4
- package/expansion-packs/{bmad-infrastructure-devops → infrastructure-devops}/tasks/validate-infrastructure.md +4 -4
- package/expansion-packs/infrastructure-devops/templates/infrastructure-architecture-tmpl.md +415 -0
- package/expansion-packs/infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.md +0 -0
- package/package.json +11 -19
- package/tools/bmad-npx-wrapper.js +1 -1
- package/tools/builders/web-builder.js +28 -563
- package/tools/cli.js +22 -55
- package/tools/installer/README.md +53 -3
- package/tools/installer/bin/bmad.js +56 -294
- package/tools/installer/config/install.config.yml +139 -0
- package/tools/installer/lib/config-loader.js +34 -198
- package/tools/installer/lib/file-manager.js +7 -200
- package/tools/installer/lib/ide-setup.js +189 -545
- package/tools/installer/lib/installer.js +61 -1171
- package/tools/installer/package-lock.json +3 -3
- package/tools/installer/package.json +4 -4
- package/tools/installer/templates/claude-commands.md +7 -0
- package/tools/installer/templates/cursor-rules.md +22 -0
- package/tools/installer/templates/windsurf-rules.md +22 -0
- package/tools/lib/dependency-resolver.js +22 -22
- package/tools/upgraders/v3-to-v4-upgrader.js +43 -35
- package/tools/version-bump.js +1 -1
- package/tools/yaml-format.js +2 -2
- package/.github/FUNDING.yaml +0 -15
- package/.github/ISSUE_TEMPLATE/bug_report.md +0 -32
- package/.github/ISSUE_TEMPLATE/feature_request.md +0 -22
- package/.prettierignore +0 -21
- package/.prettierrc +0 -23
- package/bmad-core/agent-teams/team-all.yaml +0 -14
- package/bmad-core/agent-teams/team-fullstack.yaml +0 -18
- package/bmad-core/agent-teams/team-ide-minimal.yaml +0 -10
- package/bmad-core/agent-teams/team-no-ui.yaml +0 -13
- package/bmad-core/agents/architect.md +0 -62
- package/bmad-core/agents/bmad-master.md +0 -88
- package/bmad-core/agents/bmad-orchestrator.md +0 -135
- package/bmad-core/agents/dev.md +0 -56
- package/bmad-core/agents/qa.md +0 -54
- package/bmad-core/agents/sm.md +0 -45
- package/bmad-core/agents/ux-expert.md +0 -53
- package/bmad-core/core-config.yaml +0 -25
- package/bmad-core/data/bmad-kb.md +0 -803
- package/bmad-core/data/brainstorming-techniques.md +0 -36
- package/bmad-core/data/elicitation-methods.md +0 -134
- package/bmad-core/tasks/advanced-elicitation.md +0 -117
- package/bmad-core/tasks/create-brownfield-story.md +0 -355
- package/bmad-core/tasks/create-next-story.md +0 -113
- package/bmad-core/tasks/create-workflow-plan.md +0 -289
- package/bmad-core/tasks/document-project.md +0 -317
- package/bmad-core/tasks/facilitate-brainstorming-session.md +0 -136
- package/bmad-core/tasks/generate-ai-frontend-prompt.md +0 -51
- package/bmad-core/tasks/kb-mode-interaction.md +0 -70
- package/bmad-core/tasks/review-story.md +0 -145
- package/bmad-core/tasks/update-workflow-plan.md +0 -248
- package/bmad-core/tasks/validate-next-story.md +0 -134
- package/bmad-core/templates/architecture-tmpl.yaml +0 -650
- package/bmad-core/templates/brainstorming-output-tmpl.yaml +0 -156
- package/bmad-core/templates/brownfield-architecture-tmpl.yaml +0 -476
- package/bmad-core/templates/brownfield-prd-tmpl.yaml +0 -280
- package/bmad-core/templates/competitor-analysis-tmpl.yaml +0 -293
- package/bmad-core/templates/front-end-architecture-tmpl.yaml +0 -206
- package/bmad-core/templates/front-end-spec-tmpl.yaml +0 -349
- package/bmad-core/templates/fullstack-architecture-tmpl.yaml +0 -805
- package/bmad-core/templates/market-research-tmpl.yaml +0 -252
- package/bmad-core/templates/prd-tmpl.yaml +0 -202
- package/bmad-core/templates/project-brief-tmpl.yaml +0 -221
- package/bmad-core/templates/story-tmpl.yaml +0 -137
- package/bmad-core/workflows/brownfield-fullstack.yaml +0 -297
- package/bmad-core/workflows/brownfield-service.yaml +0 -187
- package/bmad-core/workflows/brownfield-ui.yaml +0 -197
- package/bmad-core/workflows/greenfield-fullstack.yaml +0 -240
- package/bmad-core/workflows/greenfield-service.yaml +0 -206
- package/bmad-core/workflows/greenfield-ui.yaml +0 -235
- package/common/tasks/create-doc.md +0 -79
- package/common/utils/bmad-doc-template.md +0 -325
- package/common/utils/workflow-management.md +0 -69
- package/dist/agents/analyst.txt +0 -2849
- package/dist/agents/architect.txt +0 -3505
- package/dist/agents/bmad-master.txt +0 -9271
- package/dist/agents/bmad-orchestrator.txt +0 -2006
- package/dist/agents/qa.txt +0 -388
- package/dist/agents/sm.txt +0 -672
- package/dist/agents/ux-expert.txt +0 -987
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +0 -2401
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.txt +0 -1635
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.txt +0 -825
- package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +0 -11504
- package/dist/expansion-packs/bmad-creator-tools/agents/bmad-the-creator.txt +0 -2023
- package/dist/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.txt +0 -2052
- package/dist/teams/team-all.txt +0 -11572
- package/dist/teams/team-fullstack.txt +0 -10903
- package/dist/teams/team-ide-minimal.txt +0 -4346
- package/dist/teams/team-no-ui.txt +0 -9458
- package/docs/GUIDING-PRINCIPLES.md +0 -91
- package/docs/agentic-tools/claude-code-guide.md +0 -19
- package/docs/agentic-tools/cline-guide.md +0 -16
- package/docs/agentic-tools/cursor-guide.md +0 -14
- package/docs/agentic-tools/gemini-cli-guide.md +0 -32
- package/docs/agentic-tools/github-copilot-guide.md +0 -42
- package/docs/agentic-tools/roo-code-guide.md +0 -15
- package/docs/agentic-tools/trae-guide.md +0 -14
- package/docs/agentic-tools/windsurf-guide.md +0 -14
- package/docs/core-architecture.md +0 -219
- package/docs/expansion-packs.md +0 -280
- package/docs/how-to-contribute-with-pull-requests.md +0 -158
- package/docs/template-markup-references.md +0 -86
- package/docs/user-guide.md +0 -1142
- package/docs/working-in-the-brownfield.md +0 -361
- package/expansion-packs/bmad-2d-phaser-game-dev/agent-teams/phaser-2d-nodejs-game-team.yaml +0 -13
- package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.md +0 -59
- package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.md +0 -67
- package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.md +0 -52
- package/expansion-packs/bmad-2d-phaser-game-dev/checklists/game-design-checklist.md +0 -201
- package/expansion-packs/bmad-2d-phaser-game-dev/checklists/game-story-dod-checklist.md +0 -160
- package/expansion-packs/bmad-2d-phaser-game-dev/config.yaml +0 -7
- package/expansion-packs/bmad-2d-phaser-game-dev/data/bmad-kb.md +0 -254
- package/expansion-packs/bmad-2d-phaser-game-dev/data/development-guidelines.md +0 -651
- package/expansion-packs/bmad-2d-phaser-game-dev/tasks/advanced-elicitation.md +0 -111
- package/expansion-packs/bmad-2d-phaser-game-dev/tasks/create-game-story.md +0 -216
- package/expansion-packs/bmad-2d-phaser-game-dev/tasks/game-design-brainstorming.md +0 -308
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-architecture-tmpl.yaml +0 -613
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-brief-tmpl.yaml +0 -356
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-design-doc-tmpl.yaml +0 -343
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-story-tmpl.yaml +0 -253
- package/expansion-packs/bmad-2d-phaser-game-dev/templates/level-design-doc-tmpl.yaml +0 -484
- package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-dev-greenfield.yaml +0 -183
- package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-prototype.yaml +0 -175
- package/expansion-packs/bmad-creator-tools/README.md +0 -8
- package/expansion-packs/bmad-creator-tools/agents/bmad-the-creator.md +0 -54
- package/expansion-packs/bmad-creator-tools/config.yaml +0 -5
- package/expansion-packs/bmad-creator-tools/tasks/generate-expansion-pack.md +0 -1020
- package/expansion-packs/bmad-creator-tools/templates/agent-teams-tmpl.yaml +0 -178
- package/expansion-packs/bmad-creator-tools/templates/agent-tmpl.yaml +0 -154
- package/expansion-packs/bmad-creator-tools/templates/expansion-pack-plan-tmpl.yaml +0 -120
- package/expansion-packs/bmad-infrastructure-devops/config.yaml +0 -8
- package/expansion-packs/bmad-infrastructure-devops/data/bmad-kb.md +0 -308
- package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-architecture-tmpl.yaml +0 -424
- package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.yaml +0 -629
- package/tools/bump-all-versions.js +0 -107
- package/tools/bump-core-version.js +0 -57
- package/tools/bump-expansion-version.js +0 -78
- package/tools/installer/config/ide-agent-config.yaml +0 -58
- package/tools/installer/config/install.config.yaml +0 -91
- package/tools/lib/yaml-utils.js +0 -29
- package/tools/md-assets/web-agent-startup-instructions.md +0 -39
- package/tools/update-expansion-version.js +0 -54
- /package/{bmad-core → .bmad-core}/checklists/architect-checklist.md +0 -0
- /package/{bmad-core → .bmad-core}/checklists/pm-checklist.md +0 -0
- /package/{bmad-core → .bmad-core}/checklists/po-master-checklist.md +0 -0
- /package/{bmad-core → .bmad-core}/checklists/story-dod-checklist.md +0 -0
- /package/{bmad-core → .bmad-core}/data/technical-preferences.md +0 -0
- /package/{bmad-core → .bmad-core}/tasks/brownfield-create-epic.md +0 -0
- /package/{bmad-core → .bmad-core}/tasks/brownfield-create-story.md +0 -0
- /package/{bmad-core → .bmad-core}/tasks/correct-course.md +0 -0
- /package/{bmad-core → .bmad-core}/tasks/create-deep-research-prompt.md +0 -0
- /package/.github/workflows/{release.yaml → release.yml} +0 -0
|
@@ -1,47 +1,19 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
|
-
const fs = require("fs-extra");
|
|
3
|
-
const yaml = require("js-yaml");
|
|
4
2
|
const fileManager = require("./file-manager");
|
|
5
3
|
const configLoader = require("./config-loader");
|
|
6
|
-
const { extractYamlFromAgent } = require("../../lib/yaml-utils");
|
|
7
4
|
|
|
8
5
|
// Dynamic import for ES module
|
|
9
6
|
let chalk;
|
|
10
|
-
let inquirer;
|
|
11
7
|
|
|
12
8
|
// Initialize ES modules
|
|
13
9
|
async function initializeModules() {
|
|
14
10
|
if (!chalk) {
|
|
15
11
|
chalk = (await import("chalk")).default;
|
|
16
12
|
}
|
|
17
|
-
if (!inquirer) {
|
|
18
|
-
inquirer = (await import("inquirer")).default;
|
|
19
|
-
}
|
|
20
13
|
}
|
|
21
14
|
|
|
22
15
|
class IdeSetup {
|
|
23
|
-
|
|
24
|
-
this.ideAgentConfig = null;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async loadIdeAgentConfig() {
|
|
28
|
-
if (this.ideAgentConfig) return this.ideAgentConfig;
|
|
29
|
-
|
|
30
|
-
try {
|
|
31
|
-
const configPath = path.join(__dirname, '..', 'config', 'ide-agent-config.yaml');
|
|
32
|
-
const configContent = await fs.readFile(configPath, 'utf8');
|
|
33
|
-
this.ideAgentConfig = yaml.load(configContent);
|
|
34
|
-
return this.ideAgentConfig;
|
|
35
|
-
} catch (error) {
|
|
36
|
-
console.warn('Failed to load IDE agent configuration, using defaults');
|
|
37
|
-
return {
|
|
38
|
-
'roo-permissions': {},
|
|
39
|
-
'cline-order': {}
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
async setup(ide, installDir, selectedAgent = null, spinner = null, preConfiguredSettings = null) {
|
|
16
|
+
async setup(ide, installDir, selectedAgent = null) {
|
|
45
17
|
await initializeModules();
|
|
46
18
|
const ideConfig = await configLoader.getIdeConfiguration(ide);
|
|
47
19
|
|
|
@@ -57,16 +29,8 @@ class IdeSetup {
|
|
|
57
29
|
return this.setupClaudeCode(installDir, selectedAgent);
|
|
58
30
|
case "windsurf":
|
|
59
31
|
return this.setupWindsurf(installDir, selectedAgent);
|
|
60
|
-
case "trae":
|
|
61
|
-
return this.setupTrae(installDir, selectedAgent);
|
|
62
32
|
case "roo":
|
|
63
33
|
return this.setupRoo(installDir, selectedAgent);
|
|
64
|
-
case "cline":
|
|
65
|
-
return this.setupCline(installDir, selectedAgent);
|
|
66
|
-
case "gemini":
|
|
67
|
-
return this.setupGeminiCli(installDir, selectedAgent);
|
|
68
|
-
case "github-copilot":
|
|
69
|
-
return this.setupGitHubCopilot(installDir, selectedAgent, spinner, preConfiguredSettings);
|
|
70
34
|
default:
|
|
71
35
|
console.log(chalk.yellow(`\nIDE ${ide} not yet supported`));
|
|
72
36
|
return false;
|
|
@@ -75,15 +39,25 @@ class IdeSetup {
|
|
|
75
39
|
|
|
76
40
|
async setupCursor(installDir, selectedAgent) {
|
|
77
41
|
const cursorRulesDir = path.join(installDir, ".cursor", "rules");
|
|
78
|
-
const agents = selectedAgent
|
|
42
|
+
const agents = selectedAgent
|
|
43
|
+
? [selectedAgent]
|
|
44
|
+
: await this.getAllAgentIds(installDir);
|
|
79
45
|
|
|
80
46
|
await fileManager.ensureDirectory(cursorRulesDir);
|
|
81
47
|
|
|
82
48
|
for (const agentId of agents) {
|
|
83
|
-
//
|
|
84
|
-
|
|
49
|
+
// Check if .bmad-core is a subdirectory (full install) or if agents are in root (single agent install)
|
|
50
|
+
let agentPath = path.join(
|
|
51
|
+
installDir,
|
|
52
|
+
".bmad-core",
|
|
53
|
+
"agents",
|
|
54
|
+
`${agentId}.md`
|
|
55
|
+
);
|
|
56
|
+
if (!(await fileManager.pathExists(agentPath))) {
|
|
57
|
+
agentPath = path.join(installDir, "agents", `${agentId}.md`);
|
|
58
|
+
}
|
|
85
59
|
|
|
86
|
-
if (agentPath) {
|
|
60
|
+
if (await fileManager.pathExists(agentPath)) {
|
|
87
61
|
const agentContent = await fileManager.readFile(agentPath);
|
|
88
62
|
const mdcPath = path.join(cursorRulesDir, `${agentId}.mdc`);
|
|
89
63
|
|
|
@@ -94,31 +68,28 @@ class IdeSetup {
|
|
|
94
68
|
mdcContent += "alwaysApply: false\n";
|
|
95
69
|
mdcContent += "---\n\n";
|
|
96
70
|
mdcContent += `# ${agentId.toUpperCase()} Agent Rule\n\n`;
|
|
97
|
-
mdcContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${
|
|
98
|
-
agentId
|
|
99
|
-
installDir
|
|
71
|
+
mdcContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${this.getAgentTitle(
|
|
72
|
+
agentId
|
|
100
73
|
)} agent persona.\n\n`;
|
|
101
74
|
mdcContent += "## Agent Activation\n\n";
|
|
102
75
|
mdcContent +=
|
|
103
|
-
"CRITICAL: Read the full
|
|
104
|
-
mdcContent += "```
|
|
76
|
+
"CRITICAL: Read the full YML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n";
|
|
77
|
+
mdcContent += "```yml\n";
|
|
105
78
|
// Extract just the YAML content from the agent file
|
|
106
|
-
const
|
|
107
|
-
if (
|
|
108
|
-
mdcContent +=
|
|
79
|
+
const yamlMatch = agentContent.match(/```ya?ml\n([\s\S]*?)```/);
|
|
80
|
+
if (yamlMatch) {
|
|
81
|
+
mdcContent += yamlMatch[1].trim();
|
|
109
82
|
} else {
|
|
110
83
|
// If no YAML found, include the whole content minus the header
|
|
111
84
|
mdcContent += agentContent.replace(/^#.*$/m, "").trim();
|
|
112
85
|
}
|
|
113
86
|
mdcContent += "\n```\n\n";
|
|
114
87
|
mdcContent += "## File Reference\n\n";
|
|
115
|
-
|
|
116
|
-
mdcContent += `The complete agent definition is available in [${relativePath}](mdc:${relativePath}).\n\n`;
|
|
88
|
+
mdcContent += `The complete agent definition is available in [.bmad-core/agents/${agentId}.md](mdc:.bmad-core/agents/${agentId}.md).\n\n`;
|
|
117
89
|
mdcContent += "## Usage\n\n";
|
|
118
|
-
mdcContent += `When the user types \`@${agentId}\`, activate this ${
|
|
119
|
-
agentId
|
|
120
|
-
|
|
121
|
-
)} persona and follow all instructions defined in the YAML configuration above.\n`;
|
|
90
|
+
mdcContent += `When the user types \`@${agentId}\`, activate this ${this.getAgentTitle(
|
|
91
|
+
agentId
|
|
92
|
+
)} persona and follow all instructions defined in the YML configuration above.\n`;
|
|
122
93
|
|
|
123
94
|
await fileManager.writeFile(mdcPath, mdcContent);
|
|
124
95
|
console.log(chalk.green(`✓ Created rule: ${agentId}.mdc`));
|
|
@@ -132,16 +103,26 @@ class IdeSetup {
|
|
|
132
103
|
|
|
133
104
|
async setupClaudeCode(installDir, selectedAgent) {
|
|
134
105
|
const commandsDir = path.join(installDir, ".claude", "commands");
|
|
135
|
-
const agents = selectedAgent
|
|
106
|
+
const agents = selectedAgent
|
|
107
|
+
? [selectedAgent]
|
|
108
|
+
: await this.getAllAgentIds(installDir);
|
|
136
109
|
|
|
137
110
|
await fileManager.ensureDirectory(commandsDir);
|
|
138
111
|
|
|
139
112
|
for (const agentId of agents) {
|
|
140
|
-
//
|
|
141
|
-
|
|
113
|
+
// Check if .bmad-core is a subdirectory (full install) or if agents are in root (single agent install)
|
|
114
|
+
let agentPath = path.join(
|
|
115
|
+
installDir,
|
|
116
|
+
".bmad-core",
|
|
117
|
+
"agents",
|
|
118
|
+
`${agentId}.md`
|
|
119
|
+
);
|
|
120
|
+
if (!(await fileManager.pathExists(agentPath))) {
|
|
121
|
+
agentPath = path.join(installDir, "agents", `${agentId}.md`);
|
|
122
|
+
}
|
|
142
123
|
const commandPath = path.join(commandsDir, `${agentId}.md`);
|
|
143
124
|
|
|
144
|
-
if (agentPath) {
|
|
125
|
+
if (await fileManager.pathExists(agentPath)) {
|
|
145
126
|
// Create command file with agent content
|
|
146
127
|
const agentContent = await fileManager.readFile(agentPath);
|
|
147
128
|
|
|
@@ -155,206 +136,113 @@ class IdeSetup {
|
|
|
155
136
|
}
|
|
156
137
|
}
|
|
157
138
|
|
|
158
|
-
console.log(
|
|
139
|
+
console.log(
|
|
140
|
+
chalk.green(`\n✓ Created Claude Code commands in ${commandsDir}`)
|
|
141
|
+
);
|
|
159
142
|
|
|
160
143
|
return true;
|
|
161
144
|
}
|
|
162
145
|
|
|
163
146
|
async setupWindsurf(installDir, selectedAgent) {
|
|
164
147
|
const windsurfRulesDir = path.join(installDir, ".windsurf", "rules");
|
|
165
|
-
const agents = selectedAgent
|
|
148
|
+
const agents = selectedAgent
|
|
149
|
+
? [selectedAgent]
|
|
150
|
+
: await this.getAllAgentIds(installDir);
|
|
166
151
|
|
|
167
152
|
await fileManager.ensureDirectory(windsurfRulesDir);
|
|
168
153
|
|
|
169
154
|
for (const agentId of agents) {
|
|
170
|
-
//
|
|
171
|
-
|
|
155
|
+
// Check if .bmad-core is a subdirectory (full install) or if agents are in root (single agent install)
|
|
156
|
+
let agentPath = path.join(
|
|
157
|
+
installDir,
|
|
158
|
+
".bmad-core",
|
|
159
|
+
"agents",
|
|
160
|
+
`${agentId}.md`
|
|
161
|
+
);
|
|
162
|
+
if (!(await fileManager.pathExists(agentPath))) {
|
|
163
|
+
agentPath = path.join(installDir, "agents", `${agentId}.md`);
|
|
164
|
+
}
|
|
172
165
|
|
|
173
|
-
if (agentPath) {
|
|
166
|
+
if (await fileManager.pathExists(agentPath)) {
|
|
174
167
|
const agentContent = await fileManager.readFile(agentPath);
|
|
175
168
|
const mdPath = path.join(windsurfRulesDir, `${agentId}.md`);
|
|
176
169
|
|
|
177
170
|
// Create MD content (similar to Cursor but without frontmatter)
|
|
178
171
|
let mdContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
|
|
179
|
-
mdContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${
|
|
180
|
-
agentId
|
|
181
|
-
installDir
|
|
172
|
+
mdContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${this.getAgentTitle(
|
|
173
|
+
agentId
|
|
182
174
|
)} agent persona.\n\n`;
|
|
183
175
|
mdContent += "## Agent Activation\n\n";
|
|
184
176
|
mdContent +=
|
|
185
|
-
"CRITICAL: Read the full
|
|
186
|
-
mdContent += "```
|
|
177
|
+
"CRITICAL: Read the full YML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n";
|
|
178
|
+
mdContent += "```yml\n";
|
|
187
179
|
// Extract just the YAML content from the agent file
|
|
188
|
-
const
|
|
189
|
-
if (
|
|
190
|
-
mdContent +=
|
|
180
|
+
const yamlMatch = agentContent.match(/```ya?ml\n([\s\S]*?)```/);
|
|
181
|
+
if (yamlMatch) {
|
|
182
|
+
mdContent += yamlMatch[1].trim();
|
|
191
183
|
} else {
|
|
192
184
|
// If no YAML found, include the whole content minus the header
|
|
193
185
|
mdContent += agentContent.replace(/^#.*$/m, "").trim();
|
|
194
186
|
}
|
|
195
187
|
mdContent += "\n```\n\n";
|
|
196
188
|
mdContent += "## File Reference\n\n";
|
|
197
|
-
|
|
198
|
-
mdContent += `The complete agent definition is available in [${relativePath}](${relativePath}).\n\n`;
|
|
189
|
+
mdContent += `The complete agent definition is available in [.bmad-core/agents/${agentId}.md](.bmad-core/agents/${agentId}.md).\n\n`;
|
|
199
190
|
mdContent += "## Usage\n\n";
|
|
200
|
-
mdContent += `When the user types \`@${agentId}\`, activate this ${
|
|
201
|
-
agentId
|
|
202
|
-
|
|
203
|
-
)} persona and follow all instructions defined in the YAML configuration above.\n`;
|
|
191
|
+
mdContent += `When the user types \`@${agentId}\`, activate this ${this.getAgentTitle(
|
|
192
|
+
agentId
|
|
193
|
+
)} persona and follow all instructions defined in the YML configuration above.\n`;
|
|
204
194
|
|
|
205
195
|
await fileManager.writeFile(mdPath, mdContent);
|
|
206
196
|
console.log(chalk.green(`✓ Created rule: ${agentId}.md`));
|
|
207
197
|
}
|
|
208
198
|
}
|
|
209
199
|
|
|
210
|
-
console.log(
|
|
200
|
+
console.log(
|
|
201
|
+
chalk.green(`\n✓ Created Windsurf rules in ${windsurfRulesDir}`)
|
|
202
|
+
);
|
|
211
203
|
|
|
212
204
|
return true;
|
|
213
205
|
}
|
|
214
206
|
|
|
215
|
-
async setupTrae(installDir, selectedAgent) {
|
|
216
|
-
const traeRulesDir = path.join(installDir, ".trae", "rules");
|
|
217
|
-
const agents = selectedAgent? [selectedAgent] : await this.getAllAgentIds(installDir);
|
|
218
|
-
|
|
219
|
-
await fileManager.ensureDirectory(traeRulesDir);
|
|
220
|
-
|
|
221
|
-
for (const agentId of agents) {
|
|
222
|
-
// Find the agent file
|
|
223
|
-
const agentPath = await this.findAgentPath(agentId, installDir);
|
|
224
|
-
|
|
225
|
-
if (agentPath) {
|
|
226
|
-
const agentContent = await fileManager.readFile(agentPath);
|
|
227
|
-
const mdPath = path.join(traeRulesDir, `${agentId}.md`);
|
|
228
|
-
|
|
229
|
-
// Create MD content (similar to Cursor but without frontmatter)
|
|
230
|
-
let mdContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
|
|
231
|
-
mdContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${await this.getAgentTitle(
|
|
232
|
-
agentId,
|
|
233
|
-
installDir
|
|
234
|
-
)} agent persona.\n\n`;
|
|
235
|
-
mdContent += "## Agent Activation\n\n";
|
|
236
|
-
mdContent +=
|
|
237
|
-
"CRITICAL: Read the full YAML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n";
|
|
238
|
-
mdContent += "```yaml\n";
|
|
239
|
-
// Extract just the YAML content from the agent file
|
|
240
|
-
const yamlContent = extractYamlFromAgent(agentContent);
|
|
241
|
-
if (yamlContent) {
|
|
242
|
-
mdContent += yamlContent;
|
|
243
|
-
}
|
|
244
|
-
else {
|
|
245
|
-
// If no YAML found, include the whole content minus the header
|
|
246
|
-
mdContent += agentContent.replace(/^#.*$/m, "").trim();
|
|
247
|
-
}
|
|
248
|
-
mdContent += "\n```\n\n";
|
|
249
|
-
mdContent += "## File Reference\n\n";
|
|
250
|
-
const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
|
|
251
|
-
mdContent += `The complete agent definition is available in [${relativePath}](${relativePath}).\n\n`;
|
|
252
|
-
mdContent += "## Usage\n\n";
|
|
253
|
-
mdContent += `When the user types \`@${agentId}\`, activate this ${await this.getAgentTitle(
|
|
254
|
-
agentId,
|
|
255
|
-
installDir
|
|
256
|
-
)} persona and follow all instructions defined in the YAML configuration above.\n`;
|
|
257
|
-
|
|
258
|
-
await fileManager.writeFile(mdPath, mdContent);
|
|
259
|
-
console.log(chalk.green(`✓ Created rule: ${agentId}.md`));
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
async findAgentPath(agentId, installDir) {
|
|
265
|
-
// Try to find the agent file in various locations
|
|
266
|
-
const possiblePaths = [
|
|
267
|
-
path.join(installDir, ".bmad-core", "agents", `${agentId}.md`),
|
|
268
|
-
path.join(installDir, "agents", `${agentId}.md`)
|
|
269
|
-
];
|
|
270
|
-
|
|
271
|
-
// Also check expansion pack directories
|
|
272
|
-
const glob = require("glob");
|
|
273
|
-
const expansionDirs = glob.sync(".*/agents", { cwd: installDir });
|
|
274
|
-
for (const expDir of expansionDirs) {
|
|
275
|
-
possiblePaths.push(path.join(installDir, expDir, `${agentId}.md`));
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
for (const agentPath of possiblePaths) {
|
|
279
|
-
if (await fileManager.pathExists(agentPath)) {
|
|
280
|
-
return agentPath;
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
return null;
|
|
285
|
-
}
|
|
286
|
-
|
|
287
207
|
async getAllAgentIds(installDir) {
|
|
288
|
-
|
|
289
|
-
const allAgentIds = [];
|
|
290
|
-
|
|
291
|
-
// Check core agents in .bmad-core or root
|
|
208
|
+
// Check if .bmad-core is a subdirectory (full install) or if agents are in root (single agent install)
|
|
292
209
|
let agentsDir = path.join(installDir, ".bmad-core", "agents");
|
|
293
210
|
if (!(await fileManager.pathExists(agentsDir))) {
|
|
294
211
|
agentsDir = path.join(installDir, "agents");
|
|
295
212
|
}
|
|
296
|
-
|
|
297
|
-
if (await fileManager.pathExists(agentsDir)) {
|
|
298
|
-
const agentFiles = glob.sync("*.md", { cwd: agentsDir });
|
|
299
|
-
allAgentIds.push(...agentFiles.map((file) => path.basename(file, ".md")));
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
// Also check for expansion pack agents in dot folders
|
|
303
|
-
const expansionDirs = glob.sync(".*/agents", { cwd: installDir });
|
|
304
|
-
for (const expDir of expansionDirs) {
|
|
305
|
-
const fullExpDir = path.join(installDir, expDir);
|
|
306
|
-
const expAgentFiles = glob.sync("*.md", { cwd: fullExpDir });
|
|
307
|
-
allAgentIds.push(...expAgentFiles.map((file) => path.basename(file, ".md")));
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// Remove duplicates
|
|
311
|
-
return [...new Set(allAgentIds)];
|
|
312
|
-
}
|
|
313
213
|
|
|
314
|
-
async getAgentTitle(agentId, installDir) {
|
|
315
|
-
// Try to find the agent file in various locations
|
|
316
|
-
const possiblePaths = [
|
|
317
|
-
path.join(installDir, ".bmad-core", "agents", `${agentId}.md`),
|
|
318
|
-
path.join(installDir, "agents", `${agentId}.md`)
|
|
319
|
-
];
|
|
320
|
-
|
|
321
|
-
// Also check expansion pack directories
|
|
322
214
|
const glob = require("glob");
|
|
323
|
-
const
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
} catch (error) {
|
|
342
|
-
console.warn(`Failed to read agent title for ${agentId}: ${error.message}`);
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// Fallback to formatted agent ID
|
|
348
|
-
return agentId.split('-').map(word =>
|
|
349
|
-
word.charAt(0).toUpperCase() + word.slice(1)
|
|
350
|
-
).join(' ');
|
|
215
|
+
const agentFiles = glob.sync("*.md", { cwd: agentsDir });
|
|
216
|
+
return agentFiles.map((file) => path.basename(file, ".md"));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
getAgentTitle(agentId) {
|
|
220
|
+
const agentTitles = {
|
|
221
|
+
analyst: "Business Analyst",
|
|
222
|
+
architect: "Solution Architect",
|
|
223
|
+
"bmad-master": "BMAD Master",
|
|
224
|
+
"bmad-orchestrator": "BMAD Orchestrator",
|
|
225
|
+
dev: "Developer",
|
|
226
|
+
pm: "Product Manager",
|
|
227
|
+
po: "Product Owner",
|
|
228
|
+
qa: "QA Specialist",
|
|
229
|
+
sm: "Scrum Master",
|
|
230
|
+
"ux-expert": "UX Expert",
|
|
231
|
+
};
|
|
232
|
+
return agentTitles[agentId] || agentId;
|
|
351
233
|
}
|
|
352
234
|
|
|
353
235
|
async setupRoo(installDir, selectedAgent) {
|
|
354
|
-
const agents = selectedAgent
|
|
236
|
+
const agents = selectedAgent
|
|
237
|
+
? [selectedAgent]
|
|
238
|
+
: await this.getAllAgentIds(installDir);
|
|
355
239
|
|
|
356
|
-
//
|
|
357
|
-
const
|
|
240
|
+
// Create .roo directory first
|
|
241
|
+
const rooDir = path.join(installDir, ".roo");
|
|
242
|
+
await fileManager.ensureDirectory(rooDir);
|
|
243
|
+
|
|
244
|
+
// Check for existing .roomodes file inside .roo directory
|
|
245
|
+
const roomodesPath = path.join(rooDir, ".roomodes");
|
|
358
246
|
let existingModes = [];
|
|
359
247
|
let existingContent = "";
|
|
360
248
|
|
|
@@ -365,27 +253,72 @@ class IdeSetup {
|
|
|
365
253
|
for (const match of modeMatches) {
|
|
366
254
|
existingModes.push(match[1]);
|
|
367
255
|
}
|
|
368
|
-
console.log(
|
|
256
|
+
console.log(
|
|
257
|
+
chalk.yellow(
|
|
258
|
+
`Found existing .roomodes file with ${existingModes.length} modes`
|
|
259
|
+
)
|
|
260
|
+
);
|
|
369
261
|
}
|
|
370
262
|
|
|
371
263
|
// Create new modes content
|
|
372
264
|
let newModesContent = "";
|
|
373
265
|
|
|
374
|
-
//
|
|
375
|
-
const
|
|
376
|
-
|
|
266
|
+
// Define file permissions for each agent type
|
|
267
|
+
const agentPermissions = {
|
|
268
|
+
'analyst': {
|
|
269
|
+
fileRegex: '\\.(md|txt)$',
|
|
270
|
+
description: 'Documentation and text files'
|
|
271
|
+
},
|
|
272
|
+
'pm': {
|
|
273
|
+
fileRegex: '\\.(md|txt)$',
|
|
274
|
+
description: 'Product documentation'
|
|
275
|
+
},
|
|
276
|
+
'architect': {
|
|
277
|
+
fileRegex: '\\.(md|txt|yml|yaml|json)$',
|
|
278
|
+
description: 'Architecture docs and configs'
|
|
279
|
+
},
|
|
280
|
+
'dev': null, // Full edit access
|
|
281
|
+
'qa': {
|
|
282
|
+
fileRegex: '\\.(test|spec)\\.(js|ts|jsx|tsx)$|\\.md$',
|
|
283
|
+
description: 'Test files and documentation'
|
|
284
|
+
},
|
|
285
|
+
'ux-expert': {
|
|
286
|
+
fileRegex: '\\.(md|css|scss|html|jsx|tsx)$',
|
|
287
|
+
description: 'Design-related files'
|
|
288
|
+
},
|
|
289
|
+
'po': {
|
|
290
|
+
fileRegex: '\\.(md|txt)$',
|
|
291
|
+
description: 'Story and requirement docs'
|
|
292
|
+
},
|
|
293
|
+
'sm': {
|
|
294
|
+
fileRegex: '\\.(md|txt)$',
|
|
295
|
+
description: 'Process and planning docs'
|
|
296
|
+
},
|
|
297
|
+
'bmad-orchestrator': null, // Full edit access
|
|
298
|
+
'bmad-master': null // Full edit access
|
|
299
|
+
};
|
|
377
300
|
|
|
378
301
|
for (const agentId of agents) {
|
|
379
302
|
// Skip if already exists
|
|
380
303
|
if (existingModes.includes(`bmad-${agentId}`)) {
|
|
381
|
-
console.log(
|
|
304
|
+
console.log(
|
|
305
|
+
chalk.dim(`Skipping ${agentId} - already exists in .roomodes`)
|
|
306
|
+
);
|
|
382
307
|
continue;
|
|
383
308
|
}
|
|
384
309
|
|
|
385
310
|
// Read agent file to extract all information
|
|
386
|
-
|
|
311
|
+
let agentPath = path.join(
|
|
312
|
+
installDir,
|
|
313
|
+
".bmad-core",
|
|
314
|
+
"agents",
|
|
315
|
+
`${agentId}.md`
|
|
316
|
+
);
|
|
317
|
+
if (!(await fileManager.pathExists(agentPath))) {
|
|
318
|
+
agentPath = path.join(installDir, "agents", `${agentId}.md`);
|
|
319
|
+
}
|
|
387
320
|
|
|
388
|
-
if (agentPath) {
|
|
321
|
+
if (await fileManager.pathExists(agentPath)) {
|
|
389
322
|
const agentContent = await fileManager.readFile(agentPath);
|
|
390
323
|
|
|
391
324
|
// Extract YAML content
|
|
@@ -399,9 +332,11 @@ class IdeSetup {
|
|
|
399
332
|
const whenToUseMatch = yaml.match(/whenToUse:\s*"(.+)"/);
|
|
400
333
|
const roleDefinitionMatch = yaml.match(/roleDefinition:\s*"(.+)"/);
|
|
401
334
|
|
|
402
|
-
const title = titleMatch ? titleMatch[1].trim() :
|
|
335
|
+
const title = titleMatch ? titleMatch[1].trim() : this.getAgentTitle(agentId);
|
|
403
336
|
const icon = iconMatch ? iconMatch[1].trim() : "🤖";
|
|
404
|
-
const whenToUse = whenToUseMatch
|
|
337
|
+
const whenToUse = whenToUseMatch
|
|
338
|
+
? whenToUseMatch[1].trim()
|
|
339
|
+
: `Use for ${title} tasks`;
|
|
405
340
|
const roleDefinition = roleDefinitionMatch
|
|
406
341
|
? roleDefinitionMatch[1].trim()
|
|
407
342
|
: `You are a ${title} specializing in ${title.toLowerCase()} tasks and responsibilities.`;
|
|
@@ -411,12 +346,10 @@ class IdeSetup {
|
|
|
411
346
|
newModesContent += ` name: '${icon} ${title}'\n`;
|
|
412
347
|
newModesContent += ` roleDefinition: ${roleDefinition}\n`;
|
|
413
348
|
newModesContent += ` whenToUse: ${whenToUse}\n`;
|
|
414
|
-
|
|
415
|
-
const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
|
|
416
|
-
newModesContent += ` customInstructions: CRITICAL Read the full YAML from ${relativePath} start activation to alter your state of being follow startup section instructions stay in this being until told to exit this mode\n`;
|
|
349
|
+
newModesContent += ` customInstructions: CRITICAL Read the full YML from .bmad-core/agents/${agentId}.md start activation to alter your state of being follow startup section instructions stay in this being until told to exit this mode\n`;
|
|
417
350
|
newModesContent += ` groups:\n`;
|
|
418
351
|
newModesContent += ` - read\n`;
|
|
419
|
-
|
|
352
|
+
|
|
420
353
|
// Add permissions based on agent type
|
|
421
354
|
const permissions = agentPermissions[agentId];
|
|
422
355
|
if (permissions) {
|
|
@@ -427,7 +360,9 @@ class IdeSetup {
|
|
|
427
360
|
newModesContent += ` - edit\n`;
|
|
428
361
|
}
|
|
429
362
|
|
|
430
|
-
console.log(
|
|
363
|
+
console.log(
|
|
364
|
+
chalk.green(`✓ Added mode: bmad-${agentId} (${icon} ${title})`)
|
|
365
|
+
);
|
|
431
366
|
}
|
|
432
367
|
}
|
|
433
368
|
}
|
|
@@ -444,342 +379,51 @@ class IdeSetup {
|
|
|
444
379
|
|
|
445
380
|
// Write .roomodes file
|
|
446
381
|
await fileManager.writeFile(roomodesPath, roomodesContent);
|
|
447
|
-
console.log(chalk.green("✓ Created .roomodes file
|
|
382
|
+
console.log(chalk.green("✓ Created .roo/.roomodes file"));
|
|
448
383
|
|
|
449
|
-
|
|
450
|
-
|
|
384
|
+
// Create README in .roo directory
|
|
385
|
+
const rooReadme = `# Roo Code Custom Modes for BMAD-METHOD
|
|
451
386
|
|
|
452
|
-
|
|
453
|
-
}
|
|
387
|
+
This directory contains custom mode configurations for Roo Code to enable BMAD agent personalities.
|
|
454
388
|
|
|
455
|
-
|
|
456
|
-
const clineRulesDir = path.join(installDir, ".clinerules");
|
|
457
|
-
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
|
|
389
|
+
## Setup
|
|
458
390
|
|
|
459
|
-
|
|
391
|
+
The \`.roomodes\` file defines all BMAD agents as custom modes using the proper \`customModes:\` structure. Modes are automatically available in Roo Code when you open this project.
|
|
460
392
|
|
|
461
|
-
|
|
462
|
-
const config = await this.loadIdeAgentConfig();
|
|
463
|
-
const agentOrder = config['cline-order'] || {};
|
|
393
|
+
## Available Modes
|
|
464
394
|
|
|
465
|
-
|
|
466
|
-
// Find the agent file
|
|
467
|
-
const agentPath = await this.findAgentPath(agentId, installDir);
|
|
395
|
+
${agents.map((id) => `- **bmad-${id}** - ${this.getAgentTitle(id)}`).join("\n")}
|
|
468
396
|
|
|
469
|
-
|
|
470
|
-
const agentContent = await fileManager.readFile(agentPath);
|
|
397
|
+
## Usage
|
|
471
398
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
399
|
+
In Roo Code:
|
|
400
|
+
1. Open the mode selector (usually in the status bar)
|
|
401
|
+
2. Select any BMAD agent mode
|
|
402
|
+
3. The AI will adopt that agent's personality and expertise
|
|
476
403
|
|
|
477
|
-
|
|
478
|
-
let mdContent = `# ${await this.getAgentTitle(agentId, installDir)} Agent\n\n`;
|
|
479
|
-
mdContent += `This rule defines the ${await this.getAgentTitle(agentId, installDir)} persona and project standards.\n\n`;
|
|
480
|
-
mdContent += "## Role Definition\n\n";
|
|
481
|
-
mdContent +=
|
|
482
|
-
"When the user types `@" + agentId + "`, adopt this persona and follow these guidelines:\n\n";
|
|
483
|
-
mdContent += "```yaml\n";
|
|
484
|
-
// Extract just the YAML content from the agent file
|
|
485
|
-
const yamlContent = extractYamlFromAgent(agentContent);
|
|
486
|
-
if (yamlContent) {
|
|
487
|
-
mdContent += yamlContent;
|
|
488
|
-
} else {
|
|
489
|
-
// If no YAML found, include the whole content minus the header
|
|
490
|
-
mdContent += agentContent.replace(/^#.*$/m, "").trim();
|
|
491
|
-
}
|
|
492
|
-
mdContent += "\n```\n\n";
|
|
493
|
-
mdContent += "## Project Standards\n\n";
|
|
494
|
-
mdContent += `- Always maintain consistency with project documentation in .bmad-core/\n`;
|
|
495
|
-
mdContent += `- Follow the agent's specific guidelines and constraints\n`;
|
|
496
|
-
mdContent += `- Update relevant project files when making changes\n`;
|
|
497
|
-
const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
|
|
498
|
-
mdContent += `- Reference the complete agent definition in [${relativePath}](${relativePath})\n\n`;
|
|
499
|
-
mdContent += "## Usage\n\n";
|
|
500
|
-
mdContent += `Type \`@${agentId}\` to activate this ${await this.getAgentTitle(agentId, installDir)} persona.\n`;
|
|
501
|
-
|
|
502
|
-
await fileManager.writeFile(mdPath, mdContent);
|
|
503
|
-
console.log(chalk.green(`✓ Created rule: ${prefix}-${agentId}.md`));
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
|
|
507
|
-
console.log(chalk.green(`\n✓ Created Cline rules in ${clineRulesDir}`));
|
|
508
|
-
|
|
509
|
-
return true;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
async setupGeminiCli(installDir, selectedAgent) {
|
|
513
|
-
await initializeModules();
|
|
514
|
-
const geminiDir = path.join(installDir, ".gemini");
|
|
515
|
-
const agentsContextDir = path.join(geminiDir, "agents");
|
|
516
|
-
await fileManager.ensureDirectory(agentsContextDir);
|
|
517
|
-
|
|
518
|
-
// Get all available agents
|
|
519
|
-
const agents = await this.getAllAgentIds(installDir);
|
|
520
|
-
const agentContextFiles = [];
|
|
521
|
-
|
|
522
|
-
for (const agentId of agents) {
|
|
523
|
-
// Find the source agent file
|
|
524
|
-
const agentPath = await this.findAgentPath(agentId, installDir);
|
|
525
|
-
|
|
526
|
-
if (agentPath) {
|
|
527
|
-
const agentContent = await fileManager.readFile(agentPath);
|
|
528
|
-
const contextFilePath = path.join(agentsContextDir, `${agentId}.md`);
|
|
529
|
-
|
|
530
|
-
// Copy the agent content directly into its own context file
|
|
531
|
-
await fileManager.writeFile(contextFilePath, agentContent);
|
|
532
|
-
|
|
533
|
-
// Store the relative path for settings.json
|
|
534
|
-
const relativePath = path.relative(geminiDir, contextFilePath);
|
|
535
|
-
agentContextFiles.push(relativePath.replace(/\\/g, '/')); // Ensure forward slashes for consistency
|
|
536
|
-
console.log(chalk.green(`✓ Created context file for @${agentId}`));
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
|
|
540
|
-
console.log(chalk.green(`\n✓ Created individual agent context files in ${agentsContextDir}`));
|
|
541
|
-
|
|
542
|
-
// Add GEMINI.md to the context files array
|
|
543
|
-
agentContextFiles.push("GEMINI.md");
|
|
544
|
-
|
|
545
|
-
// Create or update settings.json
|
|
546
|
-
const settingsPath = path.join(geminiDir, "settings.json");
|
|
547
|
-
let settings = {};
|
|
548
|
-
|
|
549
|
-
if (await fileManager.pathExists(settingsPath)) {
|
|
550
|
-
try {
|
|
551
|
-
const existingSettings = await fileManager.readFile(settingsPath);
|
|
552
|
-
settings = JSON.parse(existingSettings);
|
|
553
|
-
console.log(chalk.yellow("Found existing .gemini/settings.json. Merging settings..."));
|
|
554
|
-
} catch (e) {
|
|
555
|
-
console.error(chalk.red("Error parsing existing settings.json. It will be overwritten."), e);
|
|
556
|
-
settings = {};
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
// Set contextFileName to our new array of files
|
|
561
|
-
settings.contextFileName = agentContextFiles;
|
|
562
|
-
|
|
563
|
-
await fileManager.writeFile(settingsPath, JSON.stringify(settings, null, 2));
|
|
564
|
-
console.log(chalk.green(`✓ Configured .gemini/settings.json to load all agent context files.`));
|
|
565
|
-
|
|
566
|
-
return true;
|
|
567
|
-
}
|
|
568
|
-
|
|
569
|
-
async setupGitHubCopilot(installDir, selectedAgent, spinner = null, preConfiguredSettings = null) {
|
|
570
|
-
await initializeModules();
|
|
571
|
-
|
|
572
|
-
// Configure VS Code workspace settings first to avoid UI conflicts with loading spinners
|
|
573
|
-
await this.configureVsCodeSettings(installDir, spinner, preConfiguredSettings);
|
|
574
|
-
|
|
575
|
-
const chatmodesDir = path.join(installDir, ".github", "chatmodes");
|
|
576
|
-
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
|
|
577
|
-
|
|
578
|
-
await fileManager.ensureDirectory(chatmodesDir);
|
|
579
|
-
|
|
580
|
-
for (const agentId of agents) {
|
|
581
|
-
// Find the agent file
|
|
582
|
-
const agentPath = await this.findAgentPath(agentId, installDir);
|
|
583
|
-
const chatmodePath = path.join(chatmodesDir, `${agentId}.chatmode.md`);
|
|
584
|
-
|
|
585
|
-
if (agentPath) {
|
|
586
|
-
// Create chat mode file with agent content
|
|
587
|
-
const agentContent = await fileManager.readFile(agentPath);
|
|
588
|
-
const agentTitle = await this.getAgentTitle(agentId, installDir);
|
|
589
|
-
|
|
590
|
-
// Extract whenToUse for the description
|
|
591
|
-
const yamlMatch = agentContent.match(/```ya?ml\n([\s\S]*?)```/);
|
|
592
|
-
let description = `Activates the ${agentTitle} agent persona.`;
|
|
593
|
-
if (yamlMatch) {
|
|
594
|
-
const whenToUseMatch = yamlMatch[1].match(/whenToUse:\s*"(.*?)"/);
|
|
595
|
-
if (whenToUseMatch && whenToUseMatch[1]) {
|
|
596
|
-
description = whenToUseMatch[1];
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
let chatmodeContent = `---
|
|
601
|
-
description: "${description.replace(/"/g, '\\"')}"
|
|
602
|
-
tools: ['changes', 'codebase', 'fetch', 'findTestFiles', 'githubRepo', 'problems', 'usages']
|
|
603
|
-
---
|
|
404
|
+
## File Permissions
|
|
604
405
|
|
|
406
|
+
Each agent has specific file access permissions:
|
|
407
|
+
- **Analysts, PM, PO, SM**: Limited to documentation files (.md, .txt)
|
|
408
|
+
- **Architect**: Architecture docs and configs (.md, .txt, .yml, .yaml, .json)
|
|
409
|
+
- **QA**: Test files and documentation
|
|
410
|
+
- **UX Expert**: Design-related files (.md, .css, .scss, .html, .jsx, .tsx)
|
|
411
|
+
- **Developer, Orchestrator, Master**: Full edit access to all files
|
|
605
412
|
`;
|
|
606
|
-
chatmodeContent += agentContent;
|
|
607
413
|
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
}
|
|
414
|
+
const readmePath = path.join(rooDir, "README.md");
|
|
415
|
+
await fileManager.writeFile(readmePath, rooReadme);
|
|
416
|
+
console.log(chalk.green("✓ Created .roo/README.md"));
|
|
612
417
|
|
|
613
|
-
console.log(chalk.green(`\n✓
|
|
614
|
-
console.log(
|
|
418
|
+
console.log(chalk.green(`\n✓ Roo Code setup complete!`));
|
|
419
|
+
console.log(
|
|
420
|
+
chalk.dim(
|
|
421
|
+
"Custom modes will be available when you open this project in Roo Code"
|
|
422
|
+
)
|
|
423
|
+
);
|
|
615
424
|
|
|
616
425
|
return true;
|
|
617
426
|
}
|
|
618
|
-
|
|
619
|
-
async configureVsCodeSettings(installDir, spinner, preConfiguredSettings = null) {
|
|
620
|
-
await initializeModules(); // Ensure inquirer is loaded
|
|
621
|
-
const vscodeDir = path.join(installDir, ".vscode");
|
|
622
|
-
const settingsPath = path.join(vscodeDir, "settings.json");
|
|
623
|
-
|
|
624
|
-
await fileManager.ensureDirectory(vscodeDir);
|
|
625
|
-
|
|
626
|
-
// Read existing settings if they exist
|
|
627
|
-
let existingSettings = {};
|
|
628
|
-
if (await fileManager.pathExists(settingsPath)) {
|
|
629
|
-
try {
|
|
630
|
-
const existingContent = await fileManager.readFile(settingsPath);
|
|
631
|
-
existingSettings = JSON.parse(existingContent);
|
|
632
|
-
console.log(chalk.yellow("Found existing .vscode/settings.json. Merging BMad settings..."));
|
|
633
|
-
} catch (error) {
|
|
634
|
-
console.warn(chalk.yellow("Could not parse existing settings.json. Creating new one."));
|
|
635
|
-
existingSettings = {};
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
// Use pre-configured settings if provided, otherwise prompt
|
|
640
|
-
let configChoice;
|
|
641
|
-
if (preConfiguredSettings && preConfiguredSettings.configChoice) {
|
|
642
|
-
configChoice = preConfiguredSettings.configChoice;
|
|
643
|
-
console.log(chalk.dim(`Using pre-configured GitHub Copilot settings: ${configChoice}`));
|
|
644
|
-
} else {
|
|
645
|
-
// Clear any previous output and add spacing to avoid conflicts with loaders
|
|
646
|
-
console.log('\n'.repeat(2));
|
|
647
|
-
console.log(chalk.blue("🔧 Github Copilot Agent Settings Configuration"));
|
|
648
|
-
console.log(chalk.dim("BMad works best with specific VS Code settings for optimal agent experience."));
|
|
649
|
-
console.log(''); // Add extra spacing
|
|
650
|
-
|
|
651
|
-
const response = await inquirer.prompt([
|
|
652
|
-
{
|
|
653
|
-
type: 'list',
|
|
654
|
-
name: 'configChoice',
|
|
655
|
-
message: chalk.yellow('How would you like to configure GitHub Copilot settings?'),
|
|
656
|
-
choices: [
|
|
657
|
-
{
|
|
658
|
-
name: 'Use recommended defaults (fastest setup)',
|
|
659
|
-
value: 'defaults'
|
|
660
|
-
},
|
|
661
|
-
{
|
|
662
|
-
name: 'Configure each setting manually (customize to your preferences)',
|
|
663
|
-
value: 'manual'
|
|
664
|
-
},
|
|
665
|
-
{
|
|
666
|
-
name: 'Skip settings configuration (I\'ll configure manually later)',
|
|
667
|
-
value: 'skip'
|
|
668
|
-
}
|
|
669
|
-
],
|
|
670
|
-
default: 'defaults'
|
|
671
|
-
}
|
|
672
|
-
]);
|
|
673
|
-
configChoice = response.configChoice;
|
|
674
|
-
}
|
|
675
|
-
|
|
676
|
-
let bmadSettings = {};
|
|
677
|
-
|
|
678
|
-
if (configChoice === 'skip') {
|
|
679
|
-
console.log(chalk.yellow("⚠️ Skipping VS Code settings configuration."));
|
|
680
|
-
console.log(chalk.dim("You can manually configure these settings in .vscode/settings.json:"));
|
|
681
|
-
console.log(chalk.dim(" • chat.agent.enabled: true"));
|
|
682
|
-
console.log(chalk.dim(" • chat.agent.maxRequests: 15"));
|
|
683
|
-
console.log(chalk.dim(" • github.copilot.chat.agent.runTasks: true"));
|
|
684
|
-
console.log(chalk.dim(" • chat.mcp.discovery.enabled: true"));
|
|
685
|
-
console.log(chalk.dim(" • github.copilot.chat.agent.autoFix: true"));
|
|
686
|
-
console.log(chalk.dim(" • chat.tools.autoApprove: false"));
|
|
687
|
-
return true;
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
if (configChoice === 'defaults') {
|
|
691
|
-
// Use recommended defaults
|
|
692
|
-
bmadSettings = {
|
|
693
|
-
"chat.agent.enabled": true,
|
|
694
|
-
"chat.agent.maxRequests": 15,
|
|
695
|
-
"github.copilot.chat.agent.runTasks": true,
|
|
696
|
-
"chat.mcp.discovery.enabled": true,
|
|
697
|
-
"github.copilot.chat.agent.autoFix": true,
|
|
698
|
-
"chat.tools.autoApprove": false
|
|
699
|
-
};
|
|
700
|
-
console.log(chalk.green("✓ Using recommended BMad defaults for Github Copilot settings"));
|
|
701
|
-
} else {
|
|
702
|
-
// Manual configuration
|
|
703
|
-
console.log(chalk.blue("\n📋 Let's configure each setting for your preferences:"));
|
|
704
|
-
|
|
705
|
-
// Pause spinner during manual configuration prompts
|
|
706
|
-
let spinnerWasActive = false;
|
|
707
|
-
if (spinner && spinner.isSpinning) {
|
|
708
|
-
spinner.stop();
|
|
709
|
-
spinnerWasActive = true;
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
const manualSettings = await inquirer.prompt([
|
|
713
|
-
{
|
|
714
|
-
type: 'input',
|
|
715
|
-
name: 'maxRequests',
|
|
716
|
-
message: 'Maximum requests per agent session (recommended: 15)?',
|
|
717
|
-
default: '15',
|
|
718
|
-
validate: (input) => {
|
|
719
|
-
const num = parseInt(input);
|
|
720
|
-
if (isNaN(num) || num < 1 || num > 50) {
|
|
721
|
-
return 'Please enter a number between 1 and 50';
|
|
722
|
-
}
|
|
723
|
-
return true;
|
|
724
|
-
}
|
|
725
|
-
},
|
|
726
|
-
{
|
|
727
|
-
type: 'confirm',
|
|
728
|
-
name: 'runTasks',
|
|
729
|
-
message: 'Allow agents to run workspace tasks (package.json scripts, etc.)?',
|
|
730
|
-
default: true
|
|
731
|
-
},
|
|
732
|
-
{
|
|
733
|
-
type: 'confirm',
|
|
734
|
-
name: 'mcpDiscovery',
|
|
735
|
-
message: 'Enable MCP (Model Context Protocol) server discovery?',
|
|
736
|
-
default: true
|
|
737
|
-
},
|
|
738
|
-
{
|
|
739
|
-
type: 'confirm',
|
|
740
|
-
name: 'autoFix',
|
|
741
|
-
message: 'Enable automatic error detection and fixing in generated code?',
|
|
742
|
-
default: true
|
|
743
|
-
},
|
|
744
|
-
{
|
|
745
|
-
type: 'confirm',
|
|
746
|
-
name: 'autoApprove',
|
|
747
|
-
message: 'Auto-approve ALL tools without confirmation? (⚠️ EXPERIMENTAL - less secure)',
|
|
748
|
-
default: false
|
|
749
|
-
}
|
|
750
|
-
]);
|
|
751
|
-
|
|
752
|
-
// Restart spinner if it was active before prompts
|
|
753
|
-
if (spinner && spinnerWasActive) {
|
|
754
|
-
spinner.start();
|
|
755
|
-
}
|
|
756
|
-
|
|
757
|
-
bmadSettings = {
|
|
758
|
-
"chat.agent.enabled": true, // Always enabled - required for BMad agents
|
|
759
|
-
"chat.agent.maxRequests": parseInt(manualSettings.maxRequests),
|
|
760
|
-
"github.copilot.chat.agent.runTasks": manualSettings.runTasks,
|
|
761
|
-
"chat.mcp.discovery.enabled": manualSettings.mcpDiscovery,
|
|
762
|
-
"github.copilot.chat.agent.autoFix": manualSettings.autoFix,
|
|
763
|
-
"chat.tools.autoApprove": manualSettings.autoApprove
|
|
764
|
-
};
|
|
765
|
-
|
|
766
|
-
console.log(chalk.green("✓ Custom settings configured"));
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
// Merge settings (existing settings take precedence to avoid overriding user preferences)
|
|
770
|
-
const mergedSettings = { ...bmadSettings, ...existingSettings };
|
|
771
|
-
|
|
772
|
-
// Write the updated settings
|
|
773
|
-
await fileManager.writeFile(settingsPath, JSON.stringify(mergedSettings, null, 2));
|
|
774
|
-
|
|
775
|
-
console.log(chalk.green("✓ VS Code workspace settings configured successfully"));
|
|
776
|
-
console.log(chalk.dim(" Settings written to .vscode/settings.json:"));
|
|
777
|
-
Object.entries(bmadSettings).forEach(([key, value]) => {
|
|
778
|
-
console.log(chalk.dim(` • ${key}: ${value}`));
|
|
779
|
-
});
|
|
780
|
-
console.log(chalk.dim(""));
|
|
781
|
-
console.log(chalk.dim("You can modify these settings anytime in .vscode/settings.json"));
|
|
782
|
-
}
|
|
783
427
|
}
|
|
784
428
|
|
|
785
429
|
module.exports = new IdeSetup();
|