bmad-method 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/.bmad-core/agent-teams/team-all.yml +16 -0
  2. package/.bmad-core/agent-teams/team-fullstack.yml +26 -0
  3. package/.bmad-core/agent-teams/team-no-ui.yml +15 -0
  4. package/.bmad-core/agents/analyst.md +65 -0
  5. package/.bmad-core/agents/architect.md +66 -0
  6. package/.bmad-core/agents/bmad-master.md +107 -0
  7. package/.bmad-core/agents/bmad-orchestrator.md +81 -0
  8. package/.bmad-core/agents/dev.md +69 -0
  9. package/.bmad-core/agents/pm.md +64 -0
  10. package/.bmad-core/agents/po.md +60 -0
  11. package/.bmad-core/agents/qa.md +52 -0
  12. package/.bmad-core/agents/sm.md +60 -0
  13. package/.bmad-core/agents/ux-expert.md +66 -0
  14. package/.bmad-core/checklists/architect-checklist.md +443 -0
  15. package/.bmad-core/checklists/change-checklist.md +182 -0
  16. package/.bmad-core/checklists/pm-checklist.md +375 -0
  17. package/.bmad-core/checklists/po-master-checklist.md +441 -0
  18. package/.bmad-core/checklists/story-dod-checklist.md +101 -0
  19. package/.bmad-core/checklists/story-draft-checklist.md +156 -0
  20. package/.bmad-core/data/bmad-kb.md +36 -0
  21. package/.bmad-core/data/technical-preferences.md +3 -0
  22. package/.bmad-core/schemas/agent-team-schema.yml +153 -0
  23. package/.bmad-core/tasks/advanced-elicitation.md +92 -0
  24. package/.bmad-core/tasks/brainstorming-techniques.md +238 -0
  25. package/.bmad-core/tasks/brownfield-create-epic.md +160 -0
  26. package/.bmad-core/tasks/brownfield-create-story.md +147 -0
  27. package/.bmad-core/tasks/core-dump.md +74 -0
  28. package/.bmad-core/tasks/correct-course.md +73 -0
  29. package/.bmad-core/tasks/create-agent.md +202 -0
  30. package/.bmad-core/tasks/create-deep-research-prompt.md +301 -0
  31. package/.bmad-core/tasks/create-doc.md +74 -0
  32. package/.bmad-core/tasks/create-expansion-pack.md +425 -0
  33. package/.bmad-core/tasks/create-next-story.md +206 -0
  34. package/.bmad-core/tasks/create-team.md +229 -0
  35. package/.bmad-core/tasks/doc-migration-task.md +198 -0
  36. package/.bmad-core/tasks/execute-checklist.md +97 -0
  37. package/.bmad-core/tasks/generate-ai-frontend-prompt.md +58 -0
  38. package/.bmad-core/tasks/index-docs.md +180 -0
  39. package/.bmad-core/tasks/shard-doc.md +173 -0
  40. package/.bmad-core/templates/agent-tmpl.md +58 -0
  41. package/.bmad-core/templates/architecture-tmpl.md +771 -0
  42. package/.bmad-core/templates/brownfield-architecture-tmpl.md +542 -0
  43. package/.bmad-core/templates/brownfield-prd-tmpl.md +240 -0
  44. package/.bmad-core/templates/competitor-analysis-tmpl.md +289 -0
  45. package/.bmad-core/templates/expansion-pack-plan-tmpl.md +91 -0
  46. package/.bmad-core/templates/front-end-architecture-tmpl.md +173 -0
  47. package/.bmad-core/templates/front-end-spec-tmpl.md +411 -0
  48. package/.bmad-core/templates/fullstack-architecture-tmpl.md +1034 -0
  49. package/.bmad-core/templates/market-research-tmpl.md +261 -0
  50. package/.bmad-core/templates/prd-tmpl.md +200 -0
  51. package/.bmad-core/templates/project-brief-tmpl.md +228 -0
  52. package/.bmad-core/templates/story-tmpl.md +61 -0
  53. package/.bmad-core/templates/web-agent-startup-instructions-template.md +39 -0
  54. package/.bmad-core/utils/agent-switcher.ide.md +112 -0
  55. package/.bmad-core/utils/template-format.md +26 -0
  56. package/.bmad-core/utils/workflow-management.md +224 -0
  57. package/.bmad-core/web-bundles/agents/analyst.txt +1679 -0
  58. package/.bmad-core/web-bundles/agents/architect.txt +3602 -0
  59. package/.bmad-core/web-bundles/agents/bmad-master.txt +9496 -0
  60. package/.bmad-core/web-bundles/agents/bmad-orchestrator.txt +1455 -0
  61. package/.bmad-core/web-bundles/agents/dev.txt +315 -0
  62. package/.bmad-core/web-bundles/agents/pm.txt +2196 -0
  63. package/.bmad-core/web-bundles/agents/po.txt +1489 -0
  64. package/.bmad-core/web-bundles/agents/qa.txt +129 -0
  65. package/.bmad-core/web-bundles/agents/sm.txt +663 -0
  66. package/.bmad-core/web-bundles/agents/ux-expert.txt +1099 -0
  67. package/.bmad-core/web-bundles/teams/team-all.txt +10315 -0
  68. package/.bmad-core/web-bundles/teams/team-fullstack.txt +9663 -0
  69. package/.bmad-core/web-bundles/teams/team-no-ui.txt +8504 -0
  70. package/.bmad-core/workflows/brownfield-fullstack.yml +116 -0
  71. package/.bmad-core/workflows/brownfield-service.yml +117 -0
  72. package/.bmad-core/workflows/brownfield-ui.yml +127 -0
  73. package/.bmad-core/workflows/greenfield-fullstack.yml +177 -0
  74. package/.bmad-core/workflows/greenfield-service.yml +143 -0
  75. package/.bmad-core/workflows/greenfield-ui.yml +172 -0
  76. package/.claude/commands/analyst.md +69 -0
  77. package/.claude/commands/architect.md +70 -0
  78. package/.claude/commands/bmad-master.md +111 -0
  79. package/.claude/commands/bmad-orchestrator.md +85 -0
  80. package/.claude/commands/dev.md +73 -0
  81. package/.claude/commands/pm.md +68 -0
  82. package/.claude/commands/po.md +64 -0
  83. package/.claude/commands/qa.md +56 -0
  84. package/.claude/commands/sm.md +64 -0
  85. package/.claude/commands/ux-expert.md +70 -0
  86. package/.cursor/rules/analyst.mdc +83 -0
  87. package/.cursor/rules/architect.mdc +84 -0
  88. package/.cursor/rules/bmad-master.mdc +125 -0
  89. package/.cursor/rules/bmad-orchestrator.mdc +99 -0
  90. package/.cursor/rules/dev.mdc +87 -0
  91. package/.cursor/rules/pm.mdc +82 -0
  92. package/.cursor/rules/po.mdc +78 -0
  93. package/.cursor/rules/qa.mdc +70 -0
  94. package/.cursor/rules/sm.mdc +78 -0
  95. package/.cursor/rules/ux-expert.mdc +84 -0
  96. package/.github/workflows/release.yml +59 -0
  97. package/.husky/pre-commit +2 -0
  98. package/.releaserc.json +17 -0
  99. package/.roo/.roomodes +95 -0
  100. package/.roo/README.md +38 -0
  101. package/.vscode/extensions.json +6 -0
  102. package/.vscode/settings.json +72 -0
  103. package/.windsurf/rules/analyst.md +77 -0
  104. package/.windsurf/rules/architect.md +78 -0
  105. package/.windsurf/rules/bmad-master.md +119 -0
  106. package/.windsurf/rules/bmad-orchestrator.md +93 -0
  107. package/.windsurf/rules/dev.md +81 -0
  108. package/.windsurf/rules/pm.md +76 -0
  109. package/.windsurf/rules/po.md +72 -0
  110. package/.windsurf/rules/qa.md +64 -0
  111. package/.windsurf/rules/sm.md +72 -0
  112. package/.windsurf/rules/ux-expert.md +78 -0
  113. package/CHANGELOG.md +22 -0
  114. package/CONTRIBUTING.md +46 -0
  115. package/LICENSE +21 -0
  116. package/README.md +283 -0
  117. package/docs/versioning-and-releases.md +85 -0
  118. package/docs/versions.md +49 -0
  119. package/expansion-packs/README.md +113 -0
  120. package/expansion-packs/infrastructure-devops/README.md +147 -0
  121. package/expansion-packs/infrastructure-devops/agents/infra-devops-platform.md +59 -0
  122. package/expansion-packs/infrastructure-devops/checklists/infrastructure-checklist.md +484 -0
  123. package/expansion-packs/infrastructure-devops/manifest.yml +38 -0
  124. package/expansion-packs/infrastructure-devops/tasks/review-infrastructure.md +160 -0
  125. package/expansion-packs/infrastructure-devops/tasks/validate-infrastructure.md +154 -0
  126. package/expansion-packs/infrastructure-devops/templates/infrastructure-architecture-tmpl.md +415 -0
  127. package/expansion-packs/infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.md +0 -0
  128. package/package.json +73 -0
  129. package/tools/bmad-npx-wrapper.js +41 -0
  130. package/tools/builders/web-builder.js +145 -0
  131. package/tools/cli.js +119 -0
  132. package/tools/installer/README.md +58 -0
  133. package/tools/installer/bin/bmad.js +179 -0
  134. package/tools/installer/config/install.config.yml +139 -0
  135. package/tools/installer/lib/config-loader.js +89 -0
  136. package/tools/installer/lib/file-manager.js +169 -0
  137. package/tools/installer/lib/ide-setup.js +419 -0
  138. package/tools/installer/lib/installer.js +534 -0
  139. package/tools/installer/package-lock.json +704 -0
  140. package/tools/installer/package.json +43 -0
  141. package/tools/installer/templates/claude-commands.md +7 -0
  142. package/tools/installer/templates/cursor-rules.md +22 -0
  143. package/tools/installer/templates/windsurf-rules.md +22 -0
  144. package/tools/lib/dependency-resolver.js +179 -0
  145. package/tools/upgraders/v3-to-v4-upgrader.js +766 -0
  146. package/tools/version-bump.js +72 -0
  147. package/tools/yaml-format.js +211 -0
