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.
- package/.bmad-core/agent-teams/team-all.yml +16 -0
- package/.bmad-core/agent-teams/team-fullstack.yml +26 -0
- package/.bmad-core/agent-teams/team-no-ui.yml +15 -0
- package/.bmad-core/agents/analyst.md +65 -0
- package/.bmad-core/agents/architect.md +66 -0
- package/.bmad-core/agents/bmad-master.md +107 -0
- package/.bmad-core/agents/bmad-orchestrator.md +81 -0
- package/.bmad-core/agents/dev.md +69 -0
- package/.bmad-core/agents/pm.md +64 -0
- package/.bmad-core/agents/po.md +60 -0
- package/.bmad-core/agents/qa.md +52 -0
- package/.bmad-core/agents/sm.md +60 -0
- package/.bmad-core/agents/ux-expert.md +66 -0
- package/.bmad-core/checklists/architect-checklist.md +443 -0
- package/.bmad-core/checklists/change-checklist.md +182 -0
- package/.bmad-core/checklists/pm-checklist.md +375 -0
- package/.bmad-core/checklists/po-master-checklist.md +441 -0
- package/.bmad-core/checklists/story-dod-checklist.md +101 -0
- package/.bmad-core/checklists/story-draft-checklist.md +156 -0
- package/.bmad-core/data/bmad-kb.md +36 -0
- package/.bmad-core/data/technical-preferences.md +3 -0
- package/.bmad-core/schemas/agent-team-schema.yml +153 -0
- package/.bmad-core/tasks/advanced-elicitation.md +92 -0
- package/.bmad-core/tasks/brainstorming-techniques.md +238 -0
- package/.bmad-core/tasks/brownfield-create-epic.md +160 -0
- package/.bmad-core/tasks/brownfield-create-story.md +147 -0
- package/.bmad-core/tasks/core-dump.md +74 -0
- package/.bmad-core/tasks/correct-course.md +73 -0
- package/.bmad-core/tasks/create-agent.md +202 -0
- package/.bmad-core/tasks/create-deep-research-prompt.md +301 -0
- package/.bmad-core/tasks/create-doc.md +74 -0
- package/.bmad-core/tasks/create-expansion-pack.md +425 -0
- package/.bmad-core/tasks/create-next-story.md +206 -0
- package/.bmad-core/tasks/create-team.md +229 -0
- package/.bmad-core/tasks/doc-migration-task.md +198 -0
- package/.bmad-core/tasks/execute-checklist.md +97 -0
- package/.bmad-core/tasks/generate-ai-frontend-prompt.md +58 -0
- package/.bmad-core/tasks/index-docs.md +180 -0
- package/.bmad-core/tasks/shard-doc.md +173 -0
- package/.bmad-core/templates/agent-tmpl.md +58 -0
- package/.bmad-core/templates/architecture-tmpl.md +771 -0
- package/.bmad-core/templates/brownfield-architecture-tmpl.md +542 -0
- package/.bmad-core/templates/brownfield-prd-tmpl.md +240 -0
- package/.bmad-core/templates/competitor-analysis-tmpl.md +289 -0
- package/.bmad-core/templates/expansion-pack-plan-tmpl.md +91 -0
- package/.bmad-core/templates/front-end-architecture-tmpl.md +173 -0
- package/.bmad-core/templates/front-end-spec-tmpl.md +411 -0
- package/.bmad-core/templates/fullstack-architecture-tmpl.md +1034 -0
- package/.bmad-core/templates/market-research-tmpl.md +261 -0
- package/.bmad-core/templates/prd-tmpl.md +200 -0
- package/.bmad-core/templates/project-brief-tmpl.md +228 -0
- package/.bmad-core/templates/story-tmpl.md +61 -0
- package/.bmad-core/templates/web-agent-startup-instructions-template.md +39 -0
- package/.bmad-core/utils/agent-switcher.ide.md +112 -0
- package/.bmad-core/utils/template-format.md +26 -0
- package/.bmad-core/utils/workflow-management.md +224 -0
- package/.bmad-core/web-bundles/agents/analyst.txt +1679 -0
- package/.bmad-core/web-bundles/agents/architect.txt +3602 -0
- package/.bmad-core/web-bundles/agents/bmad-master.txt +9496 -0
- package/.bmad-core/web-bundles/agents/bmad-orchestrator.txt +1455 -0
- package/.bmad-core/web-bundles/agents/dev.txt +315 -0
- package/.bmad-core/web-bundles/agents/pm.txt +2196 -0
- package/.bmad-core/web-bundles/agents/po.txt +1489 -0
- package/.bmad-core/web-bundles/agents/qa.txt +129 -0
- package/.bmad-core/web-bundles/agents/sm.txt +663 -0
- package/.bmad-core/web-bundles/agents/ux-expert.txt +1099 -0
- package/.bmad-core/web-bundles/teams/team-all.txt +10315 -0
- package/.bmad-core/web-bundles/teams/team-fullstack.txt +9663 -0
- package/.bmad-core/web-bundles/teams/team-no-ui.txt +8504 -0
- package/.bmad-core/workflows/brownfield-fullstack.yml +116 -0
- package/.bmad-core/workflows/brownfield-service.yml +117 -0
- package/.bmad-core/workflows/brownfield-ui.yml +127 -0
- package/.bmad-core/workflows/greenfield-fullstack.yml +177 -0
- package/.bmad-core/workflows/greenfield-service.yml +143 -0
- package/.bmad-core/workflows/greenfield-ui.yml +172 -0
- package/.claude/commands/analyst.md +69 -0
- package/.claude/commands/architect.md +70 -0
- package/.claude/commands/bmad-master.md +111 -0
- package/.claude/commands/bmad-orchestrator.md +85 -0
- package/.claude/commands/dev.md +73 -0
- package/.claude/commands/pm.md +68 -0
- package/.claude/commands/po.md +64 -0
- package/.claude/commands/qa.md +56 -0
- package/.claude/commands/sm.md +64 -0
- package/.claude/commands/ux-expert.md +70 -0
- package/.cursor/rules/analyst.mdc +83 -0
- package/.cursor/rules/architect.mdc +84 -0
- package/.cursor/rules/bmad-master.mdc +125 -0
- package/.cursor/rules/bmad-orchestrator.mdc +99 -0
- package/.cursor/rules/dev.mdc +87 -0
- package/.cursor/rules/pm.mdc +82 -0
- package/.cursor/rules/po.mdc +78 -0
- package/.cursor/rules/qa.mdc +70 -0
- package/.cursor/rules/sm.mdc +78 -0
- package/.cursor/rules/ux-expert.mdc +84 -0
- package/.github/workflows/release.yml +59 -0
- package/.husky/pre-commit +2 -0
- package/.releaserc.json +17 -0
- package/.roo/.roomodes +95 -0
- package/.roo/README.md +38 -0
- package/.vscode/extensions.json +6 -0
- package/.vscode/settings.json +72 -0
- package/.windsurf/rules/analyst.md +77 -0
- package/.windsurf/rules/architect.md +78 -0
- package/.windsurf/rules/bmad-master.md +119 -0
- package/.windsurf/rules/bmad-orchestrator.md +93 -0
- package/.windsurf/rules/dev.md +81 -0
- package/.windsurf/rules/pm.md +76 -0
- package/.windsurf/rules/po.md +72 -0
- package/.windsurf/rules/qa.md +64 -0
- package/.windsurf/rules/sm.md +72 -0
- package/.windsurf/rules/ux-expert.md +78 -0
- package/CHANGELOG.md +22 -0
- package/CONTRIBUTING.md +46 -0
- package/LICENSE +21 -0
- package/README.md +283 -0
- package/docs/versioning-and-releases.md +85 -0
- package/docs/versions.md +49 -0
- package/expansion-packs/README.md +113 -0
- package/expansion-packs/infrastructure-devops/README.md +147 -0
- package/expansion-packs/infrastructure-devops/agents/infra-devops-platform.md +59 -0
- package/expansion-packs/infrastructure-devops/checklists/infrastructure-checklist.md +484 -0
- package/expansion-packs/infrastructure-devops/manifest.yml +38 -0
- package/expansion-packs/infrastructure-devops/tasks/review-infrastructure.md +160 -0
- package/expansion-packs/infrastructure-devops/tasks/validate-infrastructure.md +154 -0
- package/expansion-packs/infrastructure-devops/templates/infrastructure-architecture-tmpl.md +415 -0
- package/expansion-packs/infrastructure-devops/templates/infrastructure-platform-from-arch-tmpl.md +0 -0
- package/package.json +73 -0
- package/tools/bmad-npx-wrapper.js +41 -0
- package/tools/builders/web-builder.js +145 -0
- package/tools/cli.js +119 -0
- package/tools/installer/README.md +58 -0
- package/tools/installer/bin/bmad.js +179 -0
- package/tools/installer/config/install.config.yml +139 -0
- package/tools/installer/lib/config-loader.js +89 -0
- package/tools/installer/lib/file-manager.js +169 -0
- package/tools/installer/lib/ide-setup.js +419 -0
- package/tools/installer/lib/installer.js +534 -0
- package/tools/installer/package-lock.json +704 -0
- package/tools/installer/package.json +43 -0
- package/tools/installer/templates/claude-commands.md +7 -0
- package/tools/installer/templates/cursor-rules.md +22 -0
- package/tools/installer/templates/windsurf-rules.md +22 -0
- package/tools/lib/dependency-resolver.js +179 -0
- package/tools/upgraders/v3-to-v4-upgrader.js +766 -0
- package/tools/version-bump.js +72 -0
- 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();
|