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.
Files changed (274) hide show
  1. package/.bmad-core/agent-teams/team-all.yml +16 -0
  2. package/.bmad-core/agent-teams/team-fullstack.yml +26 -0
  3. package/.bmad-core/agent-teams/team-no-ui.yml +15 -0
  4. package/{bmad-core → .bmad-core}/agents/analyst.md +23 -29
  5. package/.bmad-core/agents/architect.md +66 -0
  6. package/.bmad-core/agents/bmad-master.md +104 -0
  7. package/.bmad-core/agents/bmad-orchestrator.md +81 -0
  8. package/.bmad-core/agents/dev.md +70 -0
  9. package/{bmad-core → .bmad-core}/agents/pm.md +24 -24
  10. package/{bmad-core → .bmad-core}/agents/po.md +24 -27
  11. package/.bmad-core/agents/qa.md +52 -0
  12. package/.bmad-core/agents/sm.md +55 -0
  13. package/.bmad-core/agents/ux-expert.md +66 -0
  14. package/{bmad-core → .bmad-core}/checklists/change-checklist.md +2 -2
  15. package/{bmad-core → .bmad-core}/checklists/story-draft-checklist.md +1 -1
  16. package/.bmad-core/data/bmad-kb.md +47 -0
  17. package/.bmad-core/schemas/agent-team-schema.yml +153 -0
  18. package/.bmad-core/tasks/advanced-elicitation.md +92 -0
  19. package/.bmad-core/tasks/brainstorming-techniques.md +238 -0
  20. package/.bmad-core/tasks/core-dump.md +74 -0
  21. package/{expansion-packs/bmad-creator-tools → .bmad-core}/tasks/create-agent.md +11 -9
  22. package/.bmad-core/tasks/create-doc.md +74 -0
  23. package/.bmad-core/tasks/create-expansion-pack.md +425 -0
  24. package/.bmad-core/tasks/create-next-story.md +206 -0
  25. package/.bmad-core/tasks/create-team.md +229 -0
  26. package/{bmad-core → .bmad-core}/tasks/doc-migration-task.md +9 -9
  27. package/{common → .bmad-core}/tasks/execute-checklist.md +6 -2
  28. package/.bmad-core/tasks/generate-ai-frontend-prompt.md +58 -0
  29. package/{bmad-core → .bmad-core}/tasks/index-docs.md +7 -3
  30. package/{bmad-core → .bmad-core}/tasks/shard-doc.md +7 -25
  31. package/.bmad-core/templates/agent-tmpl.md +58 -0
  32. package/.bmad-core/templates/architecture-tmpl.md +771 -0
  33. package/.bmad-core/templates/brownfield-architecture-tmpl.md +542 -0
  34. package/.bmad-core/templates/brownfield-prd-tmpl.md +240 -0
  35. package/.bmad-core/templates/competitor-analysis-tmpl.md +289 -0
  36. package/.bmad-core/templates/expansion-pack-plan-tmpl.md +91 -0
  37. package/.bmad-core/templates/front-end-architecture-tmpl.md +173 -0
  38. package/.bmad-core/templates/front-end-spec-tmpl.md +411 -0
  39. package/.bmad-core/templates/fullstack-architecture-tmpl.md +1016 -0
  40. package/.bmad-core/templates/market-research-tmpl.md +261 -0
  41. package/.bmad-core/templates/prd-tmpl.md +200 -0
  42. package/.bmad-core/templates/project-brief-tmpl.md +228 -0
  43. package/.bmad-core/templates/simple-project-prd-tmpl.md +461 -0
  44. package/.bmad-core/templates/story-tmpl.md +61 -0
  45. package/.bmad-core/templates/web-agent-startup-instructions-template.md +39 -0
  46. package/.bmad-core/utils/agent-switcher.ide.md +112 -0
  47. package/.bmad-core/utils/template-format.md +26 -0
  48. package/.bmad-core/utils/workflow-management.md +224 -0
  49. package/.bmad-core/web-bundles/agents/analyst.txt +1684 -0
  50. package/.bmad-core/web-bundles/agents/architect.txt +3584 -0
  51. package/.bmad-core/web-bundles/agents/bmad-master.txt +9491 -0
  52. package/.bmad-core/web-bundles/agents/bmad-orchestrator.txt +1466 -0
  53. package/{dist → .bmad-core/web-bundles}/agents/dev.txt +71 -179
  54. package/{dist → .bmad-core/web-bundles}/agents/pm.txt +1058 -624
  55. package/{dist → .bmad-core/web-bundles}/agents/po.txt +138 -337
  56. package/.bmad-core/web-bundles/agents/qa.txt +129 -0
  57. package/.bmad-core/web-bundles/agents/sm.txt +658 -0
  58. package/.bmad-core/web-bundles/agents/ux-expert.txt +1099 -0
  59. package/.bmad-core/web-bundles/teams/team-all.txt +10757 -0
  60. package/.bmad-core/web-bundles/teams/team-fullstack.txt +10109 -0
  61. package/.bmad-core/web-bundles/teams/team-no-ui.txt +8950 -0
  62. package/.bmad-core/workflows/brownfield-fullstack.yml +116 -0
  63. package/.bmad-core/workflows/brownfield-service.yml +117 -0
  64. package/.bmad-core/workflows/brownfield-ui.yml +127 -0
  65. package/.bmad-core/workflows/greenfield-fullstack.yml +177 -0
  66. package/.bmad-core/workflows/greenfield-service.yml +143 -0
  67. package/.bmad-core/workflows/greenfield-ui.yml +172 -0
  68. package/.claude/commands/analyst.md +63 -0
  69. package/.claude/commands/architect.md +70 -0
  70. package/.claude/commands/bmad-master.md +108 -0
  71. package/.claude/commands/bmad-orchestrator.md +85 -0
  72. package/.claude/commands/dev.md +74 -0
  73. package/.claude/commands/pm.md +63 -0
  74. package/.claude/commands/po.md +64 -0
  75. package/.claude/commands/qa.md +56 -0
  76. package/.claude/commands/sm.md +59 -0
  77. package/.claude/commands/ux-expert.md +70 -0
  78. package/.cursor/rules/analyst.mdc +77 -0
  79. package/.cursor/rules/architect.mdc +84 -0
  80. package/.cursor/rules/bmad-master.mdc +122 -0
  81. package/.cursor/rules/bmad-orchestrator.mdc +99 -0
  82. package/.cursor/rules/dev.mdc +88 -0
  83. package/.cursor/rules/pm.mdc +77 -0
  84. package/.cursor/rules/po.mdc +78 -0
  85. package/.cursor/rules/qa.mdc +70 -0
  86. package/.cursor/rules/sm.mdc +73 -0
  87. package/.cursor/rules/ux-expert.mdc +84 -0
  88. package/.roo/.roomodes +95 -0
  89. package/.roo/README.md +38 -0
  90. package/.vscode/extensions.json +6 -0
  91. package/.vscode/settings.json +75 -49
  92. package/.windsurf/rules/analyst.md +71 -0
  93. package/.windsurf/rules/architect.md +78 -0
  94. package/.windsurf/rules/bmad-master.md +116 -0
  95. package/.windsurf/rules/bmad-orchestrator.md +93 -0
  96. package/.windsurf/rules/dev.md +82 -0
  97. package/.windsurf/rules/pm.md +71 -0
  98. package/.windsurf/rules/po.md +72 -0
  99. package/.windsurf/rules/qa.md +64 -0
  100. package/.windsurf/rules/sm.md +67 -0
  101. package/.windsurf/rules/ux-expert.md +78 -0
  102. package/CHANGELOG.md +16 -459
  103. package/CONTRIBUTING.md +5 -168
  104. package/LICENSE +1 -1
  105. package/README.md +230 -77
  106. package/docs/bmad-workflow-guide.md +15 -19
  107. package/docs/claude-code-guide.md +119 -0
  108. package/docs/cursor-guide.md +127 -0
  109. package/docs/roo-code-guide.md +140 -0
  110. package/docs/sample-output/simple-fullstack-greenfield/prd.md +42 -0
  111. package/docs/versioning-and-releases.md +16 -8
  112. package/docs/versions.md +5 -4
  113. package/docs/windsurf-guide.md +127 -0
  114. package/expansion-packs/README.md +112 -2
  115. package/expansion-packs/{bmad-infrastructure-devops → infrastructure-devops}/README.md +9 -9
  116. package/expansion-packs/{bmad-infrastructure-devops → infrastructure-devops}/agents/infra-devops-platform.md +15 -14
  117. package/expansion-packs/{bmad-infrastructure-devops → infrastructure-devops}/checklists/infrastructure-checklist.md +1 -1
  118. package/expansion-packs/infrastructure-devops/manifest.yml +38 -0
  119. package/expansion-packs/{bmad-infrastructure-devops → infrastructure-devops}/tasks/review-infrastructure.md +4 -4
  120. package/expansion-packs/{bmad-infrastructure-devops → infrastructure-devops}/tasks/validate-infrastructure.md +4 -4
  121. package/expansion-packs/infrastructure-devops/templates/infrastructure-architecture-tmpl.md +415 -0
  122. package/expansion-packs/infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.md +0 -0
  123. package/package.json +11 -19
  124. package/tools/bmad-npx-wrapper.js +1 -1
  125. package/tools/builders/web-builder.js +28 -563
  126. package/tools/cli.js +22 -55
  127. package/tools/installer/README.md +53 -3
  128. package/tools/installer/bin/bmad.js +56 -294
  129. package/tools/installer/config/install.config.yml +139 -0
  130. package/tools/installer/lib/config-loader.js +34 -198
  131. package/tools/installer/lib/file-manager.js +7 -200
  132. package/tools/installer/lib/ide-setup.js +189 -545
  133. package/tools/installer/lib/installer.js +61 -1171
  134. package/tools/installer/package-lock.json +3 -3
  135. package/tools/installer/package.json +4 -4
  136. package/tools/installer/templates/claude-commands.md +7 -0
  137. package/tools/installer/templates/cursor-rules.md +22 -0
  138. package/tools/installer/templates/windsurf-rules.md +22 -0
  139. package/tools/lib/dependency-resolver.js +22 -22
  140. package/tools/upgraders/v3-to-v4-upgrader.js +43 -35
  141. package/tools/version-bump.js +1 -1
  142. package/tools/yaml-format.js +2 -2
  143. package/.github/FUNDING.yaml +0 -15
  144. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -32
  145. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -22
  146. package/.prettierignore +0 -21
  147. package/.prettierrc +0 -23
  148. package/bmad-core/agent-teams/team-all.yaml +0 -14
  149. package/bmad-core/agent-teams/team-fullstack.yaml +0 -18
  150. package/bmad-core/agent-teams/team-ide-minimal.yaml +0 -10
  151. package/bmad-core/agent-teams/team-no-ui.yaml +0 -13
  152. package/bmad-core/agents/architect.md +0 -62
  153. package/bmad-core/agents/bmad-master.md +0 -88
  154. package/bmad-core/agents/bmad-orchestrator.md +0 -135
  155. package/bmad-core/agents/dev.md +0 -56
  156. package/bmad-core/agents/qa.md +0 -54
  157. package/bmad-core/agents/sm.md +0 -45
  158. package/bmad-core/agents/ux-expert.md +0 -53
  159. package/bmad-core/core-config.yaml +0 -25
  160. package/bmad-core/data/bmad-kb.md +0 -803
  161. package/bmad-core/data/brainstorming-techniques.md +0 -36
  162. package/bmad-core/data/elicitation-methods.md +0 -134
  163. package/bmad-core/tasks/advanced-elicitation.md +0 -117
  164. package/bmad-core/tasks/create-brownfield-story.md +0 -355
  165. package/bmad-core/tasks/create-next-story.md +0 -113
  166. package/bmad-core/tasks/create-workflow-plan.md +0 -289
  167. package/bmad-core/tasks/document-project.md +0 -317
  168. package/bmad-core/tasks/facilitate-brainstorming-session.md +0 -136
  169. package/bmad-core/tasks/generate-ai-frontend-prompt.md +0 -51
  170. package/bmad-core/tasks/kb-mode-interaction.md +0 -70
  171. package/bmad-core/tasks/review-story.md +0 -145
  172. package/bmad-core/tasks/update-workflow-plan.md +0 -248
  173. package/bmad-core/tasks/validate-next-story.md +0 -134
  174. package/bmad-core/templates/architecture-tmpl.yaml +0 -650
  175. package/bmad-core/templates/brainstorming-output-tmpl.yaml +0 -156
  176. package/bmad-core/templates/brownfield-architecture-tmpl.yaml +0 -476
  177. package/bmad-core/templates/brownfield-prd-tmpl.yaml +0 -280
  178. package/bmad-core/templates/competitor-analysis-tmpl.yaml +0 -293
  179. package/bmad-core/templates/front-end-architecture-tmpl.yaml +0 -206
  180. package/bmad-core/templates/front-end-spec-tmpl.yaml +0 -349
  181. package/bmad-core/templates/fullstack-architecture-tmpl.yaml +0 -805
  182. package/bmad-core/templates/market-research-tmpl.yaml +0 -252
  183. package/bmad-core/templates/prd-tmpl.yaml +0 -202
  184. package/bmad-core/templates/project-brief-tmpl.yaml +0 -221
  185. package/bmad-core/templates/story-tmpl.yaml +0 -137
  186. package/bmad-core/workflows/brownfield-fullstack.yaml +0 -297
  187. package/bmad-core/workflows/brownfield-service.yaml +0 -187
  188. package/bmad-core/workflows/brownfield-ui.yaml +0 -197
  189. package/bmad-core/workflows/greenfield-fullstack.yaml +0 -240
  190. package/bmad-core/workflows/greenfield-service.yaml +0 -206
  191. package/bmad-core/workflows/greenfield-ui.yaml +0 -235
  192. package/common/tasks/create-doc.md +0 -79
  193. package/common/utils/bmad-doc-template.md +0 -325
  194. package/common/utils/workflow-management.md +0 -69
  195. package/dist/agents/analyst.txt +0 -2849
  196. package/dist/agents/architect.txt +0 -3505
  197. package/dist/agents/bmad-master.txt +0 -9271
  198. package/dist/agents/bmad-orchestrator.txt +0 -2006
  199. package/dist/agents/qa.txt +0 -388
  200. package/dist/agents/sm.txt +0 -672
  201. package/dist/agents/ux-expert.txt +0 -987
  202. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +0 -2401
  203. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.txt +0 -1635
  204. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.txt +0 -825
  205. package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +0 -11504
  206. package/dist/expansion-packs/bmad-creator-tools/agents/bmad-the-creator.txt +0 -2023
  207. package/dist/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.txt +0 -2052
  208. package/dist/teams/team-all.txt +0 -11572
  209. package/dist/teams/team-fullstack.txt +0 -10903
  210. package/dist/teams/team-ide-minimal.txt +0 -4346
  211. package/dist/teams/team-no-ui.txt +0 -9458
  212. package/docs/GUIDING-PRINCIPLES.md +0 -91
  213. package/docs/agentic-tools/claude-code-guide.md +0 -19
  214. package/docs/agentic-tools/cline-guide.md +0 -16
  215. package/docs/agentic-tools/cursor-guide.md +0 -14
  216. package/docs/agentic-tools/gemini-cli-guide.md +0 -32
  217. package/docs/agentic-tools/github-copilot-guide.md +0 -42
  218. package/docs/agentic-tools/roo-code-guide.md +0 -15
  219. package/docs/agentic-tools/trae-guide.md +0 -14
  220. package/docs/agentic-tools/windsurf-guide.md +0 -14
  221. package/docs/core-architecture.md +0 -219
  222. package/docs/expansion-packs.md +0 -280
  223. package/docs/how-to-contribute-with-pull-requests.md +0 -158
  224. package/docs/template-markup-references.md +0 -86
  225. package/docs/user-guide.md +0 -1142
  226. package/docs/working-in-the-brownfield.md +0 -361
  227. package/expansion-packs/bmad-2d-phaser-game-dev/agent-teams/phaser-2d-nodejs-game-team.yaml +0 -13
  228. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.md +0 -59
  229. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.md +0 -67
  230. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.md +0 -52
  231. package/expansion-packs/bmad-2d-phaser-game-dev/checklists/game-design-checklist.md +0 -201
  232. package/expansion-packs/bmad-2d-phaser-game-dev/checklists/game-story-dod-checklist.md +0 -160
  233. package/expansion-packs/bmad-2d-phaser-game-dev/config.yaml +0 -7
  234. package/expansion-packs/bmad-2d-phaser-game-dev/data/bmad-kb.md +0 -254
  235. package/expansion-packs/bmad-2d-phaser-game-dev/data/development-guidelines.md +0 -651
  236. package/expansion-packs/bmad-2d-phaser-game-dev/tasks/advanced-elicitation.md +0 -111
  237. package/expansion-packs/bmad-2d-phaser-game-dev/tasks/create-game-story.md +0 -216
  238. package/expansion-packs/bmad-2d-phaser-game-dev/tasks/game-design-brainstorming.md +0 -308
  239. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-architecture-tmpl.yaml +0 -613
  240. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-brief-tmpl.yaml +0 -356
  241. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-design-doc-tmpl.yaml +0 -343
  242. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-story-tmpl.yaml +0 -253
  243. package/expansion-packs/bmad-2d-phaser-game-dev/templates/level-design-doc-tmpl.yaml +0 -484
  244. package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-dev-greenfield.yaml +0 -183
  245. package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-prototype.yaml +0 -175
  246. package/expansion-packs/bmad-creator-tools/README.md +0 -8
  247. package/expansion-packs/bmad-creator-tools/agents/bmad-the-creator.md +0 -54
  248. package/expansion-packs/bmad-creator-tools/config.yaml +0 -5
  249. package/expansion-packs/bmad-creator-tools/tasks/generate-expansion-pack.md +0 -1020
  250. package/expansion-packs/bmad-creator-tools/templates/agent-teams-tmpl.yaml +0 -178
  251. package/expansion-packs/bmad-creator-tools/templates/agent-tmpl.yaml +0 -154
  252. package/expansion-packs/bmad-creator-tools/templates/expansion-pack-plan-tmpl.yaml +0 -120
  253. package/expansion-packs/bmad-infrastructure-devops/config.yaml +0 -8
  254. package/expansion-packs/bmad-infrastructure-devops/data/bmad-kb.md +0 -308
  255. package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-architecture-tmpl.yaml +0 -424
  256. package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.yaml +0 -629
  257. package/tools/bump-all-versions.js +0 -107
  258. package/tools/bump-core-version.js +0 -57
  259. package/tools/bump-expansion-version.js +0 -78
  260. package/tools/installer/config/ide-agent-config.yaml +0 -58
  261. package/tools/installer/config/install.config.yaml +0 -91
  262. package/tools/lib/yaml-utils.js +0 -29
  263. package/tools/md-assets/web-agent-startup-instructions.md +0 -39
  264. package/tools/update-expansion-version.js +0 -54
  265. /package/{bmad-core → .bmad-core}/checklists/architect-checklist.md +0 -0
  266. /package/{bmad-core → .bmad-core}/checklists/pm-checklist.md +0 -0
  267. /package/{bmad-core → .bmad-core}/checklists/po-master-checklist.md +0 -0
  268. /package/{bmad-core → .bmad-core}/checklists/story-dod-checklist.md +0 -0
  269. /package/{bmad-core → .bmad-core}/data/technical-preferences.md +0 -0
  270. /package/{bmad-core → .bmad-core}/tasks/brownfield-create-epic.md +0 -0
  271. /package/{bmad-core → .bmad-core}/tasks/brownfield-create-story.md +0 -0
  272. /package/{bmad-core → .bmad-core}/tasks/correct-course.md +0 -0
  273. /package/{bmad-core → .bmad-core}/tasks/create-deep-research-prompt.md +0 -0
  274. /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
