bmad-method 4.4.1 → 4.4.2
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/CHANGELOG.md +8 -2
- package/README.md +6 -26
- package/bmad-core/agent-teams/team-all.yml +1 -1
- package/bmad-core/agent-teams/team-fullstack.yml +1 -1
- package/bmad-core/agent-teams/team-ide-minimal.yml +10 -0
- package/bmad-core/agent-teams/team-no-ui.yml +1 -1
- package/package.json +1 -1
- package/tools/installer/bin/bmad.js +66 -13
- package/tools/installer/lib/config-loader.js +77 -4
- package/tools/installer/lib/installer.js +68 -5
- package/tools/installer/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
## [4.4.
|
|
1
|
+
## [4.4.2](https://github.com/bmadcode/BMAD-METHOD/compare/v4.4.1...v4.4.2) (2025-06-17)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* single agent install and team installation support ([18a382b](https://github.com/bmadcode/BMAD-METHOD/commit/18a382baa4e4a82db20affa3525eb951af1081e0))
|
|
2
7
|
|
|
8
|
+
## [4.4.1](https://github.com/bmadcode/BMAD-METHOD/compare/v4.4.0...v4.4.1) (2025-06-17)
|
|
3
9
|
|
|
4
10
|
### Bug Fixes
|
|
5
11
|
|
|
6
|
-
|
|
12
|
+
- installer no longer suggests the bmad-method directory as defauly ([e2e1658](https://github.com/bmadcode/BMAD-METHOD/commit/e2e1658c07f6957fea4e3aa9e7657a650205ee71))
|
|
7
13
|
|
|
8
14
|
# [4.4.0](https://github.com/bmadcode/BMAD-METHOD/compare/v4.3.0...v4.4.0) (2025-06-16)
|
|
9
15
|
|
package/README.md
CHANGED
|
@@ -15,22 +15,16 @@
|
|
|
15
15
|
|
|
16
16
|
### Fastest Start: Web UI (2 minutes) 🏃♂️
|
|
17
17
|
|
|
18
|
-
1. Copy
|
|
18
|
+
1. Copy `bmad-core/web-bundles/teams/team-fullstack.txt`
|
|
19
19
|
2. Create a new Gemini Gem or CustomGPT
|
|
20
20
|
3. Upload the file and set instructions: "Your critical operating instructions are attached, do not break character as directed"
|
|
21
21
|
4. Start chatting! Type `/help` to see available commands
|
|
22
22
|
|
|
23
23
|
### IDE Quick Start (5 minutes) 💻
|
|
24
24
|
|
|
25
|
-
**Prerequisites**: Install [Node.js](https://nodejs.org) (
|
|
25
|
+
**Prerequisites**: Install [Node.js](https://nodejs.org) (v20 or higher)
|
|
26
26
|
|
|
27
|
-
|
|
28
|
-
npx bmad-method install
|
|
29
|
-
# The installer will automatically detect your project state and guide you through:
|
|
30
|
-
# - Fresh installation or upgrade from v3
|
|
31
|
-
# - Full installation or single agent
|
|
32
|
-
# - Destination folder and IDE configuration
|
|
33
|
-
```text
|
|
27
|
+
Run `npx bmad-method install`
|
|
34
28
|
|
|
35
29
|
This installs all agents and configures them for your IDE. If you have an existing v3 installation, it will offer to upgrade it automatically.
|
|
36
30
|
|
|
@@ -70,23 +64,9 @@ For ChatGPT, Claude, or Gemini web interfaces:
|
|
|
70
64
|
|
|
71
65
|
### Method 2: CLI Installer (For IDEs) 🎯
|
|
72
66
|
|
|
73
|
-
**Prerequisites**: Install [Node.js](https://nodejs.org)
|
|
74
|
-
|
|
75
|
-
Install directly into your project:
|
|
67
|
+
**Prerequisites**: Install [Node.js](https://nodejs.org) v20+ first
|
|
76
68
|
|
|
77
|
-
|
|
78
|
-
# Interactive installation (recommended)
|
|
79
|
-
npx bmad-method install
|
|
80
|
-
# The installer automatically detects your project state and guides you through:
|
|
81
|
-
# - Fresh installation or upgrade from v3
|
|
82
|
-
# - Installation type (full/single agent)
|
|
83
|
-
# - Destination directory
|
|
84
|
-
# - IDE configuration
|
|
85
|
-
|
|
86
|
-
# Or use command line options for fresh installations
|
|
87
|
-
npx bmad-method install --full --directory ./my-project --ide cursor
|
|
88
|
-
npx bmad-method install --agent pm --directory ./my-project --ide claude-code
|
|
89
|
-
````
|
|
69
|
+
Install directly into your project: `npx bmad-method install`
|
|
90
70
|
|
|
91
71
|
**Supported IDEs:**
|
|
92
72
|
|
|
@@ -96,7 +76,7 @@ The BMad Method works with any IDE, but has built-in integration for:
|
|
|
96
76
|
- `claude-code` - Claude Code with /agent commands
|
|
97
77
|
- `windsurf` - Windsurf with @agent commands
|
|
98
78
|
- `roo` - Roo Code with custom modes (see `.roomodes`)
|
|
99
|
-
- More coming soon - BUT ITS easy to use with ANY IDE
|
|
79
|
+
- More coming soon - BUT ITS easy to use with ANY IDE - just copy the bmad-code folder to your project, and rename it .bmad-code.
|
|
100
80
|
|
|
101
81
|
## Available Agents
|
|
102
82
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
bundle:
|
|
2
2
|
name: Team All
|
|
3
3
|
icon: 👥
|
|
4
|
-
description:
|
|
4
|
+
description: Includes every core system agent.
|
|
5
5
|
agents:
|
|
6
6
|
- bmad-orchestrator
|
|
7
7
|
- '*'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
bundle:
|
|
2
2
|
name: Team Fullstack
|
|
3
3
|
icon: 🚀
|
|
4
|
-
description:
|
|
4
|
+
description: Team capable of full stack, front end only, or service development.
|
|
5
5
|
agents:
|
|
6
6
|
- bmad-orchestrator
|
|
7
7
|
- analyst
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
bundle:
|
|
2
2
|
name: Team No UI
|
|
3
3
|
icon: 🔧
|
|
4
|
-
description:
|
|
4
|
+
description: Team with no UX or UI Planning.
|
|
5
5
|
agents:
|
|
6
6
|
- bmad-orchestrator
|
|
7
7
|
- analyst
|
package/package.json
CHANGED
|
@@ -46,21 +46,29 @@ program
|
|
|
46
46
|
.description('Install BMAD Method agents and tools')
|
|
47
47
|
.option('-f, --full', 'Install complete .bmad-core folder')
|
|
48
48
|
.option('-a, --agent <agent>', 'Install specific agent with dependencies')
|
|
49
|
+
.option('-t, --team <team>', 'Install specific team with required agents and dependencies')
|
|
50
|
+
.option('-x, --expansion-only', 'Install only expansion packs (no bmad-core)')
|
|
49
51
|
.option('-d, --directory <path>', 'Installation directory (default: .bmad-core)')
|
|
50
52
|
.option('-i, --ide <ide...>', 'Configure for specific IDE(s) - can specify multiple (cursor, claude-code, windsurf, roo, other)')
|
|
51
53
|
.option('-e, --expansion-packs <packs...>', 'Install specific expansion packs (can specify multiple)')
|
|
52
54
|
.action(async (options) => {
|
|
53
55
|
try {
|
|
54
56
|
await initializeModules();
|
|
55
|
-
if (!options.full && !options.agent) {
|
|
57
|
+
if (!options.full && !options.agent && !options.team && !options.expansionOnly) {
|
|
56
58
|
// Interactive mode
|
|
57
59
|
const answers = await promptInstallation();
|
|
58
60
|
await installer.install(answers);
|
|
59
61
|
} else {
|
|
60
62
|
// Direct mode
|
|
63
|
+
let installType = 'full';
|
|
64
|
+
if (options.agent) installType = 'single-agent';
|
|
65
|
+
else if (options.team) installType = 'team';
|
|
66
|
+
else if (options.expansionOnly) installType = 'expansion-only';
|
|
67
|
+
|
|
61
68
|
const config = {
|
|
62
|
-
installType
|
|
69
|
+
installType,
|
|
63
70
|
agent: options.agent,
|
|
71
|
+
team: options.team,
|
|
64
72
|
directory: options.directory || '.bmad-core',
|
|
65
73
|
ides: (options.ide || []).filter(ide => ide !== 'other'),
|
|
66
74
|
expansionPacks: options.expansionPacks || []
|
|
@@ -161,9 +169,17 @@ async function promptInstallation() {
|
|
|
161
169
|
name: 'Complete installation (recommended) - All agents and tools',
|
|
162
170
|
value: 'full'
|
|
163
171
|
},
|
|
172
|
+
{
|
|
173
|
+
name: 'Team installation - Install a specific team with required agents',
|
|
174
|
+
value: 'team'
|
|
175
|
+
},
|
|
164
176
|
{
|
|
165
177
|
name: 'Single agent - Choose one agent to install',
|
|
166
178
|
value: 'single-agent'
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
name: 'Expansion packs only - Install expansion packs without bmad-core',
|
|
182
|
+
value: 'expansion-only'
|
|
167
183
|
}
|
|
168
184
|
]
|
|
169
185
|
}
|
|
@@ -187,25 +203,62 @@ async function promptInstallation() {
|
|
|
187
203
|
answers.agent = agent;
|
|
188
204
|
}
|
|
189
205
|
|
|
190
|
-
//
|
|
191
|
-
if (installType === '
|
|
206
|
+
// If team installation, ask which team
|
|
207
|
+
if (installType === 'team') {
|
|
208
|
+
const teams = await installer.getAvailableTeams();
|
|
209
|
+
const { team } = await inquirer.prompt([
|
|
210
|
+
{
|
|
211
|
+
type: 'list',
|
|
212
|
+
name: 'team',
|
|
213
|
+
message: 'Select a team to install:',
|
|
214
|
+
choices: teams.map(t => ({
|
|
215
|
+
name: `${t.icon || '📋'} ${t.name}: ${t.description}`,
|
|
216
|
+
value: t.id
|
|
217
|
+
}))
|
|
218
|
+
}
|
|
219
|
+
]);
|
|
220
|
+
answers.team = team;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Ask for expansion pack selection
|
|
224
|
+
if (installType === 'full' || installType === 'team' || installType === 'expansion-only') {
|
|
192
225
|
try {
|
|
193
226
|
const availableExpansionPacks = await installer.getAvailableExpansionPacks();
|
|
194
227
|
|
|
195
228
|
if (availableExpansionPacks.length > 0) {
|
|
229
|
+
let choices;
|
|
230
|
+
let message;
|
|
231
|
+
|
|
232
|
+
if (installType === 'expansion-only') {
|
|
233
|
+
message = 'Select expansion packs to install (required):'
|
|
234
|
+
choices = availableExpansionPacks.map(pack => ({
|
|
235
|
+
name: `${pack.name} - ${pack.description}`,
|
|
236
|
+
value: pack.id
|
|
237
|
+
}));
|
|
238
|
+
} else {
|
|
239
|
+
message = 'Select expansion packs to install (optional):';
|
|
240
|
+
choices = [
|
|
241
|
+
{ name: 'Skip expansion packs', value: 'none', checked: true },
|
|
242
|
+
new inquirer.Separator(' --- Expansion Packs ---'),
|
|
243
|
+
...availableExpansionPacks.map(pack => ({
|
|
244
|
+
name: `${pack.name} - ${pack.description}`,
|
|
245
|
+
value: pack.id
|
|
246
|
+
}))
|
|
247
|
+
];
|
|
248
|
+
}
|
|
249
|
+
|
|
196
250
|
const { expansionPacks } = await inquirer.prompt([
|
|
197
251
|
{
|
|
198
252
|
type: 'checkbox',
|
|
199
253
|
name: 'expansionPacks',
|
|
200
|
-
message
|
|
201
|
-
choices
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
]
|
|
254
|
+
message,
|
|
255
|
+
choices,
|
|
256
|
+
validate: installType === 'expansion-only' ? (answer) => {
|
|
257
|
+
if (answer.length < 1) {
|
|
258
|
+
return 'You must select at least one expansion pack for expansion-only installation.';
|
|
259
|
+
}
|
|
260
|
+
return true;
|
|
261
|
+
} : undefined
|
|
209
262
|
}
|
|
210
263
|
]);
|
|
211
264
|
|
|
@@ -78,10 +78,7 @@ class ConfigLoader {
|
|
|
78
78
|
// Convert to flat list of file paths
|
|
79
79
|
const depPaths = [];
|
|
80
80
|
|
|
81
|
-
//
|
|
82
|
-
const config = await this.load();
|
|
83
|
-
const coreFiles = config['agent-dependencies']?.['core-files'] || [];
|
|
84
|
-
depPaths.push(...coreFiles);
|
|
81
|
+
// Core files and utilities are included automatically by DependencyResolver
|
|
85
82
|
|
|
86
83
|
// Add agent file itself is already handled by installer
|
|
87
84
|
|
|
@@ -121,6 +118,82 @@ class ConfigLoader {
|
|
|
121
118
|
getAgentPath(agentId) {
|
|
122
119
|
return path.join(this.getBmadCorePath(), 'agents', `${agentId}.md`);
|
|
123
120
|
}
|
|
121
|
+
|
|
122
|
+
async getAvailableTeams() {
|
|
123
|
+
const teamsDir = path.join(this.getBmadCorePath(), 'agent-teams');
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
const entries = await fs.readdir(teamsDir, { withFileTypes: true });
|
|
127
|
+
const teams = [];
|
|
128
|
+
|
|
129
|
+
for (const entry of entries) {
|
|
130
|
+
if (entry.isFile() && entry.name.endsWith('.yml')) {
|
|
131
|
+
const teamPath = path.join(teamsDir, entry.name);
|
|
132
|
+
|
|
133
|
+
try {
|
|
134
|
+
const teamContent = await fs.readFile(teamPath, 'utf8');
|
|
135
|
+
const teamConfig = yaml.load(teamContent);
|
|
136
|
+
|
|
137
|
+
if (teamConfig.bundle) {
|
|
138
|
+
teams.push({
|
|
139
|
+
id: path.basename(entry.name, '.yml'),
|
|
140
|
+
name: teamConfig.bundle.name || entry.name,
|
|
141
|
+
description: teamConfig.bundle.description || 'Team configuration',
|
|
142
|
+
icon: teamConfig.bundle.icon || '📋'
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.warn(`Warning: Could not load team config ${entry.name}: ${error.message}`);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return teams;
|
|
152
|
+
} catch (error) {
|
|
153
|
+
console.warn(`Warning: Could not scan teams directory: ${error.message}`);
|
|
154
|
+
return [];
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
getTeamPath(teamId) {
|
|
159
|
+
return path.join(this.getBmadCorePath(), 'agent-teams', `${teamId}.yml`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async getTeamDependencies(teamId) {
|
|
163
|
+
// Use DependencyResolver to dynamically parse team dependencies
|
|
164
|
+
const DependencyResolver = require('../../lib/dependency-resolver');
|
|
165
|
+
const resolver = new DependencyResolver(path.join(__dirname, '..', '..', '..'));
|
|
166
|
+
|
|
167
|
+
try {
|
|
168
|
+
const teamDeps = await resolver.resolveTeamDependencies(teamId);
|
|
169
|
+
|
|
170
|
+
// Convert to flat list of file paths
|
|
171
|
+
const depPaths = [];
|
|
172
|
+
|
|
173
|
+
// Add team config file
|
|
174
|
+
depPaths.push(`.bmad-core/agent-teams/${teamId}.yml`);
|
|
175
|
+
|
|
176
|
+
// Add all agents
|
|
177
|
+
for (const agent of teamDeps.agents) {
|
|
178
|
+
const filePath = `.bmad-core/agents/${agent.id}.md`;
|
|
179
|
+
if (!depPaths.includes(filePath)) {
|
|
180
|
+
depPaths.push(filePath);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Add all resolved resources
|
|
185
|
+
for (const resource of teamDeps.resources) {
|
|
186
|
+
const filePath = `.bmad-core/${resource.type}/${resource.id}.${resource.type === 'workflows' ? 'yml' : 'md'}`;
|
|
187
|
+
if (!depPaths.includes(filePath)) {
|
|
188
|
+
depPaths.push(filePath);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return depPaths;
|
|
193
|
+
} catch (error) {
|
|
194
|
+
throw new Error(`Failed to resolve team dependencies for ${teamId}: ${error.message}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
124
197
|
}
|
|
125
198
|
|
|
126
199
|
module.exports = new ConfigLoader();
|
|
@@ -220,11 +220,12 @@ class Installer {
|
|
|
220
220
|
const agentPath = configLoader.getAgentPath(config.agent);
|
|
221
221
|
const destAgentPath = path.join(
|
|
222
222
|
installDir,
|
|
223
|
+
".bmad-core",
|
|
223
224
|
"agents",
|
|
224
225
|
`${config.agent}.md`
|
|
225
226
|
);
|
|
226
227
|
await fileManager.copyFile(agentPath, destAgentPath);
|
|
227
|
-
files.push(
|
|
228
|
+
files.push(`.bmad-core/agents/${config.agent}.md`);
|
|
228
229
|
|
|
229
230
|
// Copy dependencies
|
|
230
231
|
const dependencies = await configLoader.getAgentDependencies(
|
|
@@ -240,9 +241,9 @@ class Installer {
|
|
|
240
241
|
const copiedFiles = await fileManager.copyGlobPattern(
|
|
241
242
|
dep.replace(".bmad-core/", ""),
|
|
242
243
|
sourceBase,
|
|
243
|
-
installDir
|
|
244
|
+
path.join(installDir, ".bmad-core")
|
|
244
245
|
);
|
|
245
|
-
files.push(...copiedFiles);
|
|
246
|
+
files.push(...copiedFiles.map(f => `.bmad-core/${f}`));
|
|
246
247
|
} else {
|
|
247
248
|
// Handle single files
|
|
248
249
|
const sourcePath = path.join(
|
|
@@ -251,14 +252,72 @@ class Installer {
|
|
|
251
252
|
);
|
|
252
253
|
const destPath = path.join(
|
|
253
254
|
installDir,
|
|
254
|
-
dep
|
|
255
|
+
dep
|
|
255
256
|
);
|
|
256
257
|
|
|
257
258
|
if (await fileManager.copyFile(sourcePath, destPath)) {
|
|
258
|
-
files.push(dep
|
|
259
|
+
files.push(dep);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
} else if (config.installType === "team") {
|
|
264
|
+
// Team installation
|
|
265
|
+
spinner.text = `Installing ${config.team} team...`;
|
|
266
|
+
|
|
267
|
+
// Get team dependencies
|
|
268
|
+
const teamDependencies = await configLoader.getTeamDependencies(config.team);
|
|
269
|
+
const sourceBase = configLoader.getBmadCorePath();
|
|
270
|
+
|
|
271
|
+
// Install all team dependencies
|
|
272
|
+
for (const dep of teamDependencies) {
|
|
273
|
+
spinner.text = `Copying team dependency: ${dep}`;
|
|
274
|
+
|
|
275
|
+
if (dep.includes("*")) {
|
|
276
|
+
// Handle glob patterns
|
|
277
|
+
const copiedFiles = await fileManager.copyGlobPattern(
|
|
278
|
+
dep.replace(".bmad-core/", ""),
|
|
279
|
+
sourceBase,
|
|
280
|
+
path.join(installDir, ".bmad-core")
|
|
281
|
+
);
|
|
282
|
+
files.push(...copiedFiles.map(f => `.bmad-core/${f}`));
|
|
283
|
+
} else {
|
|
284
|
+
// Handle single files
|
|
285
|
+
const sourcePath = path.join(sourceBase, dep.replace(".bmad-core/", ""));
|
|
286
|
+
const destPath = path.join(installDir, dep);
|
|
287
|
+
|
|
288
|
+
if (await fileManager.copyFile(sourcePath, destPath)) {
|
|
289
|
+
files.push(dep);
|
|
259
290
|
}
|
|
260
291
|
}
|
|
261
292
|
}
|
|
293
|
+
} else if (config.installType === "expansion-only") {
|
|
294
|
+
// Expansion-only installation - create minimal .bmad-core structure
|
|
295
|
+
spinner.text = "Creating minimal .bmad-core structure for expansion packs...";
|
|
296
|
+
|
|
297
|
+
const bmadCoreDestDir = path.join(installDir, ".bmad-core");
|
|
298
|
+
await fileManager.ensureDirectory(bmadCoreDestDir);
|
|
299
|
+
|
|
300
|
+
// Create basic directory structure
|
|
301
|
+
const dirs = ['agents', 'agent-teams', 'templates', 'tasks', 'checklists', 'workflows', 'data', 'utils', 'schemas'];
|
|
302
|
+
for (const dir of dirs) {
|
|
303
|
+
await fileManager.ensureDirectory(path.join(bmadCoreDestDir, dir));
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
// Copy minimal required files (schemas, utils, etc.)
|
|
307
|
+
const sourceBase = configLoader.getBmadCorePath();
|
|
308
|
+
const essentialFiles = [
|
|
309
|
+
'schemas/**/*',
|
|
310
|
+
'utils/**/*'
|
|
311
|
+
];
|
|
312
|
+
|
|
313
|
+
for (const pattern of essentialFiles) {
|
|
314
|
+
const copiedFiles = await fileManager.copyGlobPattern(
|
|
315
|
+
pattern,
|
|
316
|
+
sourceBase,
|
|
317
|
+
bmadCoreDestDir
|
|
318
|
+
);
|
|
319
|
+
files.push(...copiedFiles.map(f => `.bmad-core/${f}`));
|
|
320
|
+
}
|
|
262
321
|
}
|
|
263
322
|
|
|
264
323
|
// Install expansion packs if requested
|
|
@@ -664,6 +723,10 @@ class Installer {
|
|
|
664
723
|
return configLoader.getAvailableExpansionPacks();
|
|
665
724
|
}
|
|
666
725
|
|
|
726
|
+
async getAvailableTeams() {
|
|
727
|
+
return configLoader.getAvailableTeams();
|
|
728
|
+
}
|
|
729
|
+
|
|
667
730
|
async installExpansionPacks(installDir, selectedPacks, spinner) {
|
|
668
731
|
if (!selectedPacks || selectedPacks.length === 0) {
|
|
669
732
|
return [];
|