@@ -0,0 +1,534 @@
1
+ const path = require("path");
2
+ const chalk = require("chalk");
3
+ const ora = require("ora");
4
+ const inquirer = require("inquirer");
5
+ const fileManager = require("./file-manager");
6
+ const configLoader = require("./config-loader");
7
+ const ideSetup = require("./ide-setup");
8
+
9
+ class Installer {
10
+ async install(config) {
11
+ const spinner = ora("Analyzing installation directory...").start();
12
+
13
+ try {
14
+ // Resolve installation directory
15
+ const installDir = path.resolve(config.directory);
16
+
17
+ // Detect current state
18
+ const state = await this.detectInstallationState(installDir);
19
+
20
+ // Handle different states
21
+ switch (state.type) {
22
+ case "clean":
23
+ return await this.performFreshInstall(config, installDir, spinner);
24
+
25
+ case "v4_existing":
26
+ return await this.handleExistingV4Installation(
27
+ config,
28
+ installDir,
29
+ state,
30
+ spinner
31
+ );
32
+
33
+ case "v3_existing":
34
+ return await this.handleV3Installation(
35
+ config,
36
+ installDir,
37
+ state,
38
+ spinner
39
+ );
40
+
41
+ case "unknown_existing":
42
+ return await this.handleUnknownInstallation(
43
+ config,
44
+ installDir,
45
+ state,
46
+ spinner
47
+ );
48
+ }
49
+ } catch (error) {
50
+ spinner.fail("Installation failed");
51
+ throw error;
52
+ }
53
+ }
54
+
55
+ async detectInstallationState(installDir) {
56
+ const state = {
57
+ type: "clean",
58
+ hasV4Manifest: false,
59
+ hasV3Structure: false,
60
+ hasBmadCore: false,
61
+ hasOtherFiles: false,
62
+ manifest: null,
63
+ };
64
+
65
+ // Check if directory exists
66
+ if (!(await fileManager.pathExists(installDir))) {
67
+ return state; // clean install
68
+ }
69
+
70
+ // Check for V4 installation (has .bmad-core with manifest)
71
+ const bmadCorePath = path.join(installDir, ".bmad-core");
72
+ const manifestPath = path.join(bmadCorePath, "install-manifest.yml");
73
+
74
+ if (await fileManager.pathExists(manifestPath)) {
75
+ state.type = "v4_existing";
76
+ state.hasV4Manifest = true;
77
+ state.hasBmadCore = true;
78
+ state.manifest = await fileManager.readManifest(bmadCorePath);
79
+ return state;
80
+ }
81
+
82
+ // Check for V3 installation (has bmad-agent directory)
83
+ const bmadAgentPath = path.join(installDir, "bmad-agent");
84
+ if (await fileManager.pathExists(bmadAgentPath)) {
85
+ state.type = "v3_existing";
86
+ state.hasV3Structure = true;
87
+ return state;
88
+ }
89
+
90
+ // Check for .bmad-core without manifest (broken V4 or manual copy)
91
+ if (await fileManager.pathExists(bmadCorePath)) {
92
+ state.type = "unknown_existing";
93
+ state.hasBmadCore = true;
94
+ return state;
95
+ }
96
+
97
+ // Check if directory has other files
98
+ const glob = require("glob");
99
+ const files = glob.sync("**/*", {
100
+ cwd: installDir,
101
+ nodir: true,
102
+ ignore: ["**/.git/**", "**/node_modules/**"],
103
+ });
104
+
105
+ if (files.length > 0) {
106
+ state.type = "unknown_existing";
107
+ state.hasOtherFiles = true;
108
+ return state;
109
+ }
110
+
111
+ return state; // clean install
112
+ }
113
+
114
+ async performFreshInstall(config, installDir, spinner) {
115
+ spinner.text = "Installing BMAD Method...";
116
+
117
+ let files = [];
118
+
119
+ if (config.installType === "full") {
120
+ // Full installation - copy entire .bmad-core folder as a subdirectory
121
+ spinner.text = "Copying complete .bmad-core folder...";
122
+ const sourceDir = configLoader.getBmadCorePath();
123
+ const bmadCoreDestDir = path.join(installDir, ".bmad-core");
124
+ await fileManager.copyDirectory(sourceDir, bmadCoreDestDir);
125
+
126
+ // Get list of all files for manifest
127
+ const glob = require("glob");
128
+ files = glob
129
+ .sync("**/*", {
130
+ cwd: bmadCoreDestDir,
131
+ nodir: true,
132
+ ignore: ["**/.git/**", "**/node_modules/**"],
133
+ })
134
+ .map((file) => path.join(".bmad-core", file));
135
+ } else if (config.installType === "single-agent") {
136
+ // Single agent installation
137
+ spinner.text = `Installing ${config.agent} agent...`;
138
+
139
+ // Copy agent file
140
+ const agentPath = configLoader.getAgentPath(config.agent);
141
+ const destAgentPath = path.join(
142
+ installDir,
143
+ "agents",
144
+ `${config.agent}.md`
145
+ );
146
+ await fileManager.copyFile(agentPath, destAgentPath);
147
+ files.push(`agents/${config.agent}.md`);
148
+
149
+ // Copy dependencies
150
+ const dependencies = await configLoader.getAgentDependencies(
151
+ config.agent
152
+ );
153
+ const sourceBase = configLoader.getBmadCorePath();
154
+
155
+ for (const dep of dependencies) {
156
+ spinner.text = `Copying dependency: ${dep}`;
157
+
158
+ if (dep.includes("*")) {
159
+ // Handle glob patterns
160
+ const copiedFiles = await fileManager.copyGlobPattern(
161
+ dep.replace(".bmad-core/", ""),
162
+ sourceBase,
163
+ installDir
164
+ );
165
+ files.push(...copiedFiles);
166
+ } else {
167
+ // Handle single files
168
+ const sourcePath = path.join(
169
+ sourceBase,
170
+ dep.replace(".bmad-core/", "")
171
+ );
172
+ const destPath = path.join(
173
+ installDir,
174
+ dep.replace(".bmad-core/", "")
175
+ );
176
+
177
+ if (await fileManager.copyFile(sourcePath, destPath)) {
178
+ files.push(dep.replace(".bmad-core/", ""));
179
+ }
180
+ }
181
+ }
182
+ }
183
+
184
+ // Set up IDE integration if requested
185
+ if (config.ide) {
186
+ spinner.text = `Setting up ${config.ide} integration...`;
187
+ await ideSetup.setup(config.ide, installDir, config.agent);
188
+ }
189
+
190
+ // Create manifest
191
+ spinner.text = "Creating installation manifest...";
192
+ await fileManager.createManifest(installDir, config, files);
193
+
194
+ spinner.succeed("Installation complete!");
195
+ this.showSuccessMessage(config, installDir);
196
+ }
197
+
198
+ async handleExistingV4Installation(config, installDir, state, spinner) {
199
+ spinner.stop();
200
+
201
+ console.log(chalk.yellow("\n🔍 Found existing BMAD v4 installation"));
202
+ console.log(` Directory: ${installDir}`);
203
+ console.log(` Version: ${state.manifest.version}`);
204
+ console.log(
205
+ ` Installed: ${new Date(
206
+ state.manifest.installed_at
207
+ ).toLocaleDateString()}`
208
+ );
209
+
210
+ const { action } = await inquirer.prompt([
211
+ {
212
+ type: "list",
213
+ name: "action",
214
+ message: "What would you like to do?",
215
+ choices: [
216
+ { name: "Update existing installation", value: "update" },
217
+ { name: "Reinstall (overwrite)", value: "reinstall" },
218
+ { name: "Cancel", value: "cancel" },
219
+ ],
220
+ },
221
+ ]);
222
+
223
+ switch (action) {
224
+ case "update":
225
+ return await this.performUpdate(installDir, state.manifest, spinner);
226
+ case "reinstall":
227
+ return await this.performReinstall(config, installDir, spinner);
228
+ case "cancel":
229
+ console.log("Installation cancelled.");
230
+ return;
231
+ }
232
+ }
233
+
234
+ async handleV3Installation(config, installDir, state, spinner) {
235
+ spinner.stop();
236
+
237
+ console.log(
238
+ chalk.yellow("\n🔍 Found BMAD v3 installation (bmad-agent/ directory)")
239
+ );
240
+ console.log(` Directory: ${installDir}`);
241
+
242
+ const { action } = await inquirer.prompt([
243
+ {
244
+ type: "list",
245
+ name: "action",
246
+ message: "What would you like to do?",
247
+ choices: [
248
+ { name: "Upgrade from v3 to v4 (recommended)", value: "upgrade" },
249
+ { name: "Install v4 alongside v3", value: "alongside" },
250
+ { name: "Cancel", value: "cancel" },
251
+ ],
252
+ },
253
+ ]);
254
+
255
+ switch (action) {
256
+ case "upgrade":
257
+ console.log(chalk.cyan("\n📦 Starting v3 to v4 upgrade process..."));
258
+ const V3ToV4Upgrader = require("../../upgraders/v3-to-v4-upgrader");
259
+ const upgrader = new V3ToV4Upgrader();
260
+ return await upgrader.upgrade({ projectPath: installDir });
261
+ case "alongside":
262
+ return await this.performFreshInstall(config, installDir, spinner);
263
+ case "cancel":
264
+ console.log("Installation cancelled.");
265
+ return;
266
+ }
267
+ }
268
+
269
+ async handleUnknownInstallation(config, installDir, state, spinner) {
270
+ spinner.stop();
271
+
272
+ console.log(chalk.yellow("\n⚠️ Directory contains existing files"));
273
+ console.log(` Directory: ${installDir}`);
274
+
275
+ if (state.hasBmadCore) {
276
+ console.log(" Found: .bmad-core directory (but no manifest)");
277
+ }
278
+ if (state.hasOtherFiles) {
279
+ console.log(" Found: Other files in directory");
280
+ }
281
+
282
+ const { action } = await inquirer.prompt([
283
+ {
284
+ type: "list",
285
+ name: "action",
286
+ message: "What would you like to do?",
287
+ choices: [
288
+ { name: "Install anyway (may overwrite files)", value: "force" },
289
+ { name: "Choose different directory", value: "different" },
290
+ { name: "Cancel", value: "cancel" },
291
+ ],
292
+ },
293
+ ]);
294
+
295
+ switch (action) {
296
+ case "force":
297
+ return await this.performFreshInstall(config, installDir, spinner);
298
+ case "different":
299
+ const { newDir } = await inquirer.prompt([
300
+ {
301
+ type: "input",
302
+ name: "newDir",
303
+ message: "Enter new installation directory:",
304
+ default: path.join(path.dirname(installDir), "bmad-project"),
305
+ },
306
+ ]);
307
+ config.directory = newDir;
308
+ return await this.install(config);
309
+ case "cancel":
310
+ console.log("Installation cancelled.");
311
+ return;
312
+ }
313
+ }
314
+
315
+ async performUpdate(installDir, manifest, spinner) {
316
+ spinner.start("Checking for updates...");
317
+
318
+ try {
319
+ // Check for modified files
320
+ spinner.text = "Checking for modified files...";
321
+ const modifiedFiles = await fileManager.checkModifiedFiles(
322
+ installDir,
323
+ manifest
324
+ );
325
+
326
+ if (modifiedFiles.length > 0) {
327
+ spinner.warn("Found modified files");
328
+ console.log(chalk.yellow("\nThe following files have been modified:"));
329
+ modifiedFiles.forEach((file) => console.log(` - ${file}`));
330
+
331
+ const { action } = await inquirer.prompt([
332
+ {
333
+ type: "list",
334
+ name: "action",
335
+ message: "How would you like to proceed?",
336
+ choices: [
337
+ { name: "Backup and overwrite modified files", value: "backup" },
338
+ { name: "Skip modified files", value: "skip" },
339
+ { name: "Cancel update", value: "cancel" },
340
+ ],
341
+ },
342
+ ]);
343
+
344
+ if (action === "cancel") {
345
+ console.log("Update cancelled.");
346
+ return;
347
+ }
348
+
349
+ if (action === "backup") {
350
+ spinner.start("Backing up modified files...");
351
+ for (const file of modifiedFiles) {
352
+ const filePath = path.join(installDir, file);
353
+ const backupPath = await fileManager.backupFile(filePath);
354
+ console.log(
355
+ chalk.dim(` Backed up: ${file} → ${path.basename(backupPath)}`)
356
+ );
357
+ }
358
+ }
359
+ }
360
+
361
+ // Perform update by re-running installation
362
+ spinner.text = "Updating files...";
363
+ const config = {
364
+ installType: manifest.install_type,
365
+ agent: manifest.agent,
366
+ directory: installDir,
367
+ ide: manifest.ide_setup,
368
+ };
369
+
370
+ await this.performFreshInstall(config, installDir, spinner);
371
+ } catch (error) {
372
+ spinner.fail("Update failed");
373
+ throw error;
374
+ }
375
+ }
376
+
377
+ async performReinstall(config, installDir, spinner) {
378
+ spinner.start("Reinstalling BMAD Method...");
379
+
380
+ // Remove existing .bmad-core
381
+ const bmadCorePath = path.join(installDir, ".bmad-core");
382
+ if (await fileManager.pathExists(bmadCorePath)) {
383
+ await fileManager.removeDirectory(bmadCorePath);
384
+ }
385
+
386
+ return await this.performFreshInstall(config, installDir, spinner);
387
+ }
388
+
389
+ showSuccessMessage(config, installDir) {
390
+ console.log(chalk.green("\n✓ BMAD Method installed successfully!\n"));
391
+
392
+ if (config.ide) {
393
+ const ideConfig = configLoader.getIdeConfiguration(config.ide);
394
+ if (ideConfig && ideConfig.instructions) {
395
+ console.log(
396
+ chalk.bold("To use BMAD agents in " + ideConfig.name + ":")
397
+ );
398
+ console.log(ideConfig.instructions);
399
+ }
400
+ } else {
401
+ console.log(chalk.yellow("No IDE configuration was set up."));
402
+ console.log(
403
+ "You can manually configure your IDE using the agent files in:",
404
+ installDir
405
+ );
406
+ }
407
+
408
+ if (config.installType === "single-agent") {
409
+ console.log(
410
+ chalk.dim(
411
+ "\nNeed other agents? Run: npx bmad-method install --agent=<name>"
412
+ )
413
+ );
414
+ console.log(
415
+ chalk.dim("Need everything? Run: npx bmad-method install --full")
416
+ );
417
+ }
418
+ }
419
+
420
+ // Legacy method for backward compatibility
421
+ async update(options) {
422
+ console.log(chalk.yellow('The "update" command is deprecated.'));
423
+ console.log(
424
+ 'Please use "install" instead - it will detect and offer to update existing installations.'
425
+ );
426
+
427
+ const installDir = await this.findInstallation();
428
+ if (installDir) {
429
+ const config = {
430
+ installType: "full",
431
+ directory: path.dirname(installDir),
432
+ ide: null,
433
+ };
434
+ return await this.install(config);
435
+ } else {
436
+ console.log(chalk.red("No BMAD installation found."));
437
+ }
438
+ }
439
+
440
+ async listAgents() {
441
+ const agents = await configLoader.getAvailableAgents();
442
+
443
+ console.log(chalk.bold("\nAvailable BMAD Agents:\n"));
444
+
445
+ agents.forEach((agent) => {
446
+ console.log(chalk.cyan(` ${agent.id.padEnd(20)}`), agent.description);
447
+ });
448
+
449
+ console.log(
450
+ chalk.dim("\nInstall with: npx bmad-method install --agent=<id>\n")
451
+ );
452
+ }
453
+
454
+ async showStatus() {
455
+ const installDir = await this.findInstallation();
456
+
457
+ if (!installDir) {
458
+ console.log(
459
+ chalk.yellow("No BMAD installation found in current directory tree")
460
+ );
461
+ return;
462
+ }
463
+
464
+ const manifest = await fileManager.readManifest(installDir);
465
+
466
+ if (!manifest) {
467
+ console.log(chalk.red("Invalid installation - manifest not found"));
468
+ return;
469
+ }
470
+
471
+ console.log(chalk.bold("\nBMAD Installation Status:\n"));
472
+ console.log(` Directory: ${installDir}`);
473
+ console.log(` Version: ${manifest.version}`);
474
+ console.log(
475
+ ` Installed: ${new Date(
476
+ manifest.installed_at
477
+ ).toLocaleDateString()}`
478
+ );
479
+ console.log(` Type: ${manifest.install_type}`);
480
+
481
+ if (manifest.agent) {
482
+ console.log(` Agent: ${manifest.agent}`);
483
+ }
484
+
485
+ if (manifest.ide_setup) {
486
+ console.log(` IDE Setup: ${manifest.ide_setup}`);
487
+ }
488
+
489
+ console.log(` Total Files: ${manifest.files.length}`);
490
+
491
+ // Check for modifications
492
+ const modifiedFiles = await fileManager.checkModifiedFiles(
493
+ installDir,
494
+ manifest
495
+ );
496
+ if (modifiedFiles.length > 0) {
497
+ console.log(chalk.yellow(` Modified Files: ${modifiedFiles.length}`));
498
+ }
499
+
500
+ console.log("");
501
+ }
502
+
503
+ async getAvailableAgents() {
504
+ return configLoader.getAvailableAgents();
505
+ }
506
+
507
+ async findInstallation() {
508
+ // Look for .bmad-core in current directory or parent directories
509
+ let currentDir = process.cwd();
510
+
511
+ while (currentDir !== path.dirname(currentDir)) {
512
+ const bmadDir = path.join(currentDir, ".bmad-core");
513
+ const manifestPath = path.join(bmadDir, "install-manifest.yml");
514
+
515
+ if (await fileManager.pathExists(manifestPath)) {
516
+ return bmadDir;
517
+ }
518
+
519
+ currentDir = path.dirname(currentDir);
520
+ }
521
+
522
+ // Also check if we're inside a .bmad-core directory
523
+ if (path.basename(process.cwd()) === ".bmad-core") {
524
+ const manifestPath = path.join(process.cwd(), "install-manifest.yml");
525
+ if (await fileManager.pathExists(manifestPath)) {
526
+ return process.cwd();
527
+ }
528
+ }
529
+
530
+ return null;
531
+ }
532
+ }
533
+
534
+ module.exports = new Installer();