- constructor() {
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 ? [selectedAgent] : await this.getAllAgentIds(installDir);
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
- // Find the agent file
84
- const agentPath = await this.findAgentPath(agentId, installDir);
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 ${await this.getAgentTitle(
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 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";
104
- mdcContent += "```yaml\n";
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 yamlContent = extractYamlFromAgent(agentContent);
107
- if (yamlContent) {
108
- mdcContent += yamlContent;
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
- const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
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 ${await this.getAgentTitle(
119
- agentId,
120
- installDir
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 ? [selectedAgent] : await this.getAllAgentIds(installDir);
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
- // Find the agent file
141
- const agentPath = await this.findAgentPath(agentId, installDir);
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(chalk.green(`\n✓ Created Claude Code commands in ${commandsDir}`));
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 ? [selectedAgent] : await this.getAllAgentIds(installDir);
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
- // Find the agent file
171
- const agentPath = await this.findAgentPath(agentId, installDir);
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 ${await this.getAgentTitle(
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 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";
186
- mdContent += "```yaml\n";
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 yamlContent = extractYamlFromAgent(agentContent);
189
- if (yamlContent) {
190
- mdContent += yamlContent;
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
- const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
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 ${await this.getAgentTitle(
201
- agentId,
202
- installDir
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(chalk.green(`\n✓ Created Windsurf rules in ${windsurfRulesDir}`));
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
- const glob = require("glob");
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 expansionDirs = glob.sync(".*/agents", { cwd: installDir });
324
- for (const expDir of expansionDirs) {
325
- possiblePaths.push(path.join(installDir, expDir, `${agentId}.md`));
326
- }
327
-
328
- for (const agentPath of possiblePaths) {
329
- if (await fileManager.pathExists(agentPath)) {
330
- try {
331
- const agentContent = await fileManager.readFile(agentPath);
332
- const yamlMatch = agentContent.match(/```ya?ml\n([\s\S]*?)```/);
333
-
334
- if (yamlMatch) {
335
- const yaml = yamlMatch[1];
336
- const titleMatch = yaml.match(/title:\s*(.+)/);
337
- if (titleMatch) {
338
- return titleMatch[1].trim();
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 ? [selectedAgent] : await this.getAllAgentIds(installDir);
236
+ const agents = selectedAgent
237
+ ? [selectedAgent]
238
+ : await this.getAllAgentIds(installDir);
355
239
 
356
- // Check for existing .roomodes file in project root
357
- const roomodesPath = path.join(installDir, ".roomodes");
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(chalk.yellow(`Found existing .roomodes file with ${existingModes.length} modes`));
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
- // Load dynamic agent permissions from configuration
375
- const config = await this.loadIdeAgentConfig();
376
- const agentPermissions = config['roo-permissions'] || {};
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(chalk.dim(`Skipping ${agentId} - already exists in .roomodes`));
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
- const agentPath = await this.findAgentPath(agentId, installDir);
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() : await this.getAgentTitle(agentId, installDir);
335
+ const title = titleMatch ? titleMatch[1].trim() : this.getAgentTitle(agentId);
403
336
  const icon = iconMatch ? iconMatch[1].trim() : "🤖";
404
- const whenToUse = whenToUseMatch ? whenToUseMatch[1].trim() : `Use for ${title} tasks`;
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
- // Get relative path from installDir to agent file
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(chalk.green(`✓ Added mode: bmad-${agentId} (${icon} ${title})`));
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 in project root"));
382
+ console.log(chalk.green("✓ Created .roo/.roomodes file"));
448
383
 
449
- console.log(chalk.green(`\n✓ Roo Code setup complete!`));
450
- console.log(chalk.dim("Custom modes will be available when you open this project in Roo Code"));
384
+ // Create README in .roo directory
385
+ const rooReadme = `# Roo Code Custom Modes for BMAD-METHOD
451
386
 
452
- return true;
453
- }
387
+ This directory contains custom mode configurations for Roo Code to enable BMAD agent personalities.
454
388
 
455
- async setupCline(installDir, selectedAgent) {
456
- const clineRulesDir = path.join(installDir, ".clinerules");
457
- const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
389
+ ## Setup
458
390
 
459
- await fileManager.ensureDirectory(clineRulesDir);
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
- // Load dynamic agent ordering from configuration
462
- const config = await this.loadIdeAgentConfig();
463
- const agentOrder = config['cline-order'] || {};
393
+ ## Available Modes
464
394
 
465
- for (const agentId of agents) {
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
- if (agentPath) {
470
- const agentContent = await fileManager.readFile(agentPath);
397
+ ## Usage
471
398
 
472
- // Get numeric prefix for ordering
473
- const order = agentOrder[agentId] || 99;
474
- const prefix = order.toString().padStart(2, '0');
475
- const mdPath = path.join(clineRulesDir, `${prefix}-${agentId}.md`);
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
- // Create MD content for Cline (focused on project standards and role)
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
- await fileManager.writeFile(chatmodePath, chatmodeContent);
609
- console.log(chalk.green(`✓ Created chat mode: ${agentId}.chatmode.md`));
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✓ Github Copilot setup complete!`));
614
- console.log(chalk.dim(`You can now find the BMad agents in the Chat view's mode selector.`));
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();