bmad-method 4.37.0 → 4.39.1

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 (251) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +3 -3
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +3 -3
  3. package/.github/workflows/discord.yaml +11 -2
  4. package/.github/workflows/format-check.yaml +42 -0
  5. package/.github/workflows/manual-release.yaml +173 -0
  6. package/.husky/pre-commit +3 -0
  7. package/.vscode/settings.json +26 -1
  8. package/CHANGELOG.md +2 -23
  9. package/README.md +2 -0
  10. package/bmad-core/agent-teams/team-all.yaml +1 -1
  11. package/bmad-core/agents/analyst.md +16 -15
  12. package/bmad-core/agents/architect.md +11 -11
  13. package/bmad-core/agents/bmad-master.md +23 -22
  14. package/bmad-core/agents/bmad-orchestrator.md +13 -17
  15. package/bmad-core/agents/dev.md +14 -11
  16. package/bmad-core/agents/pm.md +15 -14
  17. package/bmad-core/agents/po.md +9 -8
  18. package/bmad-core/agents/qa.md +42 -22
  19. package/bmad-core/agents/sm.md +7 -6
  20. package/bmad-core/agents/ux-expert.md +6 -5
  21. package/bmad-core/core-config.yaml +2 -0
  22. package/bmad-core/data/bmad-kb.md +1 -1
  23. package/bmad-core/data/test-levels-framework.md +146 -0
  24. package/bmad-core/data/test-priorities-matrix.md +172 -0
  25. package/bmad-core/tasks/apply-qa-fixes.md +148 -0
  26. package/bmad-core/tasks/facilitate-brainstorming-session.md +1 -1
  27. package/bmad-core/tasks/nfr-assess.md +343 -0
  28. package/bmad-core/tasks/qa-gate.md +161 -0
  29. package/bmad-core/tasks/review-story.md +234 -74
  30. package/bmad-core/tasks/risk-profile.md +353 -0
  31. package/bmad-core/tasks/test-design.md +174 -0
  32. package/bmad-core/tasks/trace-requirements.md +264 -0
  33. package/bmad-core/templates/architecture-tmpl.yaml +49 -49
  34. package/bmad-core/templates/brainstorming-output-tmpl.yaml +5 -5
  35. package/bmad-core/templates/brownfield-architecture-tmpl.yaml +31 -31
  36. package/bmad-core/templates/brownfield-prd-tmpl.yaml +13 -13
  37. package/bmad-core/templates/competitor-analysis-tmpl.yaml +19 -6
  38. package/bmad-core/templates/front-end-architecture-tmpl.yaml +21 -9
  39. package/bmad-core/templates/front-end-spec-tmpl.yaml +24 -24
  40. package/bmad-core/templates/fullstack-architecture-tmpl.yaml +122 -104
  41. package/bmad-core/templates/market-research-tmpl.yaml +2 -2
  42. package/bmad-core/templates/prd-tmpl.yaml +9 -9
  43. package/bmad-core/templates/project-brief-tmpl.yaml +4 -4
  44. package/bmad-core/templates/qa-gate-tmpl.yaml +102 -0
  45. package/bmad-core/templates/story-tmpl.yaml +12 -12
  46. package/bmad-core/workflows/brownfield-fullstack.yaml +9 -9
  47. package/bmad-core/workflows/brownfield-service.yaml +1 -1
  48. package/bmad-core/workflows/brownfield-ui.yaml +1 -1
  49. package/bmad-core/workflows/greenfield-fullstack.yaml +1 -1
  50. package/bmad-core/workflows/greenfield-service.yaml +1 -1
  51. package/bmad-core/workflows/greenfield-ui.yaml +1 -1
  52. package/common/utils/bmad-doc-template.md +5 -5
  53. package/dist/agents/analyst.txt +1086 -1079
  54. package/dist/agents/architect.txt +1534 -1526
  55. package/dist/agents/bmad-master.txt +646 -632
  56. package/dist/agents/bmad-orchestrator.txt +40 -18
  57. package/dist/agents/dev.txt +158 -19
  58. package/dist/agents/pm.txt +1082 -1107
  59. package/dist/agents/po.txt +314 -332
  60. package/dist/agents/qa.txt +1754 -151
  61. package/dist/agents/sm.txt +88 -98
  62. package/dist/agents/ux-expert.txt +80 -87
  63. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-designer.txt +109 -146
  64. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.txt +75 -86
  65. package/dist/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.txt +41 -48
  66. package/dist/expansion-packs/bmad-2d-phaser-game-dev/teams/phaser-2d-nodejs-game-team.txt +1903 -1941
  67. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-architect.txt +15 -50
  68. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-designer.txt +149 -195
  69. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-developer.txt +0 -15
  70. package/dist/expansion-packs/bmad-2d-unity-game-dev/agents/game-sm.txt +20 -37
  71. package/dist/expansion-packs/bmad-2d-unity-game-dev/teams/unity-2d-game-team.txt +2660 -2752
  72. package/dist/expansion-packs/bmad-creative-writing/agents/beta-reader.txt +871 -0
  73. package/dist/expansion-packs/bmad-creative-writing/agents/book-critic.txt +78 -0
  74. package/dist/expansion-packs/bmad-creative-writing/agents/character-psychologist.txt +839 -0
  75. package/dist/expansion-packs/bmad-creative-writing/agents/cover-designer.txt +85 -0
  76. package/dist/expansion-packs/bmad-creative-writing/agents/dialog-specialist.txt +861 -0
  77. package/dist/expansion-packs/bmad-creative-writing/agents/editor.txt +796 -0
  78. package/dist/expansion-packs/bmad-creative-writing/agents/genre-specialist.txt +927 -0
  79. package/dist/expansion-packs/bmad-creative-writing/agents/narrative-designer.txt +842 -0
  80. package/dist/expansion-packs/bmad-creative-writing/agents/plot-architect.txt +1126 -0
  81. package/dist/expansion-packs/bmad-creative-writing/agents/world-builder.txt +864 -0
  82. package/dist/expansion-packs/bmad-creative-writing/teams/agent-team.txt +5917 -0
  83. package/dist/expansion-packs/bmad-infrastructure-devops/agents/infra-devops-platform.txt +25 -27
  84. package/dist/teams/team-all.txt +5541 -3768
  85. package/dist/teams/team-fullstack.txt +3014 -2987
  86. package/dist/teams/team-ide-minimal.txt +2219 -469
  87. package/dist/teams/team-no-ui.txt +2993 -2966
  88. package/docs/enhanced-ide-development-workflow.md +220 -15
  89. package/docs/user-guide.md +271 -18
  90. package/docs/versioning-and-releases.md +122 -44
  91. package/docs/working-in-the-brownfield.md +264 -31
  92. package/eslint.config.mjs +119 -0
  93. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-developer.md +4 -4
  94. package/expansion-packs/bmad-2d-phaser-game-dev/agents/game-sm.md +1 -1
  95. package/expansion-packs/bmad-2d-phaser-game-dev/config.yaml +1 -1
  96. package/expansion-packs/bmad-2d-phaser-game-dev/data/development-guidelines.md +26 -28
  97. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-architecture-tmpl.yaml +50 -50
  98. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-brief-tmpl.yaml +23 -23
  99. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-design-doc-tmpl.yaml +24 -24
  100. package/expansion-packs/bmad-2d-phaser-game-dev/templates/game-story-tmpl.yaml +42 -42
  101. package/expansion-packs/bmad-2d-phaser-game-dev/templates/level-design-doc-tmpl.yaml +65 -65
  102. package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-dev-greenfield.yaml +5 -5
  103. package/expansion-packs/bmad-2d-phaser-game-dev/workflows/game-prototype.yaml +1 -1
  104. package/expansion-packs/bmad-2d-unity-game-dev/agents/game-developer.md +3 -3
  105. package/expansion-packs/bmad-2d-unity-game-dev/config.yaml +1 -1
  106. package/expansion-packs/bmad-2d-unity-game-dev/data/bmad-kb.md +1 -1
  107. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-brief-tmpl.yaml +23 -23
  108. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-design-doc-tmpl.yaml +63 -63
  109. package/expansion-packs/bmad-2d-unity-game-dev/templates/game-story-tmpl.yaml +20 -20
  110. package/expansion-packs/bmad-2d-unity-game-dev/templates/level-design-doc-tmpl.yaml +65 -65
  111. package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-dev-greenfield.yaml +5 -5
  112. package/expansion-packs/bmad-2d-unity-game-dev/workflows/game-prototype.yaml +1 -1
  113. package/expansion-packs/bmad-creative-writing/README.md +132 -0
  114. package/expansion-packs/bmad-creative-writing/agent-teams/agent-team.yaml +19 -0
  115. package/expansion-packs/bmad-creative-writing/agents/beta-reader.md +91 -0
  116. package/expansion-packs/bmad-creative-writing/agents/book-critic.md +35 -0
  117. package/expansion-packs/bmad-creative-writing/agents/character-psychologist.md +90 -0
  118. package/expansion-packs/bmad-creative-writing/agents/cover-designer.md +41 -0
  119. package/expansion-packs/bmad-creative-writing/agents/dialog-specialist.md +89 -0
  120. package/expansion-packs/bmad-creative-writing/agents/editor.md +90 -0
  121. package/expansion-packs/bmad-creative-writing/agents/genre-specialist.md +92 -0
  122. package/expansion-packs/bmad-creative-writing/agents/narrative-designer.md +90 -0
  123. package/expansion-packs/bmad-creative-writing/agents/plot-architect.md +92 -0
  124. package/expansion-packs/bmad-creative-writing/agents/world-builder.md +91 -0
  125. package/expansion-packs/bmad-creative-writing/checklists/beta-feedback-closure-checklist.md +16 -0
  126. package/expansion-packs/bmad-creative-writing/checklists/character-consistency-checklist.md +16 -0
  127. package/expansion-packs/bmad-creative-writing/checklists/comedic-timing-checklist.md +16 -0
  128. package/expansion-packs/bmad-creative-writing/checklists/cyberpunk-aesthetic-checklist.md +16 -0
  129. package/expansion-packs/bmad-creative-writing/checklists/ebook-formatting-checklist.md +15 -0
  130. package/expansion-packs/bmad-creative-writing/checklists/epic-poetry-meter-checklist.md +16 -0
  131. package/expansion-packs/bmad-creative-writing/checklists/fantasy-magic-system-checklist.md +16 -0
  132. package/expansion-packs/bmad-creative-writing/checklists/foreshadowing-payoff-checklist.md +15 -0
  133. package/expansion-packs/bmad-creative-writing/checklists/genre-tropes-checklist.md +15 -0
  134. package/expansion-packs/bmad-creative-writing/checklists/historical-accuracy-checklist.md +16 -0
  135. package/expansion-packs/bmad-creative-writing/checklists/horror-suspense-checklist.md +16 -0
  136. package/expansion-packs/bmad-creative-writing/checklists/kdp-cover-ready-checklist.md +18 -0
  137. package/expansion-packs/bmad-creative-writing/checklists/line-edit-quality-checklist.md +16 -0
  138. package/expansion-packs/bmad-creative-writing/checklists/marketing-copy-checklist.md +16 -0
  139. package/expansion-packs/bmad-creative-writing/checklists/mystery-clue-trail-checklist.md +16 -0
  140. package/expansion-packs/bmad-creative-writing/checklists/orbital-mechanics-checklist.md +16 -0
  141. package/expansion-packs/bmad-creative-writing/checklists/plot-structure-checklist.md +49 -0
  142. package/expansion-packs/bmad-creative-writing/checklists/publication-readiness-checklist.md +16 -0
  143. package/expansion-packs/bmad-creative-writing/checklists/romance-emotional-beats-checklist.md +16 -0
  144. package/expansion-packs/bmad-creative-writing/checklists/scene-quality-checklist.md +16 -0
  145. package/expansion-packs/bmad-creative-writing/checklists/scifi-technology-plausibility-checklist.md +15 -0
  146. package/expansion-packs/bmad-creative-writing/checklists/sensitivity-representation-checklist.md +16 -0
  147. package/expansion-packs/bmad-creative-writing/checklists/steampunk-gadget-checklist.md +16 -0
  148. package/expansion-packs/bmad-creative-writing/checklists/thriller-pacing-stakes-checklist.md +16 -0
  149. package/expansion-packs/bmad-creative-writing/checklists/timeline-continuity-checklist.md +16 -0
  150. package/expansion-packs/bmad-creative-writing/checklists/world-building-continuity-checklist.md +16 -0
  151. package/expansion-packs/bmad-creative-writing/checklists/ya-appropriateness-checklist.md +16 -0
  152. package/expansion-packs/bmad-creative-writing/config.yaml +11 -0
  153. package/expansion-packs/bmad-creative-writing/data/bmad-kb.md +197 -0
  154. package/expansion-packs/bmad-creative-writing/data/story-structures.md +58 -0
  155. package/expansion-packs/bmad-creative-writing/docs/brief.md +183 -0
  156. package/expansion-packs/bmad-creative-writing/tasks/advanced-elicitation.md +117 -0
  157. package/expansion-packs/bmad-creative-writing/tasks/analyze-reader-feedback.md +16 -0
  158. package/expansion-packs/bmad-creative-writing/tasks/analyze-story-structure.md +55 -0
  159. package/expansion-packs/bmad-creative-writing/tasks/assemble-kdp-package.md +22 -0
  160. package/expansion-packs/bmad-creative-writing/tasks/brainstorm-premise.md +16 -0
  161. package/expansion-packs/bmad-creative-writing/tasks/build-world.md +17 -0
  162. package/expansion-packs/bmad-creative-writing/tasks/character-depth-pass.md +15 -0
  163. package/expansion-packs/bmad-creative-writing/tasks/create-doc.md +101 -0
  164. package/expansion-packs/bmad-creative-writing/tasks/create-draft-section.md +19 -0
  165. package/expansion-packs/bmad-creative-writing/tasks/critical-review.md +19 -0
  166. package/expansion-packs/bmad-creative-writing/tasks/develop-character.md +17 -0
  167. package/expansion-packs/bmad-creative-writing/tasks/execute-checklist.md +93 -0
  168. package/expansion-packs/bmad-creative-writing/tasks/expand-premise.md +16 -0
  169. package/expansion-packs/bmad-creative-writing/tasks/expand-synopsis.md +16 -0
  170. package/expansion-packs/bmad-creative-writing/tasks/final-polish.md +16 -0
  171. package/expansion-packs/bmad-creative-writing/tasks/generate-cover-brief.md +18 -0
  172. package/expansion-packs/bmad-creative-writing/tasks/generate-cover-prompts.md +19 -0
  173. package/expansion-packs/bmad-creative-writing/tasks/generate-scene-list.md +16 -0
  174. package/expansion-packs/bmad-creative-writing/tasks/incorporate-feedback.md +18 -0
  175. package/expansion-packs/bmad-creative-writing/tasks/outline-scenes.md +16 -0
  176. package/expansion-packs/bmad-creative-writing/tasks/provide-feedback.md +17 -0
  177. package/expansion-packs/bmad-creative-writing/tasks/publish-chapter.md +16 -0
  178. package/expansion-packs/bmad-creative-writing/tasks/quick-feedback.md +15 -0
  179. package/expansion-packs/bmad-creative-writing/tasks/select-next-arc.md +16 -0
  180. package/expansion-packs/bmad-creative-writing/tasks/workshop-dialog.md +51 -0
  181. package/expansion-packs/bmad-creative-writing/templates/beta-feedback-form.yaml +96 -0
  182. package/expansion-packs/bmad-creative-writing/templates/chapter-draft-tmpl.yaml +81 -0
  183. package/expansion-packs/bmad-creative-writing/templates/character-profile-tmpl.yaml +92 -0
  184. package/expansion-packs/bmad-creative-writing/templates/cover-design-brief-tmpl.yaml +97 -0
  185. package/expansion-packs/bmad-creative-writing/templates/premise-brief-tmpl.yaml +77 -0
  186. package/expansion-packs/bmad-creative-writing/templates/scene-list-tmpl.yaml +54 -0
  187. package/expansion-packs/bmad-creative-writing/templates/story-outline-tmpl.yaml +96 -0
  188. package/expansion-packs/bmad-creative-writing/templates/world-guide-tmpl.yaml +88 -0
  189. package/expansion-packs/bmad-creative-writing/workflows/book-cover-design-workflow.md +176 -0
  190. package/expansion-packs/bmad-creative-writing/workflows/novel-greenfield-workflow.yaml +58 -0
  191. package/expansion-packs/bmad-creative-writing/workflows/novel-serial-workflow.yaml +51 -0
  192. package/expansion-packs/bmad-creative-writing/workflows/novel-snowflake-workflow.yaml +69 -0
  193. package/expansion-packs/bmad-creative-writing/workflows/novel-writing.yaml +92 -0
  194. package/expansion-packs/bmad-creative-writing/workflows/screenplay-development.yaml +86 -0
  195. package/expansion-packs/bmad-creative-writing/workflows/series-planning.yaml +79 -0
  196. package/expansion-packs/bmad-creative-writing/workflows/short-story-creation.yaml +65 -0
  197. package/expansion-packs/bmad-infrastructure-devops/config.yaml +1 -1
  198. package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-architecture-tmpl.yaml +20 -20
  199. package/expansion-packs/bmad-infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.yaml +7 -7
  200. package/package.json +62 -39
  201. package/prettier.config.mjs +32 -0
  202. package/sync-version.sh +23 -0
  203. package/tools/bmad-npx-wrapper.js +10 -10
  204. package/tools/builders/web-builder.js +124 -130
  205. package/tools/bump-all-versions.js +42 -33
  206. package/tools/bump-expansion-version.js +23 -16
  207. package/tools/cli.js +10 -12
  208. package/tools/flattener/aggregate.js +10 -10
  209. package/tools/flattener/binary.js +44 -17
  210. package/tools/flattener/discovery.js +19 -18
  211. package/tools/flattener/files.js +6 -6
  212. package/tools/flattener/ignoreRules.js +125 -125
  213. package/tools/flattener/main.js +426 -70
  214. package/tools/flattener/projectRoot.js +186 -25
  215. package/tools/flattener/prompts.js +9 -9
  216. package/tools/flattener/stats.helpers.js +395 -0
  217. package/tools/flattener/stats.js +64 -14
  218. package/tools/flattener/test-matrix.js +413 -0
  219. package/tools/flattener/xml.js +33 -31
  220. package/tools/installer/bin/bmad.js +156 -113
  221. package/tools/installer/config/ide-agent-config.yaml +1 -1
  222. package/tools/installer/config/install.config.yaml +13 -3
  223. package/tools/installer/lib/config-loader.js +46 -42
  224. package/tools/installer/lib/file-manager.js +91 -113
  225. package/tools/installer/lib/ide-base-setup.js +57 -56
  226. package/tools/installer/lib/ide-setup.js +545 -399
  227. package/tools/installer/lib/installer.js +875 -714
  228. package/tools/installer/lib/memory-profiler.js +54 -53
  229. package/tools/installer/lib/module-manager.js +19 -15
  230. package/tools/installer/lib/resource-locator.js +26 -28
  231. package/tools/installer/package.json +19 -19
  232. package/tools/lib/dependency-resolver.js +26 -30
  233. package/tools/lib/yaml-utils.js +7 -7
  234. package/tools/preview-release-notes.js +66 -0
  235. package/tools/shared/bannerArt.js +3 -3
  236. package/tools/sync-installer-version.js +7 -9
  237. package/tools/update-expansion-version.js +14 -15
  238. package/tools/upgraders/v3-to-v4-upgrader.js +203 -294
  239. package/tools/version-bump.js +41 -26
  240. package/tools/yaml-format.js +56 -43
  241. package/.github/workflows/release.yaml +0 -60
  242. package/.releaserc.json +0 -21
  243. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/Complete AI Agent System - Flowchart.svg +0 -102
  244. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.1 Google Cloud Project Setup/1.1.1 - Initial Project Configuration - bash copy.txt +0 -13
  245. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.1 Google Cloud Project Setup/1.1.1 - Initial Project Configuration - bash.txt +0 -13
  246. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.2 Agent Development Kit Installation/1.2.2 - Basic Project Structure - txt.txt +0 -25
  247. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.3 Core Configuration Files/1.3.1 - settings.py +0 -34
  248. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.3 Core Configuration Files/1.3.2 - main.py - Base Application.py +0 -70
  249. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/PART 1 - Google Cloud Vertex AI Setup Documentation/1.4 Deployment Configuration/1.4.2 - cloudbuild.yaml +0 -26
  250. package/expansion-packs/Complete AI Agent System - Blank Templates & Google Cloud Setup/README.md +0 -109
  251. package/tools/semantic-release-sync-installer.js +0 -30
