@zeyue0329/xiaoma-cli 1.0.8 → 1.0.10

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