@@ -1,13 +1,13 @@
1
- const path = require("path");
2
- const fs = require("fs-extra");
3
- const yaml = require("js-yaml");
4
- const chalk = require("chalk");
5
- const inquirer = require("inquirer");
6
- const fileManager = require("./file-manager");
7
- const configLoader = require("./config-loader");
8
- const { extractYamlFromAgent } = require("../../lib/yaml-utils");
9
- const BaseIdeSetup = require("./ide-base-setup");
10
- const resourceLocator = require("./resource-locator");
1
+ const path = require('node:path');
2
+ const fs = require('fs-extra');
3
+ const yaml = require('js-yaml');
4
+ const chalk = require('chalk');
5
+ const inquirer = require('inquirer');
6
+ const fileManager = require('./file-manager');
7
+ const configLoader = require('./config-loader');
8
+ const { extractYamlFromAgent } = require('../../lib/yaml-utils');
9
+ const BaseIdeSetup = require('./ide-base-setup');
10
+ const resourceLocator = require('./resource-locator');
11
11
 
12
12
  class IdeSetup extends BaseIdeSetup {
13
13
  constructor() {
@@ -17,17 +17,17 @@ class IdeSetup extends BaseIdeSetup {
17
17
 
18
18
  async loadIdeAgentConfig() {
19
19
  if (this.ideAgentConfig) return this.ideAgentConfig;
20
-
20
+
21
21
  try {
22
22
  const configPath = path.join(__dirname, '..', 'config', 'ide-agent-config.yaml');
23
23
  const configContent = await fs.readFile(configPath, 'utf8');
24
24
  this.ideAgentConfig = yaml.load(configContent);
25
25
  return this.ideAgentConfig;
26
- } catch (error) {
26
+ } catch {
27
27
  console.warn('Failed to load IDE agent configuration, using defaults');
28
28
  return {
29
29
  'roo-permissions': {},
30
- 'cline-order': {}
30
+ 'cline-order': {},
31
31
  };
32
32
  }
33
33
  }
@@ -41,34 +41,48 @@ class IdeSetup extends BaseIdeSetup {
41
41
  }
42
42
 
43
43
  switch (ide) {
44
- case "cursor":
44
+ case 'cursor': {
45
45
  return this.setupCursor(installDir, selectedAgent);
46
- case "claude-code":
46
+ }
47
+ case 'claude-code': {
47
48
  return this.setupClaudeCode(installDir, selectedAgent);
48
- case "windsurf":
49
+ }
50
+ case 'crush': {
51
+ return this.setupCrush(installDir, selectedAgent);
52
+ }
53
+ case 'windsurf': {
49
54
  return this.setupWindsurf(installDir, selectedAgent);
50
- case "trae":
55
+ }
56
+ case 'trae': {
51
57
  return this.setupTrae(installDir, selectedAgent);
52
- case "roo":
58
+ }
59
+ case 'roo': {
53
60
  return this.setupRoo(installDir, selectedAgent);
54
- case "cline":
61
+ }
62
+ case 'cline': {
55
63
  return this.setupCline(installDir, selectedAgent);
56
- case "kilo":
64
+ }
65
+ case 'kilo': {
57
66
  return this.setupKilocode(installDir, selectedAgent);
58
- case "gemini":
67
+ }
68
+ case 'gemini': {
59
69
  return this.setupGeminiCli(installDir, selectedAgent);
60
- case "github-copilot":
70
+ }
71
+ case 'github-copilot': {
61
72
  return this.setupGitHubCopilot(installDir, selectedAgent, spinner, preConfiguredSettings);
62
- case "qwen-code":
73
+ }
74
+ case 'qwen-code': {
63
75
  return this.setupQwenCode(installDir, selectedAgent);
64
- default:
76
+ }
77
+ default: {
65
78
  console.log(chalk.yellow(`\nIDE ${ide} not yet supported`));
66
79
  return false;
80
+ }
67
81
  }
68
82
  }
69
83
 
70
84
  async setupCursor(installDir, selectedAgent) {
71
- const cursorRulesDir = path.join(installDir, ".cursor", "rules", "bmad");
85
+ const cursorRulesDir = path.join(installDir, '.cursor', 'rules', 'bmad');
72
86
  const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
73
87
 
74
88
  await fileManager.ensureDirectory(cursorRulesDir);
@@ -88,12 +102,57 @@ class IdeSetup extends BaseIdeSetup {
88
102
  return true;
89
103
  }
90
104
 
105
+ async setupCrush(installDir, selectedAgent) {
106
+ // Setup bmad-core commands
107
+ const coreSlashPrefix = await this.getCoreSlashPrefix(installDir);
108
+ const coreAgents = selectedAgent ? [selectedAgent] : await this.getCoreAgentIds(installDir);
109
+ const coreTasks = await this.getCoreTaskIds(installDir);
110
+ await this.setupCrushForPackage(
111
+ installDir,
112
+ 'core',
113
+ coreSlashPrefix,
114
+ coreAgents,
115
+ coreTasks,
116
+ '.bmad-core',
117
+ );
118
+
119
+ // Setup expansion pack commands
120
+ const expansionPacks = await this.getInstalledExpansionPacks(installDir);
121
+ for (const packInfo of expansionPacks) {
122
+ const packSlashPrefix = await this.getExpansionPackSlashPrefix(packInfo.path);
123
+ const packAgents = await this.getExpansionPackAgents(packInfo.path);
124
+ const packTasks = await this.getExpansionPackTasks(packInfo.path);
125
+
126
+ if (packAgents.length > 0 || packTasks.length > 0) {
127
+ // Use the actual directory name where the expansion pack is installed
128
+ const rootPath = path.relative(installDir, packInfo.path);
129
+ await this.setupCrushForPackage(
130
+ installDir,
131
+ packInfo.name,
132
+ packSlashPrefix,
133
+ packAgents,
134
+ packTasks,
135
+ rootPath,
136
+ );
137
+ }
138
+ }
139
+
140
+ return true;
141
+ }
142
+
91
143
  async setupClaudeCode(installDir, selectedAgent) {
92
144
  // Setup bmad-core commands
93
145
  const coreSlashPrefix = await this.getCoreSlashPrefix(installDir);
94
146
  const coreAgents = selectedAgent ? [selectedAgent] : await this.getCoreAgentIds(installDir);
95
147
  const coreTasks = await this.getCoreTaskIds(installDir);
96
- await this.setupClaudeCodeForPackage(installDir, "core", coreSlashPrefix, coreAgents, coreTasks, ".bmad-core");
148
+ await this.setupClaudeCodeForPackage(
149
+ installDir,
150
+ 'core',
151
+ coreSlashPrefix,
152
+ coreAgents,
153
+ coreTasks,
154
+ '.bmad-core',
155
+ );
97
156
 
98
157
  // Setup expansion pack commands
99
158
  const expansionPacks = await this.getInstalledExpansionPacks(installDir);
@@ -101,21 +160,35 @@ class IdeSetup extends BaseIdeSetup {
101
160
  const packSlashPrefix = await this.getExpansionPackSlashPrefix(packInfo.path);
102
161
  const packAgents = await this.getExpansionPackAgents(packInfo.path);
103
162
  const packTasks = await this.getExpansionPackTasks(packInfo.path);
104
-
163
+
105
164
  if (packAgents.length > 0 || packTasks.length > 0) {
106
165
  // Use the actual directory name where the expansion pack is installed
107
166
  const rootPath = path.relative(installDir, packInfo.path);
108
- await this.setupClaudeCodeForPackage(installDir, packInfo.name, packSlashPrefix, packAgents, packTasks, rootPath);
167
+ await this.setupClaudeCodeForPackage(
168
+ installDir,
169
+ packInfo.name,
170
+ packSlashPrefix,
171
+ packAgents,
172
+ packTasks,
173
+ rootPath,
174
+ );
109
175
  }
110
176
  }
111
177
 
112
178
  return true;
113
179
  }
114
180
 
115
- async setupClaudeCodeForPackage(installDir, packageName, slashPrefix, agentIds, taskIds, rootPath) {
116
- const commandsBaseDir = path.join(installDir, ".claude", "commands", slashPrefix);
117
- const agentsDir = path.join(commandsBaseDir, "agents");
118
- const tasksDir = path.join(commandsBaseDir, "tasks");
181
+ async setupClaudeCodeForPackage(
182
+ installDir,
183
+ packageName,
184
+ slashPrefix,
185
+ agentIds,
186
+ taskIds,
187
+ rootPath,
188
+ ) {
189
+ const commandsBaseDir = path.join(installDir, '.claude', 'commands', slashPrefix);
190
+ const agentsDir = path.join(commandsBaseDir, 'agents');
191
+ const tasksDir = path.join(commandsBaseDir, 'tasks');
119
192
 
120
193
  // Ensure directories exist
121
194
  await fileManager.ensureDirectory(agentsDir);
@@ -125,28 +198,28 @@ class IdeSetup extends BaseIdeSetup {
125
198
  for (const agentId of agentIds) {
126
199
  // Find the agent file - for expansion packs, prefer the expansion pack version
127
200
  let agentPath;
128
- if (packageName !== "core") {
201
+ if (packageName === 'core') {
202
+ // For core, use the normal search
203
+ agentPath = await this.findAgentPath(agentId, installDir);
204
+ } else {
129
205
  // For expansion packs, first try to find the agent in the expansion pack directory
130
- const expansionPackPath = path.join(installDir, rootPath, "agents", `${agentId}.md`);
206
+ const expansionPackPath = path.join(installDir, rootPath, 'agents', `${agentId}.md`);
131
207
  if (await fileManager.pathExists(expansionPackPath)) {
132
208
  agentPath = expansionPackPath;
133
209
  } else {
134
210
  // Fall back to core if not found in expansion pack
135
211
  agentPath = await this.findAgentPath(agentId, installDir);
136
212
  }
137
- } else {
138
- // For core, use the normal search
139
- agentPath = await this.findAgentPath(agentId, installDir);
140
213
  }
141
-
214
+
142
215
  const commandPath = path.join(agentsDir, `${agentId}.md`);
143
216
 
144
217
  if (agentPath) {
145
218
  // Create command file with agent content
146
219
  let agentContent = await fileManager.readFile(agentPath);
147
-
220
+
148
221
  // Replace {root} placeholder with the appropriate root path for this context
149
- agentContent = agentContent.replace(/{root}/g, rootPath);
222
+ agentContent = agentContent.replaceAll('{root}', rootPath);
150
223
 
151
224
  // Add command header
152
225
  let commandContent = `# /${agentId} Command\n\n`;
@@ -162,28 +235,118 @@ class IdeSetup extends BaseIdeSetup {
162
235
  for (const taskId of taskIds) {
163
236
  // Find the task file - for expansion packs, prefer the expansion pack version
164
237
  let taskPath;
165
- if (packageName !== "core") {
238
+ if (packageName === 'core') {
239
+ // For core, use the normal search
240
+ taskPath = await this.findTaskPath(taskId, installDir);
241
+ } else {
166
242
  // For expansion packs, first try to find the task in the expansion pack directory
167
- const expansionPackPath = path.join(installDir, rootPath, "tasks", `${taskId}.md`);
243
+ const expansionPackPath = path.join(installDir, rootPath, 'tasks', `${taskId}.md`);
168
244
  if (await fileManager.pathExists(expansionPackPath)) {
169
245
  taskPath = expansionPackPath;
170
246
  } else {
171
247
  // Fall back to core if not found in expansion pack
172
248
  taskPath = await this.findTaskPath(taskId, installDir);
173
249
  }
250
+ }
251
+
252
+ const commandPath = path.join(tasksDir, `${taskId}.md`);
253
+
254
+ if (taskPath) {
255
+ // Create command file with task content
256
+ let taskContent = await fileManager.readFile(taskPath);
257
+
258
+ // Replace {root} placeholder with the appropriate root path for this context
259
+ taskContent = taskContent.replaceAll('{root}', rootPath);
260
+
261
+ // Add command header
262
+ let commandContent = `# /${taskId} Task\n\n`;
263
+ commandContent += `When this command is used, execute the following task:\n\n`;
264
+ commandContent += taskContent;
265
+
266
+ await fileManager.writeFile(commandPath, commandContent);
267
+ console.log(chalk.green(`✓ Created task command: /${taskId}`));
268
+ }
269
+ }
270
+
271
+ console.log(
272
+ chalk.green(`\n✓ Created Claude Code commands for ${packageName} in ${commandsBaseDir}`),
273
+ );
274
+ console.log(chalk.dim(` - Agents in: ${agentsDir}`));
275
+ console.log(chalk.dim(` - Tasks in: ${tasksDir}`));
276
+ }
277
+
278
+ async setupCrushForPackage(installDir, packageName, slashPrefix, agentIds, taskIds, rootPath) {
279
+ const commandsBaseDir = path.join(installDir, '.crush', 'commands', slashPrefix);
280
+ const agentsDir = path.join(commandsBaseDir, 'agents');
281
+ const tasksDir = path.join(commandsBaseDir, 'tasks');
282
+
283
+ // Ensure directories exist
284
+ await fileManager.ensureDirectory(agentsDir);
285
+ await fileManager.ensureDirectory(tasksDir);
286
+
287
+ // Setup agents
288
+ for (const agentId of agentIds) {
289
+ // Find the agent file - for expansion packs, prefer the expansion pack version
290
+ let agentPath;
291
+ if (packageName === 'core') {
292
+ // For core, use the normal search
293
+ agentPath = await this.findAgentPath(agentId, installDir);
174
294
  } else {
295
+ // For expansion packs, first try to find the agent in the expansion pack directory
296
+ const expansionPackPath = path.join(installDir, rootPath, 'agents', `${agentId}.md`);
297
+ if (await fileManager.pathExists(expansionPackPath)) {
298
+ agentPath = expansionPackPath;
299
+ } else {
300
+ // Fall back to core if not found in expansion pack
301
+ agentPath = await this.findAgentPath(agentId, installDir);
302
+ }
303
+ }
304
+
305
+ const commandPath = path.join(agentsDir, `${agentId}.md`);
306
+
307
+ if (agentPath) {
308
+ // Create command file with agent content
309
+ let agentContent = await fileManager.readFile(agentPath);
310
+
311
+ // Replace {root} placeholder with the appropriate root path for this context
312
+ agentContent = agentContent.replaceAll('{root}', rootPath);
313
+
314
+ // Add command header
315
+ let commandContent = `# /${agentId} Command\n\n`;
316
+ commandContent += `When this command is used, adopt the following agent persona:\n\n`;
317
+ commandContent += agentContent;
318
+
319
+ await fileManager.writeFile(commandPath, commandContent);
320
+ console.log(chalk.green(`✓ Created agent command: /${agentId}`));
321
+ }
322
+ }
323
+
324
+ // Setup tasks
325
+ for (const taskId of taskIds) {
326
+ // Find the task file - for expansion packs, prefer the expansion pack version
327
+ let taskPath;
328
+ if (packageName === 'core') {
175
329
  // For core, use the normal search
176
330
  taskPath = await this.findTaskPath(taskId, installDir);
331
+ } else {
332
+ // For expansion packs, first try to find the task in the expansion pack directory
333
+ const expansionPackPath = path.join(installDir, rootPath, 'tasks', `${taskId}.md`);
334
+ if (await fileManager.pathExists(expansionPackPath)) {
335
+ taskPath = expansionPackPath;
336
+ } else {
337
+ // Fall back to core if not found in expansion pack
338
+ taskPath = await this.findTaskPath(taskId, installDir);
339
+ }
177
340
  }
178
-
341
+
179
342
  const commandPath = path.join(tasksDir, `${taskId}.md`);
180
343
 
181
344
  if (taskPath) {
182
345
  // Create command file with task content
183
346
  let taskContent = await fileManager.readFile(taskPath);
184
-
347
+
185
348
  // Replace {root} placeholder with the appropriate root path for this context
186
- taskContent = taskContent.replace(/{root}/g, rootPath);
349
+ taskContent = taskContent.replaceAll('{root}', rootPath);
187
350
 
188
351
  // Add command header
189
352
  let commandContent = `# /${taskId} Task\n\n`;
@@ -195,16 +358,16 @@ class IdeSetup extends BaseIdeSetup {
195
358
  }
196
359
  }
197
360
 
198
- console.log(chalk.green(`\n✓ Created Claude Code commands for ${packageName} in ${commandsBaseDir}`));
361
+ console.log(chalk.green(`\n✓ Created Crush commands for ${packageName} in ${commandsBaseDir}`));
199
362
  console.log(chalk.dim(` - Agents in: ${agentsDir}`));
200
363
  console.log(chalk.dim(` - Tasks in: ${tasksDir}`));
201
364
  }
202
365
 
203
366
  async setupWindsurf(installDir, selectedAgent) {
204
- const windsurfRulesDir = path.join(installDir, ".windsurf", "rules");
367
+ const windsurfWorkflowDir = path.join(installDir, '.windsurf', 'workflows');
205
368
  const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
206
369
 
207
- await fileManager.ensureDirectory(windsurfRulesDir);
370
+ await fileManager.ensureDirectory(windsurfWorkflowDir);
208
371
 
209
372
  for (const agentId of agents) {
210
373
  // Find the agent file
@@ -212,89 +375,67 @@ class IdeSetup extends BaseIdeSetup {
212
375
 
213
376
  if (agentPath) {
214
377
  const agentContent = await fileManager.readFile(agentPath);
215
- const mdPath = path.join(windsurfRulesDir, `${agentId}.md`);
378
+ const mdPath = path.join(windsurfWorkflowDir, `${agentId}.md`);
216
379
 
217
- // Create MD content (similar to Cursor but without frontmatter)
218
- let mdContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
219
- mdContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${await this.getAgentTitle(
220
- agentId,
221
- installDir
222
- )} agent persona.\n\n`;
223
- mdContent += "## Agent Activation\n\n";
224
- mdContent +=
225
- "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";
226
- mdContent += "```yaml\n";
227
- // Extract just the YAML content from the agent file
228
- const yamlContent = extractYamlFromAgent(agentContent);
229
- if (yamlContent) {
230
- mdContent += yamlContent;
231
- } else {
232
- // If no YAML found, include the whole content minus the header
233
- mdContent += agentContent.replace(/^#.*$/m, "").trim();
234
- }
235
- mdContent += "\n```\n\n";
236
- mdContent += "## File Reference\n\n";
237
- const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
238
- mdContent += `The complete agent definition is available in [${relativePath}](${relativePath}).\n\n`;
239
- mdContent += "## Usage\n\n";
240
- mdContent += `When the user types \`@${agentId}\`, activate this ${await this.getAgentTitle(
241
- agentId,
242
- installDir
243
- )} persona and follow all instructions defined in the YAML configuration above.\n`;
380
+ // Write the agent file contents prefixed with Windsurf frontmatter
381
+ let mdContent = `---\n`;
382
+ mdContent += `description: ${agentId}\n`;
383
+ mdContent += `auto_execution_mode: 3\n`;
384
+ mdContent += `---\n\n`;
385
+ mdContent += agentContent;
244
386
 
245
387
  await fileManager.writeFile(mdPath, mdContent);
246
- console.log(chalk.green(`✓ Created rule: ${agentId}.md`));
388
+ console.log(chalk.green(`✓ Created workflow: ${agentId}.md`));
247
389
  }
248
390
  }
249
391
 
250
- console.log(chalk.green(`\n✓ Created Windsurf rules in ${windsurfRulesDir}`));
392
+ console.log(chalk.green(`\n✓ Created Windsurf workflows in ${windsurfWorkflowDir}`));
251
393
 
252
394
  return true;
253
395
  }
254
396
 
255
397
  async setupTrae(installDir, selectedAgent) {
256
- const traeRulesDir = path.join(installDir, ".trae", "rules");
257
- const agents = selectedAgent? [selectedAgent] : await this.getAllAgentIds(installDir);
258
-
398
+ const traeRulesDir = path.join(installDir, '.trae', 'rules');
399
+ const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
400
+
259
401
  await fileManager.ensureDirectory(traeRulesDir);
260
-
402
+
261
403
  for (const agentId of agents) {
262
404
  // Find the agent file
263
405
  const agentPath = await this.findAgentPath(agentId, installDir);
264
-
406
+
265
407
  if (agentPath) {
266
408
  const agentContent = await fileManager.readFile(agentPath);
267
409
  const mdPath = path.join(traeRulesDir, `${agentId}.md`);
268
-
410
+
269
411
  // Create MD content (similar to Cursor but without frontmatter)
270
412
  let mdContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
271
413
  mdContent += `This rule is triggered when the user types \`@${agentId}\` and activates the ${await this.getAgentTitle(
272
414
  agentId,
273
- installDir
415
+ installDir,
274
416
  )} agent persona.\n\n`;
275
- mdContent += "## Agent Activation\n\n";
417
+ mdContent += '## Agent Activation\n\n';
276
418
  mdContent +=
277
- "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";
278
- mdContent += "```yaml\n";
419
+ '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';
420
+ mdContent += '```yaml\n';
279
421
  // Extract just the YAML content from the agent file
280
422
  const yamlContent = extractYamlFromAgent(agentContent);
281
423
  if (yamlContent) {
282
424
  mdContent += yamlContent;
283
- }
284
- else {
425
+ } else {
285
426
  // If no YAML found, include the whole content minus the header
286
- mdContent += agentContent.replace(/^#.*$/m, "").trim();
427
+ mdContent += agentContent.replace(/^#.*$/m, '').trim();
287
428
  }
288
- mdContent += "\n```\n\n";
289
- mdContent += "## File Reference\n\n";
290
- const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
429
+ mdContent += '\n```\n\n';
430
+ mdContent += '## File Reference\n\n';
431
+ const relativePath = path.relative(installDir, agentPath).replaceAll('\\', '/');
291
432
  mdContent += `The complete agent definition is available in [${relativePath}](${relativePath}).\n\n`;
292
- mdContent += "## Usage\n\n";
433
+ mdContent += '## Usage\n\n';
293
434
  mdContent += `When the user types \`@${agentId}\`, activate this ${await this.getAgentTitle(
294
435
  agentId,
295
- installDir
436
+ installDir,
296
437
  )} persona and follow all instructions defined in the YAML configuration above.\n`;
297
-
438
+
298
439
  await fileManager.writeFile(mdPath, mdContent);
299
440
  console.log(chalk.green(`✓ Created rule: ${agentId}.md`));
300
441
  }
@@ -304,116 +445,116 @@ class IdeSetup extends BaseIdeSetup {
304
445
  async findAgentPath(agentId, installDir) {
305
446
  // Try to find the agent file in various locations
306
447
  const possiblePaths = [
307
- path.join(installDir, ".bmad-core", "agents", `${agentId}.md`),
308
- path.join(installDir, "agents", `${agentId}.md`)
448
+ path.join(installDir, '.bmad-core', 'agents', `${agentId}.md`),
449
+ path.join(installDir, 'agents', `${agentId}.md`),
309
450
  ];
310
-
451
+
311
452
  // Also check expansion pack directories
312
- const glob = require("glob");
313
- const expansionDirs = glob.sync(".*/agents", { cwd: installDir });
314
- for (const expDir of expansionDirs) {
453
+ const glob = require('glob');
454
+ const expansionDirectories = glob.sync('.*/agents', { cwd: installDir });
455
+ for (const expDir of expansionDirectories) {
315
456
  possiblePaths.push(path.join(installDir, expDir, `${agentId}.md`));
316
457
  }
317
-
458
+
318
459
  for (const agentPath of possiblePaths) {
319
460
  if (await fileManager.pathExists(agentPath)) {
320
461
  return agentPath;
321
462
  }
322
463
  }
323
-
464
+
324
465
  return null;
325
466
  }
326
467
 
327
468
  async getAllAgentIds(installDir) {
328
- const glob = require("glob");
469
+ const glob = require('glob');
329
470
  const allAgentIds = [];
330
-
471
+
331
472
  // Check core agents in .bmad-core or root
332
- let agentsDir = path.join(installDir, ".bmad-core", "agents");
473
+ let agentsDir = path.join(installDir, '.bmad-core', 'agents');
333
474
  if (!(await fileManager.pathExists(agentsDir))) {
334
- agentsDir = path.join(installDir, "agents");
475
+ agentsDir = path.join(installDir, 'agents');
335
476
  }
336
-
477
+
337
478
  if (await fileManager.pathExists(agentsDir)) {
338
- const agentFiles = glob.sync("*.md", { cwd: agentsDir });
339
- allAgentIds.push(...agentFiles.map((file) => path.basename(file, ".md")));
479
+ const agentFiles = glob.sync('*.md', { cwd: agentsDir });
480
+ allAgentIds.push(...agentFiles.map((file) => path.basename(file, '.md')));
340
481
  }
341
-
482
+
342
483
  // Also check for expansion pack agents in dot folders
343
- const expansionDirs = glob.sync(".*/agents", { cwd: installDir });
344
- for (const expDir of expansionDirs) {
484
+ const expansionDirectories = glob.sync('.*/agents', { cwd: installDir });
485
+ for (const expDir of expansionDirectories) {
345
486
  const fullExpDir = path.join(installDir, expDir);
346
- const expAgentFiles = glob.sync("*.md", { cwd: fullExpDir });
347
- allAgentIds.push(...expAgentFiles.map((file) => path.basename(file, ".md")));
487
+ const expAgentFiles = glob.sync('*.md', { cwd: fullExpDir });
488
+ allAgentIds.push(...expAgentFiles.map((file) => path.basename(file, '.md')));
348
489
  }
349
-
490
+
350
491
  // Remove duplicates
351
492
  return [...new Set(allAgentIds)];
352
493
  }
353
494
 
354
495
  async getCoreAgentIds(installDir) {
355
496
  const allAgentIds = [];
356
-
497
+
357
498
  // Check core agents in .bmad-core or root only
358
- let agentsDir = path.join(installDir, ".bmad-core", "agents");
499
+ let agentsDir = path.join(installDir, '.bmad-core', 'agents');
359
500
  if (!(await fileManager.pathExists(agentsDir))) {
360
- agentsDir = path.join(installDir, "bmad-core", "agents");
501
+ agentsDir = path.join(installDir, 'bmad-core', 'agents');
361
502
  }
362
-
503
+
363
504
  if (await fileManager.pathExists(agentsDir)) {
364
- const glob = require("glob");
365
- const agentFiles = glob.sync("*.md", { cwd: agentsDir });
366
- allAgentIds.push(...agentFiles.map((file) => path.basename(file, ".md")));
505
+ const glob = require('glob');
506
+ const agentFiles = glob.sync('*.md', { cwd: agentsDir });
507
+ allAgentIds.push(...agentFiles.map((file) => path.basename(file, '.md')));
367
508
  }
368
-
509
+
369
510
  return [...new Set(allAgentIds)];
370
511
  }
371
512
 
372
513
  async getCoreTaskIds(installDir) {
373
514
  const allTaskIds = [];
374
-
515
+
375
516
  // Check core tasks in .bmad-core or root only
376
- let tasksDir = path.join(installDir, ".bmad-core", "tasks");
517
+ let tasksDir = path.join(installDir, '.bmad-core', 'tasks');
377
518
  if (!(await fileManager.pathExists(tasksDir))) {
378
- tasksDir = path.join(installDir, "bmad-core", "tasks");
519
+ tasksDir = path.join(installDir, 'bmad-core', 'tasks');
379
520
  }
380
-
521
+
381
522
  if (await fileManager.pathExists(tasksDir)) {
382
- const glob = require("glob");
383
- const taskFiles = glob.sync("*.md", { cwd: tasksDir });
384
- allTaskIds.push(...taskFiles.map((file) => path.basename(file, ".md")));
523
+ const glob = require('glob');
524
+ const taskFiles = glob.sync('*.md', { cwd: tasksDir });
525
+ allTaskIds.push(...taskFiles.map((file) => path.basename(file, '.md')));
385
526
  }
386
-
527
+
387
528
  // Check common tasks
388
- const commonTasksDir = path.join(installDir, "common", "tasks");
529
+ const commonTasksDir = path.join(installDir, 'common', 'tasks');
389
530
  if (await fileManager.pathExists(commonTasksDir)) {
390
- const commonTaskFiles = glob.sync("*.md", { cwd: commonTasksDir });
391
- allTaskIds.push(...commonTaskFiles.map((file) => path.basename(file, ".md")));
531
+ const commonTaskFiles = glob.sync('*.md', { cwd: commonTasksDir });
532
+ allTaskIds.push(...commonTaskFiles.map((file) => path.basename(file, '.md')));
392
533
  }
393
-
534
+
394
535
  return [...new Set(allTaskIds)];
395
536
  }
396
537
 
397
538
  async getAgentTitle(agentId, installDir) {
398
539
  // Try to find the agent file in various locations
399
540
  const possiblePaths = [
400
- path.join(installDir, ".bmad-core", "agents", `${agentId}.md`),
401
- path.join(installDir, "agents", `${agentId}.md`)
541
+ path.join(installDir, '.bmad-core', 'agents', `${agentId}.md`),
542
+ path.join(installDir, 'agents', `${agentId}.md`),
402
543
  ];
403
-
544
+
404
545
  // Also check expansion pack directories
405
- const glob = require("glob");
406
- const expansionDirs = glob.sync(".*/agents", { cwd: installDir });
407
- for (const expDir of expansionDirs) {
546
+ const glob = require('glob');
547
+ const expansionDirectories = glob.sync('.*/agents', { cwd: installDir });
548
+ for (const expDir of expansionDirectories) {
408
549
  possiblePaths.push(path.join(installDir, expDir, `${agentId}.md`));
409
550
  }
410
-
551
+
411
552
  for (const agentPath of possiblePaths) {
412
553
  if (await fileManager.pathExists(agentPath)) {
413
554
  try {
414
555
  const agentContent = await fileManager.readFile(agentPath);
415
556
  const yamlMatch = agentContent.match(/```ya?ml\r?\n([\s\S]*?)```/);
416
-
557
+
417
558
  if (yamlMatch) {
418
559
  const yaml = yamlMatch[1];
419
560
  const titleMatch = yaml.match(/title:\s*(.+)/);
@@ -426,54 +567,55 @@ class IdeSetup extends BaseIdeSetup {
426
567
  }
427
568
  }
428
569
  }
429
-
570
+
430
571
  // Fallback to formatted agent ID
431
- return agentId.split('-').map(word =>
432
- word.charAt(0).toUpperCase() + word.slice(1)
433
- ).join(' ');
572
+ return agentId
573
+ .split('-')
574
+ .map((word) => word.charAt(0).toUpperCase() + word.slice(1))
575
+ .join(' ');
434
576
  }
435
577
 
436
578
  async getAllTaskIds(installDir) {
437
- const glob = require("glob");
579
+ const glob = require('glob');
438
580
  const allTaskIds = [];
439
-
581
+
440
582
  // Check core tasks in .bmad-core or root
441
- let tasksDir = path.join(installDir, ".bmad-core", "tasks");
583
+ let tasksDir = path.join(installDir, '.bmad-core', 'tasks');
442
584
  if (!(await fileManager.pathExists(tasksDir))) {
443
- tasksDir = path.join(installDir, "bmad-core", "tasks");
585
+ tasksDir = path.join(installDir, 'bmad-core', 'tasks');
444
586
  }
445
-
587
+
446
588
  if (await fileManager.pathExists(tasksDir)) {
447
- const taskFiles = glob.sync("*.md", { cwd: tasksDir });
448
- allTaskIds.push(...taskFiles.map((file) => path.basename(file, ".md")));
589
+ const taskFiles = glob.sync('*.md', { cwd: tasksDir });
590
+ allTaskIds.push(...taskFiles.map((file) => path.basename(file, '.md')));
449
591
  }
450
-
592
+
451
593
  // Check common tasks
452
- const commonTasksDir = path.join(installDir, "common", "tasks");
594
+ const commonTasksDir = path.join(installDir, 'common', 'tasks');
453
595
  if (await fileManager.pathExists(commonTasksDir)) {
454
- const commonTaskFiles = glob.sync("*.md", { cwd: commonTasksDir });
455
- allTaskIds.push(...commonTaskFiles.map((file) => path.basename(file, ".md")));
596
+ const commonTaskFiles = glob.sync('*.md', { cwd: commonTasksDir });
597
+ allTaskIds.push(...commonTaskFiles.map((file) => path.basename(file, '.md')));
456
598
  }
457
-
599
+
458
600
  // Also check for expansion pack tasks in dot folders
459
- const expansionDirs = glob.sync(".*/tasks", { cwd: installDir });
460
- for (const expDir of expansionDirs) {
601
+ const expansionDirectories = glob.sync('.*/tasks', { cwd: installDir });
602
+ for (const expDir of expansionDirectories) {
461
603
  const fullExpDir = path.join(installDir, expDir);
462
- const expTaskFiles = glob.sync("*.md", { cwd: fullExpDir });
463
- allTaskIds.push(...expTaskFiles.map((file) => path.basename(file, ".md")));
604
+ const expTaskFiles = glob.sync('*.md', { cwd: fullExpDir });
605
+ allTaskIds.push(...expTaskFiles.map((file) => path.basename(file, '.md')));
464
606
  }
465
-
607
+
466
608
  // Check expansion-packs folder tasks
467
- const expansionPacksDir = path.join(installDir, "expansion-packs");
609
+ const expansionPacksDir = path.join(installDir, 'expansion-packs');
468
610
  if (await fileManager.pathExists(expansionPacksDir)) {
469
- const expPackDirs = glob.sync("*/tasks", { cwd: expansionPacksDir });
470
- for (const expDir of expPackDirs) {
611
+ const expPackDirectories = glob.sync('*/tasks', { cwd: expansionPacksDir });
612
+ for (const expDir of expPackDirectories) {
471
613
  const fullExpDir = path.join(expansionPacksDir, expDir);
472
- const expTaskFiles = glob.sync("*.md", { cwd: fullExpDir });
473
- allTaskIds.push(...expTaskFiles.map((file) => path.basename(file, ".md")));
614
+ const expTaskFiles = glob.sync('*.md', { cwd: fullExpDir });
615
+ allTaskIds.push(...expTaskFiles.map((file) => path.basename(file, '.md')));
474
616
  }
475
617
  }
476
-
618
+
477
619
  // Remove duplicates
478
620
  return [...new Set(allTaskIds)];
479
621
  }
@@ -481,102 +623,104 @@ class IdeSetup extends BaseIdeSetup {
481
623
  async findTaskPath(taskId, installDir) {
482
624
  // Try to find the task file in various locations
483
625
  const possiblePaths = [
484
- path.join(installDir, ".bmad-core", "tasks", `${taskId}.md`),
485
- path.join(installDir, "bmad-core", "tasks", `${taskId}.md`),
486
- path.join(installDir, "common", "tasks", `${taskId}.md`)
626
+ path.join(installDir, '.bmad-core', 'tasks', `${taskId}.md`),
627
+ path.join(installDir, 'bmad-core', 'tasks', `${taskId}.md`),
628
+ path.join(installDir, 'common', 'tasks', `${taskId}.md`),
487
629
  ];
488
-
630
+
489
631
  // Also check expansion pack directories
490
- const glob = require("glob");
491
-
632
+ const glob = require('glob');
633
+
492
634
  // Check dot folder expansion packs
493
- const expansionDirs = glob.sync(".*/tasks", { cwd: installDir });
494
- for (const expDir of expansionDirs) {
635
+ const expansionDirectories = glob.sync('.*/tasks', { cwd: installDir });
636
+ for (const expDir of expansionDirectories) {
495
637
  possiblePaths.push(path.join(installDir, expDir, `${taskId}.md`));
496
638
  }
497
-
639
+
498
640
  // Check expansion-packs folder
499
- const expansionPacksDir = path.join(installDir, "expansion-packs");
641
+ const expansionPacksDir = path.join(installDir, 'expansion-packs');
500
642
  if (await fileManager.pathExists(expansionPacksDir)) {
501
- const expPackDirs = glob.sync("*/tasks", { cwd: expansionPacksDir });
502
- for (const expDir of expPackDirs) {
643
+ const expPackDirectories = glob.sync('*/tasks', { cwd: expansionPacksDir });
644
+ for (const expDir of expPackDirectories) {
503
645
  possiblePaths.push(path.join(expansionPacksDir, expDir, `${taskId}.md`));
504
646
  }
505
647
  }
506
-
648
+
507
649
  for (const taskPath of possiblePaths) {
508
650
  if (await fileManager.pathExists(taskPath)) {
509
651
  return taskPath;
510
652
  }
511
653
  }
512
-
654
+
513
655
  return null;
514
656
  }
515
657
 
516
658
  async getCoreSlashPrefix(installDir) {
517
659
  try {
518
- const coreConfigPath = path.join(installDir, ".bmad-core", "core-config.yaml");
660
+ const coreConfigPath = path.join(installDir, '.bmad-core', 'core-config.yaml');
519
661
  if (!(await fileManager.pathExists(coreConfigPath))) {
520
662
  // Try bmad-core directory
521
- const altConfigPath = path.join(installDir, "bmad-core", "core-config.yaml");
663
+ const altConfigPath = path.join(installDir, 'bmad-core', 'core-config.yaml');
522
664
  if (await fileManager.pathExists(altConfigPath)) {
523
665
  const configContent = await fileManager.readFile(altConfigPath);
524
666
  const config = yaml.load(configContent);
525
- return config.slashPrefix || "BMad";
667
+ return config.slashPrefix || 'BMad';
526
668
  }
527
- return "BMad"; // fallback
669
+ return 'BMad'; // fallback
528
670
  }
529
-
671
+
530
672
  const configContent = await fileManager.readFile(coreConfigPath);
531
673
  const config = yaml.load(configContent);
532
- return config.slashPrefix || "BMad";
674
+ return config.slashPrefix || 'BMad';
533
675
  } catch (error) {
534
676
  console.warn(`Failed to read core slashPrefix, using default 'BMad': ${error.message}`);
535
- return "BMad";
677
+ return 'BMad';
536
678
  }
537
679
  }
538
680
 
539
681
  async getInstalledExpansionPacks(installDir) {
540
682
  const expansionPacks = [];
541
-
683
+
542
684
  // Check for dot-prefixed expansion packs in install directory
543
- const glob = require("glob");
544
- const dotExpansions = glob.sync(".bmad-*", { cwd: installDir });
545
-
685
+ const glob = require('glob');
686
+ const dotExpansions = glob.sync('.bmad-*', { cwd: installDir });
687
+
546
688
  for (const dotExpansion of dotExpansions) {
547
- if (dotExpansion !== ".bmad-core") {
689
+ if (dotExpansion !== '.bmad-core') {
548
690
  const packPath = path.join(installDir, dotExpansion);
549
- const packName = dotExpansion.substring(1); // remove the dot
691
+ const packName = dotExpansion.slice(1); // remove the dot
550
692
  expansionPacks.push({
551
693
  name: packName,
552
- path: packPath
694
+ path: packPath,
553
695
  });
554
696
  }
555
697
  }
556
-
698
+
557
699
  // Check for expansion-packs directory style
558
- const expansionPacksDir = path.join(installDir, "expansion-packs");
700
+ const expansionPacksDir = path.join(installDir, 'expansion-packs');
559
701
  if (await fileManager.pathExists(expansionPacksDir)) {
560
- const packDirs = glob.sync("*", { cwd: expansionPacksDir });
561
-
562
- for (const packDir of packDirs) {
702
+ const packDirectories = glob.sync('*', { cwd: expansionPacksDir });
703
+
704
+ for (const packDir of packDirectories) {
563
705
  const packPath = path.join(expansionPacksDir, packDir);
564
- if ((await fileManager.pathExists(packPath)) &&
565
- (await fileManager.pathExists(path.join(packPath, "config.yaml")))) {
706
+ if (
707
+ (await fileManager.pathExists(packPath)) &&
708
+ (await fileManager.pathExists(path.join(packPath, 'config.yaml')))
709
+ ) {
566
710
  expansionPacks.push({
567
711
  name: packDir,
568
- path: packPath
712
+ path: packPath,
569
713
  });
570
714
  }
571
715
  }
572
716
  }
573
-
717
+
574
718
  return expansionPacks;
575
719
  }
576
720
 
577
721
  async getExpansionPackSlashPrefix(packPath) {
578
722
  try {
579
- const configPath = path.join(packPath, "config.yaml");
723
+ const configPath = path.join(packPath, 'config.yaml');
580
724
  if (await fileManager.pathExists(configPath)) {
581
725
  const configContent = await fileManager.readFile(configPath);
582
726
  const config = yaml.load(configContent);
@@ -585,20 +729,20 @@ class IdeSetup extends BaseIdeSetup {
585
729
  } catch (error) {
586
730
  console.warn(`Failed to read expansion pack slashPrefix from ${packPath}: ${error.message}`);
587
731
  }
588
-
732
+
589
733
  return path.basename(packPath); // fallback to directory name
590
734
  }
591
735
 
592
736
  async getExpansionPackAgents(packPath) {
593
- const agentsDir = path.join(packPath, "agents");
737
+ const agentsDir = path.join(packPath, 'agents');
594
738
  if (!(await fileManager.pathExists(agentsDir))) {
595
739
  return [];
596
740
  }
597
-
741
+
598
742
  try {
599
- const glob = require("glob");
600
- const agentFiles = glob.sync("*.md", { cwd: agentsDir });
601
- return agentFiles.map(file => path.basename(file, ".md"));
743
+ const glob = require('glob');
744
+ const agentFiles = glob.sync('*.md', { cwd: agentsDir });
745
+ return agentFiles.map((file) => path.basename(file, '.md'));
602
746
  } catch (error) {
603
747
  console.warn(`Failed to read expansion pack agents from ${packPath}: ${error.message}`);
604
748
  return [];
@@ -606,15 +750,15 @@ class IdeSetup extends BaseIdeSetup {
606
750
  }
607
751
 
608
752
  async getExpansionPackTasks(packPath) {
609
- const tasksDir = path.join(packPath, "tasks");
753
+ const tasksDir = path.join(packPath, 'tasks');
610
754
  if (!(await fileManager.pathExists(tasksDir))) {
611
755
  return [];
612
756
  }
613
-
757
+
614
758
  try {
615
- const glob = require("glob");
616
- const taskFiles = glob.sync("*.md", { cwd: tasksDir });
617
- return taskFiles.map(file => path.basename(file, ".md"));
759
+ const glob = require('glob');
760
+ const taskFiles = glob.sync('*.md', { cwd: tasksDir });
761
+ return taskFiles.map((file) => path.basename(file, '.md'));
618
762
  } catch (error) {
619
763
  console.warn(`Failed to read expansion pack tasks from ${packPath}: ${error.message}`);
620
764
  return [];
@@ -625,9 +769,9 @@ class IdeSetup extends BaseIdeSetup {
625
769
  const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
626
770
 
627
771
  // Check for existing .roomodes file in project root
628
- const roomodesPath = path.join(installDir, ".roomodes");
772
+ const roomodesPath = path.join(installDir, '.roomodes');
629
773
  let existingModes = [];
630
- let existingContent = "";
774
+ let existingContent = '';
631
775
 
632
776
  if (await fileManager.pathExists(roomodesPath)) {
633
777
  existingContent = await fileManager.readFile(roomodesPath);
@@ -640,7 +784,7 @@ class IdeSetup extends BaseIdeSetup {
640
784
  }
641
785
 
642
786
  // Create new modes content
643
- let newModesContent = "";
787
+ let newModesContent = '';
644
788
 
645
789
  // Load dynamic agent permissions from configuration
646
790
  const config = await this.loadIdeAgentConfig();
@@ -672,14 +816,15 @@ class IdeSetup extends BaseIdeSetup {
672
816
  const whenToUseMatch = yaml.match(/whenToUse:\s*"(.+)"/);
673
817
  const roleDefinitionMatch = yaml.match(/roleDefinition:\s*"(.+)"/);
674
818
 
675
- const title = titleMatch ? titleMatch[1].trim() : await this.getAgentTitle(agentId, installDir);
676
- const icon = iconMatch ? iconMatch[1].trim() : "🤖";
819
+ const title = titleMatch
820
+ ? titleMatch[1].trim()
821
+ : await this.getAgentTitle(agentId, installDir);
822
+ const icon = iconMatch ? iconMatch[1].trim() : '🤖';
677
823
  const whenToUse = whenToUseMatch ? whenToUseMatch[1].trim() : `Use for ${title} tasks`;
678
824
  const roleDefinition = roleDefinitionMatch
679
825
  ? roleDefinitionMatch[1].trim()
680
826
  : `You are a ${title} specializing in ${title.toLowerCase()} tasks and responsibilities.`;
681
827
 
682
-
683
828
  // Add permissions based on agent type
684
829
  const permissions = agentPermissions[agentId];
685
830
  // Build mode entry with proper formatting (matching exact indentation)
@@ -688,12 +833,12 @@ class IdeSetup extends BaseIdeSetup {
688
833
  newModesContent += ` - slug: ${slug}\n`;
689
834
  newModesContent += ` name: '${icon} ${title}'\n`;
690
835
  if (permissions) {
691
- newModesContent += ` description: '${permissions.description}'\n`;
836
+ newModesContent += ` description: '${permissions.description}'\n`;
692
837
  }
693
838
  newModesContent += ` roleDefinition: ${roleDefinition}\n`;
694
839
  newModesContent += ` whenToUse: ${whenToUse}\n`;
695
840
  // Get relative path from installDir to agent file
696
- const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
841
+ const relativePath = path.relative(installDir, agentPath).replaceAll('\\', '/');
697
842
  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`;
698
843
  newModesContent += ` groups:\n`;
699
844
  newModesContent += ` - read\n`;
@@ -712,42 +857,45 @@ class IdeSetup extends BaseIdeSetup {
712
857
  }
713
858
 
714
859
  // Build final roomodes content
715
- let roomodesContent = "";
860
+ let roomodesContent = '';
716
861
  if (existingContent) {
717
862
  // If there's existing content, append new modes to it
718
- roomodesContent = existingContent.trim() + "\n" + newModesContent;
863
+ roomodesContent = existingContent.trim() + '\n' + newModesContent;
719
864
  } else {
720
865
  // Create new .roomodes file with proper YAML structure
721
- roomodesContent = "customModes:\n" + newModesContent;
866
+ roomodesContent = 'customModes:\n' + newModesContent;
722
867
  }
723
868
 
724
869
  // Write .roomodes file
725
870
  await fileManager.writeFile(roomodesPath, roomodesContent);
726
- console.log(chalk.green("✓ Created .roomodes file in project root"));
871
+ console.log(chalk.green('✓ Created .roomodes file in project root'));
727
872
 
728
873
  console.log(chalk.green(`\n✓ Roo Code setup complete!`));
729
- console.log(chalk.dim("Custom modes will be available when you open this project in Roo Code"));
874
+ console.log(chalk.dim('Custom modes will be available when you open this project in Roo Code'));
730
875
 
731
876
  return true;
732
877
  }
733
-
878
+
734
879
  async setupKilocode(installDir, selectedAgent) {
735
- const filePath = path.join(installDir, ".kilocodemodes");
880
+ const filePath = path.join(installDir, '.kilocodemodes');
736
881
  const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
737
882
 
738
- let existingModes = [], existingContent = "";
883
+ let existingModes = [],
884
+ existingContent = '';
739
885
  if (await fileManager.pathExists(filePath)) {
740
886
  existingContent = await fileManager.readFile(filePath);
741
887
  for (const match of existingContent.matchAll(/- slug: ([\w-]+)/g)) {
742
888
  existingModes.push(match[1]);
743
889
  }
744
- console.log(chalk.yellow(`Found existing .kilocodemodes file with ${existingModes.length} modes`));
890
+ console.log(
891
+ chalk.yellow(`Found existing .kilocodemodes file with ${existingModes.length} modes`),
892
+ );
745
893
  }
746
894
 
747
895
  const config = await this.loadIdeAgentConfig();
748
896
  const permissions = config['roo-permissions'] || {}; // reuse same roo permissions block (Kilo Code understands same mode schema)
749
897
 
750
- let newContent = "";
898
+ let newContent = '';
751
899
 
752
900
  for (const agentId of agents) {
753
901
  const slug = agentId.startsWith('bmad-') ? agentId : `bmad-${agentId}`;
@@ -772,13 +920,15 @@ class IdeSetup extends BaseIdeSetup {
772
920
  const yaml = yamlMatch[1];
773
921
 
774
922
  // Robust fallback for title and icon
775
- const title = (yaml.match(/title:\s*(.+)/)?.[1]?.trim()) || await this.getAgentTitle(agentId, installDir);
776
- const icon = (yaml.match(/icon:\s*(.+)/)?.[1]?.trim()) || '🤖';
777
- const whenToUse = (yaml.match(/whenToUse:\s*"(.+)"/)?.[1]?.trim()) || `Use for ${title} tasks`;
778
- const roleDefinition = (yaml.match(/roleDefinition:\s*"(.+)"/)?.[1]?.trim()) ||
923
+ const title =
924
+ yaml.match(/title:\s*(.+)/)?.[1]?.trim() || (await this.getAgentTitle(agentId, installDir));
925
+ const icon = yaml.match(/icon:\s*(.+)/)?.[1]?.trim() || '🤖';
926
+ const whenToUse = yaml.match(/whenToUse:\s*"(.+)"/)?.[1]?.trim() || `Use for ${title} tasks`;
927
+ const roleDefinition =
928
+ yaml.match(/roleDefinition:\s*"(.+)"/)?.[1]?.trim() ||
779
929
  `You are a ${title} specializing in ${title.toLowerCase()} tasks and responsibilities.`;
780
930
 
781
- const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
931
+ const relativePath = path.relative(installDir, agentPath).replaceAll('\\', '/');
782
932
  const 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`;
783
933
 
784
934
  // Add permissions from config if they exist
@@ -788,7 +938,7 @@ class IdeSetup extends BaseIdeSetup {
788
938
  newContent += ` - slug: ${slug}\n`;
789
939
  newContent += ` name: '${icon} ${title}'\n`;
790
940
  if (agentPermission) {
791
- newContent += ` description: '${agentPermission.description}'\n`;
941
+ newContent += ` description: '${agentPermission.description}'\n`;
792
942
  }
793
943
 
794
944
  newContent += ` roleDefinition: ${roleDefinition}\n`;
@@ -797,7 +947,6 @@ class IdeSetup extends BaseIdeSetup {
797
947
  newContent += ` groups:\n`;
798
948
  newContent += ` - read\n`;
799
949
 
800
-
801
950
  if (agentPermission) {
802
951
  newContent += ` - - edit\n`;
803
952
  newContent += ` - fileRegex: ${agentPermission.fileRegex}\n`;
@@ -811,19 +960,19 @@ class IdeSetup extends BaseIdeSetup {
811
960
  }
812
961
 
813
962
  const finalContent = existingContent
814
- ? existingContent.trim() + "\n" + newContent
815
- : "customModes:\n" + newContent;
963
+ ? existingContent.trim() + '\n' + newContent
964
+ : 'customModes:\n' + newContent;
816
965
 
817
966
  await fileManager.writeFile(filePath, finalContent);
818
- console.log(chalk.green("✓ Created .kilocodemodes file in project root"));
967
+ console.log(chalk.green('✓ Created .kilocodemodes file in project root'));
819
968
  console.log(chalk.green(`✓ KiloCode setup complete!`));
820
- console.log(chalk.dim("Custom modes will be available when you open this project in KiloCode"));
969
+ console.log(chalk.dim('Custom modes will be available when you open this project in KiloCode'));
821
970
 
822
971
  return true;
823
972
  }
824
-
973
+
825
974
  async setupCline(installDir, selectedAgent) {
826
- const clineRulesDir = path.join(installDir, ".clinerules");
975
+ const clineRulesDir = path.join(installDir, '.clinerules');
827
976
  const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
828
977
 
829
978
  await fileManager.ensureDirectory(clineRulesDir);
@@ -847,26 +996,28 @@ class IdeSetup extends BaseIdeSetup {
847
996
  // Create MD content for Cline (focused on project standards and role)
848
997
  let mdContent = `# ${await this.getAgentTitle(agentId, installDir)} Agent\n\n`;
849
998
  mdContent += `This rule defines the ${await this.getAgentTitle(agentId, installDir)} persona and project standards.\n\n`;
850
- mdContent += "## Role Definition\n\n";
999
+ mdContent += '## Role Definition\n\n';
851
1000
  mdContent +=
852
- "When the user types `@" + agentId + "`, adopt this persona and follow these guidelines:\n\n";
853
- mdContent += "```yaml\n";
1001
+ 'When the user types `@' +
1002
+ agentId +
1003
+ '`, adopt this persona and follow these guidelines:\n\n';
1004
+ mdContent += '```yaml\n';
854
1005
  // Extract just the YAML content from the agent file
855
1006
  const yamlContent = extractYamlFromAgent(agentContent);
856
1007
  if (yamlContent) {
857
1008
  mdContent += yamlContent;
858
1009
  } else {
859
1010
  // If no YAML found, include the whole content minus the header
860
- mdContent += agentContent.replace(/^#.*$/m, "").trim();
1011
+ mdContent += agentContent.replace(/^#.*$/m, '').trim();
861
1012
  }
862
- mdContent += "\n```\n\n";
863
- mdContent += "## Project Standards\n\n";
1013
+ mdContent += '\n```\n\n';
1014
+ mdContent += '## Project Standards\n\n';
864
1015
  mdContent += `- Always maintain consistency with project documentation in .bmad-core/\n`;
865
1016
  mdContent += `- Follow the agent's specific guidelines and constraints\n`;
866
1017
  mdContent += `- Update relevant project files when making changes\n`;
867
- const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
1018
+ const relativePath = path.relative(installDir, agentPath).replaceAll('\\', '/');
868
1019
  mdContent += `- Reference the complete agent definition in [${relativePath}](${relativePath})\n\n`;
869
- mdContent += "## Usage\n\n";
1020
+ mdContent += '## Usage\n\n';
870
1021
  mdContent += `Type \`@${agentId}\` to activate this ${await this.getAgentTitle(agentId, installDir)} persona.\n`;
871
1022
 
872
1023
  await fileManager.writeFile(mdPath, mdContent);
@@ -880,54 +1031,50 @@ class IdeSetup extends BaseIdeSetup {
880
1031
  }
881
1032
 
882
1033
  async setupGeminiCli(installDir) {
883
- const geminiDir = path.join(installDir, ".gemini");
884
- const bmadMethodDir = path.join(geminiDir, "bmad-method");
1034
+ const geminiDir = path.join(installDir, '.gemini');
1035
+ const bmadMethodDir = path.join(geminiDir, 'bmad-method');
885
1036
  await fileManager.ensureDirectory(bmadMethodDir);
886
1037
 
887
1038
  // Update logic for existing settings.json
888
- const settingsPath = path.join(geminiDir, "settings.json");
1039
+ const settingsPath = path.join(geminiDir, 'settings.json');
889
1040
  if (await fileManager.pathExists(settingsPath)) {
890
1041
  try {
891
1042
  const settingsContent = await fileManager.readFile(settingsPath);
892
1043
  const settings = JSON.parse(settingsContent);
893
1044
  let updated = false;
894
-
1045
+
895
1046
  // Handle contextFileName property
896
1047
  if (settings.contextFileName && Array.isArray(settings.contextFileName)) {
897
1048
  const originalLength = settings.contextFileName.length;
898
1049
  settings.contextFileName = settings.contextFileName.filter(
899
- (fileName) => !fileName.startsWith("agents/")
1050
+ (fileName) => !fileName.startsWith('agents/'),
900
1051
  );
901
1052
  if (settings.contextFileName.length !== originalLength) {
902
1053
  updated = true;
903
1054
  }
904
1055
  }
905
-
1056
+
906
1057
  if (updated) {
907
- await fileManager.writeFile(
908
- settingsPath,
909
- JSON.stringify(settings, null, 2)
1058
+ await fileManager.writeFile(settingsPath, JSON.stringify(settings, null, 2));
1059
+ console.log(
1060
+ chalk.green('✓ Updated .gemini/settings.json - removed agent file references'),
910
1061
  );
911
- console.log(chalk.green("✓ Updated .gemini/settings.json - removed agent file references"));
912
1062
  }
913
1063
  } catch (error) {
914
- console.warn(
915
- chalk.yellow("Could not update .gemini/settings.json"),
916
- error
917
- );
1064
+ console.warn(chalk.yellow('Could not update .gemini/settings.json'), error);
918
1065
  }
919
1066
  }
920
1067
 
921
1068
  // Remove old agents directory
922
- const agentsDir = path.join(geminiDir, "agents");
1069
+ const agentsDir = path.join(geminiDir, 'agents');
923
1070
  if (await fileManager.pathExists(agentsDir)) {
924
1071
  await fileManager.removeDirectory(agentsDir);
925
- console.log(chalk.green("✓ Removed old .gemini/agents directory"));
1072
+ console.log(chalk.green('✓ Removed old .gemini/agents directory'));
926
1073
  }
927
1074
 
928
1075
  // Get all available agents
929
1076
  const agents = await this.getAllAgentIds(installDir);
930
- let concatenatedContent = "";
1077
+ let concatenatedContent = '';
931
1078
 
932
1079
  for (const agentId of agents) {
933
1080
  // Find the source agent file
@@ -935,44 +1082,43 @@ class IdeSetup extends BaseIdeSetup {
935
1082
 
936
1083
  if (agentPath) {
937
1084
  const agentContent = await fileManager.readFile(agentPath);
938
-
1085
+
939
1086
  // Create properly formatted agent rule content (similar to trae)
940
1087
  let agentRuleContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
941
1088
  agentRuleContent += `This rule is triggered when the user types \`*${agentId}\` and activates the ${await this.getAgentTitle(
942
1089
  agentId,
943
- installDir
1090
+ installDir,
944
1091
  )} agent persona.\n\n`;
945
- agentRuleContent += "## Agent Activation\n\n";
1092
+ agentRuleContent += '## Agent Activation\n\n';
946
1093
  agentRuleContent +=
947
- "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";
948
- agentRuleContent += "```yaml\n";
1094
+ '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';
1095
+ agentRuleContent += '```yaml\n';
949
1096
  // Extract just the YAML content from the agent file
950
1097
  const yamlContent = extractYamlFromAgent(agentContent);
951
1098
  if (yamlContent) {
952
1099
  agentRuleContent += yamlContent;
953
- }
954
- else {
1100
+ } else {
955
1101
  // If no YAML found, include the whole content minus the header
956
- agentRuleContent += agentContent.replace(/^#.*$/m, "").trim();
1102
+ agentRuleContent += agentContent.replace(/^#.*$/m, '').trim();
957
1103
  }
958
- agentRuleContent += "\n```\n\n";
959
- agentRuleContent += "## File Reference\n\n";
960
- const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
1104
+ agentRuleContent += '\n```\n\n';
1105
+ agentRuleContent += '## File Reference\n\n';
1106
+ const relativePath = path.relative(installDir, agentPath).replaceAll('\\', '/');
961
1107
  agentRuleContent += `The complete agent definition is available in [${relativePath}](${relativePath}).\n\n`;
962
- agentRuleContent += "## Usage\n\n";
1108
+ agentRuleContent += '## Usage\n\n';
963
1109
  agentRuleContent += `When the user types \`*${agentId}\`, activate this ${await this.getAgentTitle(
964
1110
  agentId,
965
- installDir
1111
+ installDir,
966
1112
  )} persona and follow all instructions defined in the YAML configuration above.\n`;
967
-
1113
+
968
1114
  // Add to concatenated content with separator
969
- concatenatedContent += agentRuleContent + "\n\n---\n\n";
1115
+ concatenatedContent += agentRuleContent + '\n\n---\n\n';
970
1116
  console.log(chalk.green(`✓ Added context for @${agentId}`));
971
1117
  }
972
1118
  }
973
1119
 
974
1120
  // Write the concatenated content to GEMINI.md
975
- const geminiMdPath = path.join(bmadMethodDir, "GEMINI.md");
1121
+ const geminiMdPath = path.join(bmadMethodDir, 'GEMINI.md');
976
1122
  await fileManager.writeFile(geminiMdPath, concatenatedContent);
977
1123
  console.log(chalk.green(`\n✓ Created GEMINI.md in ${bmadMethodDir}`));
978
1124
 
@@ -980,54 +1126,48 @@ class IdeSetup extends BaseIdeSetup {
980
1126
  }
981
1127
 
982
1128
  async setupQwenCode(installDir, selectedAgent) {
983
- const qwenDir = path.join(installDir, ".qwen");
984
- const bmadMethodDir = path.join(qwenDir, "bmad-method");
1129
+ const qwenDir = path.join(installDir, '.qwen');
1130
+ const bmadMethodDir = path.join(qwenDir, 'bmad-method');
985
1131
  await fileManager.ensureDirectory(bmadMethodDir);
986
1132
 
987
1133
  // Update logic for existing settings.json
988
- const settingsPath = path.join(qwenDir, "settings.json");
1134
+ const settingsPath = path.join(qwenDir, 'settings.json');
989
1135
  if (await fileManager.pathExists(settingsPath)) {
990
1136
  try {
991
1137
  const settingsContent = await fileManager.readFile(settingsPath);
992
1138
  const settings = JSON.parse(settingsContent);
993
1139
  let updated = false;
994
-
1140
+
995
1141
  // Handle contextFileName property
996
1142
  if (settings.contextFileName && Array.isArray(settings.contextFileName)) {
997
1143
  const originalLength = settings.contextFileName.length;
998
1144
  settings.contextFileName = settings.contextFileName.filter(
999
- (fileName) => !fileName.startsWith("agents/")
1145
+ (fileName) => !fileName.startsWith('agents/'),
1000
1146
  );
1001
1147
  if (settings.contextFileName.length !== originalLength) {
1002
1148
  updated = true;
1003
1149
  }
1004
1150
  }
1005
-
1151
+
1006
1152
  if (updated) {
1007
- await fileManager.writeFile(
1008
- settingsPath,
1009
- JSON.stringify(settings, null, 2)
1010
- );
1011
- console.log(chalk.green("✓ Updated .qwen/settings.json - removed agent file references"));
1153
+ await fileManager.writeFile(settingsPath, JSON.stringify(settings, null, 2));
1154
+ console.log(chalk.green('✓ Updated .qwen/settings.json - removed agent file references'));
1012
1155
  }
1013
1156
  } catch (error) {
1014
- console.warn(
1015
- chalk.yellow("Could not update .qwen/settings.json"),
1016
- error
1017
- );
1157
+ console.warn(chalk.yellow('Could not update .qwen/settings.json'), error);
1018
1158
  }
1019
1159
  }
1020
1160
 
1021
1161
  // Remove old agents directory
1022
- const agentsDir = path.join(qwenDir, "agents");
1162
+ const agentsDir = path.join(qwenDir, 'agents');
1023
1163
  if (await fileManager.pathExists(agentsDir)) {
1024
1164
  await fileManager.removeDirectory(agentsDir);
1025
- console.log(chalk.green("✓ Removed old .qwen/agents directory"));
1165
+ console.log(chalk.green('✓ Removed old .qwen/agents directory'));
1026
1166
  }
1027
1167
 
1028
1168
  // Get all available agents
1029
1169
  const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
1030
- let concatenatedContent = "";
1170
+ let concatenatedContent = '';
1031
1171
 
1032
1172
  for (const agentId of agents) {
1033
1173
  // Find the source agent file
@@ -1035,57 +1175,61 @@ class IdeSetup extends BaseIdeSetup {
1035
1175
 
1036
1176
  if (agentPath) {
1037
1177
  const agentContent = await fileManager.readFile(agentPath);
1038
-
1178
+
1039
1179
  // Create properly formatted agent rule content (similar to gemini)
1040
1180
  let agentRuleContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
1041
1181
  agentRuleContent += `This rule is triggered when the user types \`*${agentId}\` and activates the ${await this.getAgentTitle(
1042
1182
  agentId,
1043
- installDir
1183
+ installDir,
1044
1184
  )} agent persona.\n\n`;
1045
- agentRuleContent += "## Agent Activation\n\n";
1185
+ agentRuleContent += '## Agent Activation\n\n';
1046
1186
  agentRuleContent +=
1047
- "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";
1048
- agentRuleContent += "```yaml\n";
1187
+ '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';
1188
+ agentRuleContent += '```yaml\n';
1049
1189
  // Extract just the YAML content from the agent file
1050
1190
  const yamlContent = extractYamlFromAgent(agentContent);
1051
1191
  if (yamlContent) {
1052
1192
  agentRuleContent += yamlContent;
1053
- }
1054
- else {
1193
+ } else {
1055
1194
  // If no YAML found, include the whole content minus the header
1056
- agentRuleContent += agentContent.replace(/^#.*$/m, "").trim();
1195
+ agentRuleContent += agentContent.replace(/^#.*$/m, '').trim();
1057
1196
  }
1058
- agentRuleContent += "\n```\n\n";
1059
- agentRuleContent += "## File Reference\n\n";
1060
- const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
1197
+ agentRuleContent += '\n```\n\n';
1198
+ agentRuleContent += '## File Reference\n\n';
1199
+ const relativePath = path.relative(installDir, agentPath).replaceAll('\\', '/');
1061
1200
  agentRuleContent += `The complete agent definition is available in [${relativePath}](${relativePath}).\n\n`;
1062
- agentRuleContent += "## Usage\n\n";
1201
+ agentRuleContent += '## Usage\n\n';
1063
1202
  agentRuleContent += `When the user types \`*${agentId}\`, activate this ${await this.getAgentTitle(
1064
1203
  agentId,
1065
- installDir
1204
+ installDir,
1066
1205
  )} persona and follow all instructions defined in the YAML configuration above.\n`;
1067
-
1206
+
1068
1207
  // Add to concatenated content with separator
1069
- concatenatedContent += agentRuleContent + "\n\n---\n\n";
1208
+ concatenatedContent += agentRuleContent + '\n\n---\n\n';
1070
1209
  console.log(chalk.green(`✓ Added context for *${agentId}`));
1071
1210
  }
1072
1211
  }
1073
1212
 
1074
1213
  // Write the concatenated content to QWEN.md
1075
- const qwenMdPath = path.join(bmadMethodDir, "QWEN.md");
1214
+ const qwenMdPath = path.join(bmadMethodDir, 'QWEN.md');
1076
1215
  await fileManager.writeFile(qwenMdPath, concatenatedContent);
1077
1216
  console.log(chalk.green(`\n✓ Created QWEN.md in ${bmadMethodDir}`));
1078
1217
 
1079
1218
  return true;
1080
1219
  }
1081
1220
 
1082
- async setupGitHubCopilot(installDir, selectedAgent, spinner = null, preConfiguredSettings = null) {
1221
+ async setupGitHubCopilot(
1222
+ installDir,
1223
+ selectedAgent,
1224
+ spinner = null,
1225
+ preConfiguredSettings = null,
1226
+ ) {
1083
1227
  // Configure VS Code workspace settings first to avoid UI conflicts with loading spinners
1084
1228
  await this.configureVsCodeSettings(installDir, spinner, preConfiguredSettings);
1085
-
1086
- const chatmodesDir = path.join(installDir, ".github", "chatmodes");
1229
+
1230
+ const chatmodesDir = path.join(installDir, '.github', 'chatmodes');
1087
1231
  const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
1088
-
1232
+
1089
1233
  await fileManager.ensureDirectory(chatmodesDir);
1090
1234
 
1091
1235
  for (const agentId of agents) {
@@ -1097,7 +1241,7 @@ class IdeSetup extends BaseIdeSetup {
1097
1241
  // Create chat mode file with agent content
1098
1242
  const agentContent = await fileManager.readFile(agentPath);
1099
1243
  const agentTitle = await this.getAgentTitle(agentId, installDir);
1100
-
1244
+
1101
1245
  // Extract whenToUse for the description
1102
1246
  const yamlMatch = agentContent.match(/```ya?ml\r?\n([\s\S]*?)```/);
1103
1247
  let description = `Activates the ${agentTitle} agent persona.`;
@@ -1107,9 +1251,9 @@ class IdeSetup extends BaseIdeSetup {
1107
1251
  description = whenToUseMatch[1];
1108
1252
  }
1109
1253
  }
1110
-
1254
+
1111
1255
  let chatmodeContent = `---
1112
- description: "${description.replace(/"/g, '\\"')}"
1256
+ description: "${description.replaceAll('"', String.raw`\"`)}"
1113
1257
  tools: ['changes', 'codebase', 'fetch', 'findTestFiles', 'githubRepo', 'problems', 'usages', 'editFiles', 'runCommands', 'runTasks', 'runTests', 'search', 'searchResults', 'terminalLastCommand', 'terminalSelection', 'testFailure']
1114
1258
  ---
1115
1259
 
@@ -1128,24 +1272,24 @@ tools: ['changes', 'codebase', 'fetch', 'findTestFiles', 'githubRepo', 'problems
1128
1272
  }
1129
1273
 
1130
1274
  async configureVsCodeSettings(installDir, spinner, preConfiguredSettings = null) {
1131
- const vscodeDir = path.join(installDir, ".vscode");
1132
- const settingsPath = path.join(vscodeDir, "settings.json");
1133
-
1275
+ const vscodeDir = path.join(installDir, '.vscode');
1276
+ const settingsPath = path.join(vscodeDir, 'settings.json');
1277
+
1134
1278
  await fileManager.ensureDirectory(vscodeDir);
1135
-
1279
+
1136
1280
  // Read existing settings if they exist
1137
1281
  let existingSettings = {};
1138
1282
  if (await fileManager.pathExists(settingsPath)) {
1139
1283
  try {
1140
1284
  const existingContent = await fileManager.readFile(settingsPath);
1141
1285
  existingSettings = JSON.parse(existingContent);
1142
- console.log(chalk.yellow("Found existing .vscode/settings.json. Merging BMad settings..."));
1143
- } catch (error) {
1144
- console.warn(chalk.yellow("Could not parse existing settings.json. Creating new one."));
1286
+ console.log(chalk.yellow('Found existing .vscode/settings.json. Merging BMad settings...'));
1287
+ } catch {
1288
+ console.warn(chalk.yellow('Could not parse existing settings.json. Creating new one.'));
1145
1289
  existingSettings = {};
1146
1290
  }
1147
1291
  }
1148
-
1292
+
1149
1293
  // Use pre-configured settings if provided, otherwise prompt
1150
1294
  let configChoice;
1151
1295
  if (preConfiguredSettings && preConfiguredSettings.configChoice) {
@@ -1154,10 +1298,12 @@ tools: ['changes', 'codebase', 'fetch', 'findTestFiles', 'githubRepo', 'problems
1154
1298
  } else {
1155
1299
  // Clear any previous output and add spacing to avoid conflicts with loaders
1156
1300
  console.log('\n'.repeat(2));
1157
- console.log(chalk.blue("🔧 Github Copilot Agent Settings Configuration"));
1158
- console.log(chalk.dim("BMad works best with specific VS Code settings for optimal agent experience."));
1301
+ console.log(chalk.blue('🔧 Github Copilot Agent Settings Configuration'));
1302
+ console.log(
1303
+ chalk.dim('BMad works best with specific VS Code settings for optimal agent experience.'),
1304
+ );
1159
1305
  console.log(''); // Add extra spacing
1160
-
1306
+
1161
1307
  const response = await inquirer.prompt([
1162
1308
  {
1163
1309
  type: 'list',
@@ -1166,59 +1312,59 @@ tools: ['changes', 'codebase', 'fetch', 'findTestFiles', 'githubRepo', 'problems
1166
1312
  choices: [
1167
1313
  {
1168
1314
  name: 'Use recommended defaults (fastest setup)',
1169
- value: 'defaults'
1315
+ value: 'defaults',
1170
1316
  },
1171
1317
  {
1172
1318
  name: 'Configure each setting manually (customize to your preferences)',
1173
- value: 'manual'
1319
+ value: 'manual',
1174
1320
  },
1175
1321
  {
1176
- name: 'Skip settings configuration (I\'ll configure manually later)',
1177
- value: 'skip'
1178
- }
1322
+ name: "Skip settings configuration (I'll configure manually later)",
1323
+ value: 'skip',
1324
+ },
1179
1325
  ],
1180
- default: 'defaults'
1181
- }
1326
+ default: 'defaults',
1327
+ },
1182
1328
  ]);
1183
1329
  configChoice = response.configChoice;
1184
1330
  }
1185
-
1331
+
1186
1332
  let bmadSettings = {};
1187
-
1333
+
1188
1334
  if (configChoice === 'skip') {
1189
- console.log(chalk.yellow("⚠️ Skipping VS Code settings configuration."));
1190
- console.log(chalk.dim("You can manually configure these settings in .vscode/settings.json:"));
1191
- console.log(chalk.dim(" • chat.agent.enabled: true"));
1192
- console.log(chalk.dim(" • chat.agent.maxRequests: 15"));
1193
- console.log(chalk.dim(" • github.copilot.chat.agent.runTasks: true"));
1194
- console.log(chalk.dim(" • chat.mcp.discovery.enabled: true"));
1195
- console.log(chalk.dim(" • github.copilot.chat.agent.autoFix: true"));
1196
- console.log(chalk.dim(" • chat.tools.autoApprove: false"));
1335
+ console.log(chalk.yellow('⚠️ Skipping VS Code settings configuration.'));
1336
+ console.log(chalk.dim('You can manually configure these settings in .vscode/settings.json:'));
1337
+ console.log(chalk.dim(' • chat.agent.enabled: true'));
1338
+ console.log(chalk.dim(' • chat.agent.maxRequests: 15'));
1339
+ console.log(chalk.dim(' • github.copilot.chat.agent.runTasks: true'));
1340
+ console.log(chalk.dim(' • chat.mcp.discovery.enabled: true'));
1341
+ console.log(chalk.dim(' • github.copilot.chat.agent.autoFix: true'));
1342
+ console.log(chalk.dim(' • chat.tools.autoApprove: false'));
1197
1343
  return true;
1198
1344
  }
1199
-
1345
+
1200
1346
  if (configChoice === 'defaults') {
1201
1347
  // Use recommended defaults
1202
1348
  bmadSettings = {
1203
- "chat.agent.enabled": true,
1204
- "chat.agent.maxRequests": 15,
1205
- "github.copilot.chat.agent.runTasks": true,
1206
- "chat.mcp.discovery.enabled": true,
1207
- "github.copilot.chat.agent.autoFix": true,
1208
- "chat.tools.autoApprove": false
1349
+ 'chat.agent.enabled': true,
1350
+ 'chat.agent.maxRequests': 15,
1351
+ 'github.copilot.chat.agent.runTasks': true,
1352
+ 'chat.mcp.discovery.enabled': true,
1353
+ 'github.copilot.chat.agent.autoFix': true,
1354
+ 'chat.tools.autoApprove': false,
1209
1355
  };
1210
- console.log(chalk.green("✓ Using recommended BMad defaults for Github Copilot settings"));
1356
+ console.log(chalk.green('✓ Using recommended BMad defaults for Github Copilot settings'));
1211
1357
  } else {
1212
1358
  // Manual configuration
1213
1359
  console.log(chalk.blue("\n📋 Let's configure each setting for your preferences:"));
1214
-
1360
+
1215
1361
  // Pause spinner during manual configuration prompts
1216
1362
  let spinnerWasActive = false;
1217
1363
  if (spinner && spinner.isSpinning) {
1218
1364
  spinner.stop();
1219
1365
  spinnerWasActive = true;
1220
1366
  }
1221
-
1367
+
1222
1368
  const manualSettings = await inquirer.prompt([
1223
1369
  {
1224
1370
  type: 'input',
@@ -1226,69 +1372,69 @@ tools: ['changes', 'codebase', 'fetch', 'findTestFiles', 'githubRepo', 'problems
1226
1372
  message: 'Maximum requests per agent session (recommended: 15)?',
1227
1373
  default: '15',
1228
1374
  validate: (input) => {
1229
- const num = parseInt(input);
1230
- if (isNaN(num) || num < 1 || num > 50) {
1375
+ const number_ = Number.parseInt(input);
1376
+ if (isNaN(number_) || number_ < 1 || number_ > 50) {
1231
1377
  return 'Please enter a number between 1 and 50';
1232
1378
  }
1233
1379
  return true;
1234
- }
1380
+ },
1235
1381
  },
1236
1382
  {
1237
1383
  type: 'confirm',
1238
1384
  name: 'runTasks',
1239
1385
  message: 'Allow agents to run workspace tasks (package.json scripts, etc.)?',
1240
- default: true
1386
+ default: true,
1241
1387
  },
1242
1388
  {
1243
1389
  type: 'confirm',
1244
1390
  name: 'mcpDiscovery',
1245
1391
  message: 'Enable MCP (Model Context Protocol) server discovery?',
1246
- default: true
1392
+ default: true,
1247
1393
  },
1248
1394
  {
1249
1395
  type: 'confirm',
1250
1396
  name: 'autoFix',
1251
1397
  message: 'Enable automatic error detection and fixing in generated code?',
1252
- default: true
1398
+ default: true,
1253
1399
  },
1254
1400
  {
1255
1401
  type: 'confirm',
1256
1402
  name: 'autoApprove',
1257
1403
  message: 'Auto-approve ALL tools without confirmation? (⚠️ EXPERIMENTAL - less secure)',
1258
- default: false
1259
- }
1404
+ default: false,
1405
+ },
1260
1406
  ]);
1261
1407
 
1262
1408
  // Restart spinner if it was active before prompts
1263
1409
  if (spinner && spinnerWasActive) {
1264
1410
  spinner.start();
1265
1411
  }
1266
-
1412
+
1267
1413
  bmadSettings = {
1268
- "chat.agent.enabled": true, // Always enabled - required for BMad agents
1269
- "chat.agent.maxRequests": parseInt(manualSettings.maxRequests),
1270
- "github.copilot.chat.agent.runTasks": manualSettings.runTasks,
1271
- "chat.mcp.discovery.enabled": manualSettings.mcpDiscovery,
1272
- "github.copilot.chat.agent.autoFix": manualSettings.autoFix,
1273
- "chat.tools.autoApprove": manualSettings.autoApprove
1414
+ 'chat.agent.enabled': true, // Always enabled - required for BMad agents
1415
+ 'chat.agent.maxRequests': Number.parseInt(manualSettings.maxRequests),
1416
+ 'github.copilot.chat.agent.runTasks': manualSettings.runTasks,
1417
+ 'chat.mcp.discovery.enabled': manualSettings.mcpDiscovery,
1418
+ 'github.copilot.chat.agent.autoFix': manualSettings.autoFix,
1419
+ 'chat.tools.autoApprove': manualSettings.autoApprove,
1274
1420
  };
1275
-
1276
- console.log(chalk.green("✓ Custom settings configured"));
1421
+
1422
+ console.log(chalk.green('✓ Custom settings configured'));
1277
1423
  }
1278
-
1424
+
1279
1425
  // Merge settings (existing settings take precedence to avoid overriding user preferences)
1280
1426
  const mergedSettings = { ...bmadSettings, ...existingSettings };
1281
-
1427
+
1282
1428
  // Write the updated settings
1283
1429
  await fileManager.writeFile(settingsPath, JSON.stringify(mergedSettings, null, 2));
1284
-
1285
- console.log(chalk.green("✓ VS Code workspace settings configured successfully"));
1286
- console.log(chalk.dim(" Settings written to .vscode/settings.json:"));
1287
- Object.entries(bmadSettings).forEach(([key, value]) => {
1430
+
1431
+ console.log(chalk.green('✓ VS Code workspace settings configured successfully'));
1432
+ console.log(chalk.dim(' Settings written to .vscode/settings.json:'));
1433
+ for (const [key, value] of Object.entries(bmadSettings)) {
1288
1434
  console.log(chalk.dim(` • ${key}: ${value}`));
1289
- });
1290
- console.log(chalk.dim(""));
1291
- console.log(chalk.dim("You can modify these settings anytime in .vscode/settings.json"));
1435
+ }
1436
+ console.log(chalk.dim(''));
1437
+ console.log(chalk.dim('You can modify these settings anytime in .vscode/settings.json'));
1292
1438
  }
1293
1439
  }
1294
1440