bmad-method 4.41.0 → 4.43.0

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 (36) hide show
  1. package/.github/FORK_GUIDE.md +106 -0
  2. package/.github/workflows/discord.yaml +1 -0
  3. package/.github/workflows/format-check.yaml +2 -0
  4. package/.github/workflows/manual-release.yaml +1 -0
  5. package/.github/workflows/pr-validation.yaml +55 -0
  6. package/CONTRIBUTING.md +41 -0
  7. package/README.md +21 -1
  8. package/bmad-core/agents/bmad-master.md +4 -4
  9. package/bmad-core/agents/dev.md +1 -0
  10. package/bmad-core/data/bmad-kb.md +1 -0
  11. package/bmad-core/workflows/brownfield-fullstack.yaml +2 -2
  12. package/bmad-core/workflows/brownfield-service.yaml +2 -2
  13. package/bmad-core/workflows/brownfield-ui.yaml +2 -2
  14. package/bmad-core/workflows/greenfield-fullstack.yaml +4 -4
  15. package/bmad-core/workflows/greenfield-service.yaml +2 -2
  16. package/bmad-core/workflows/greenfield-ui.yaml +3 -3
  17. package/dist/agents/analyst.txt +1 -0
  18. package/dist/agents/bmad-master.txt +1 -0
  19. package/dist/agents/bmad-orchestrator.txt +1 -0
  20. package/dist/agents/dev.txt +1 -0
  21. package/dist/teams/team-all.txt +17 -15
  22. package/dist/teams/team-fullstack.txt +16 -15
  23. package/dist/teams/team-ide-minimal.txt +2 -0
  24. package/dist/teams/team-no-ui.txt +5 -4
  25. package/docs/expansion-packs.md +3 -83
  26. package/docs/user-guide.md +26 -0
  27. package/implement-fork-friendly-ci.sh +229 -0
  28. package/package.json +4 -1
  29. package/release_notes.md +17 -2
  30. package/test.md +1 -0
  31. package/tools/installer/bin/bmad.js +36 -1
  32. package/tools/installer/config/install.config.yaml +41 -0
  33. package/tools/installer/lib/ide-setup.js +268 -0
  34. package/tools/installer/lib/installer.js +6 -1
  35. package/tools/installer/package.json +1 -1
  36. package/tools/setup-hooks.sh +37 -0
@@ -49,7 +49,7 @@ program
49
49
  .option('-d, --directory <path>', 'Installation directory')
50
50
  .option(
51
51
  '-i, --ide <ide...>',
52
- 'Configure for specific IDE(s) - can specify multiple (cursor, claude-code, windsurf, trae, roo, kilo, cline, gemini, qwen-code, github-copilot, other)',
52
+ 'Configure for specific IDE(s) - can specify multiple (cursor, claude-code, windsurf, trae, roo, kilo, cline, gemini, qwen-code, github-copilot, codex, codex-web, auggie-cli, other)',
53
53
  )
54
54
  .option(
55
55
  '-e, --expansion-packs <packs...>',
@@ -406,6 +406,9 @@ async function promptInstallation() {
406
406
  { name: 'Qwen Code', value: 'qwen-code' },
407
407
  { name: 'Crush', value: 'crush' },
408
408
  { name: 'Github Copilot', value: 'github-copilot' },
409
+ { name: 'Auggie CLI (Augment Code)', value: 'auggie-cli' },
410
+ { name: 'Codex CLI', value: 'codex' },
411
+ { name: 'Codex Web', value: 'codex-web' },
409
412
  ],
410
413
  },
411
414
  ]);
@@ -474,6 +477,38 @@ async function promptInstallation() {
474
477
  answers.githubCopilotConfig = { configChoice };
475
478
  }
476
479
 
480
+ // Configure Auggie CLI (Augment Code) immediately if selected
481
+ if (ides.includes('auggie-cli')) {
482
+ console.log(chalk.cyan('\nšŸ“ Auggie CLI Location Configuration'));
483
+ console.log(chalk.dim('Choose where to install BMad agents for Auggie CLI access.\n'));
484
+
485
+ const { selectedLocations } = await inquirer.prompt([
486
+ {
487
+ type: 'checkbox',
488
+ name: 'selectedLocations',
489
+ message: 'Select Auggie CLI command locations:',
490
+ choices: [
491
+ {
492
+ name: 'User Commands (Global): Available across all your projects (user-wide)',
493
+ value: 'user',
494
+ },
495
+ {
496
+ name: 'Workspace Commands (Project): Stored in repository, shared with team',
497
+ value: 'workspace',
498
+ },
499
+ ],
500
+ validate: (selected) => {
501
+ if (selected.length === 0) {
502
+ return 'Please select at least one location';
503
+ }
504
+ return true;
505
+ },
506
+ },
507
+ ]);
508
+
509
+ answers.augmentCodeConfig = { selectedLocations };
510
+ }
511
+
477
512
  // Ask for web bundles installation
478
513
  const { includeWebBundles } = await inquirer.prompt([
479
514
  {
@@ -121,3 +121,44 @@ ide-configurations:
121
121
  # 2. It concatenates all agent files into a single QWEN.md file.
122
122
  # 3. Simply mention the agent in your prompt (e.g., "As *dev, ...").
123
123
  # 4. The Qwen Code CLI will automatically have the context for that agent.
124
+
125
+ auggie-cli:
126
+ name: Auggie CLI (Augment Code)
127
+ format: multi-location
128
+ locations:
129
+ user:
130
+ name: User Commands (Global)
131
+ rule-dir: ~/.augment/commands/bmad/
132
+ description: Available across all your projects (user-wide)
133
+ workspace:
134
+ name: Workspace Commands (Project)
135
+ rule-dir: ./.augment/commands/bmad/
136
+ description: Stored in your repository and shared with your team
137
+ command-suffix: .md
138
+ instructions: |
139
+ # To use BMad agents in Auggie CLI (Augment Code):
140
+ # 1. Type /bmad:agent-name (e.g., "/bmad:dev", "/bmad:pm", "/bmad:architect")
141
+ # 2. The agent will adopt that persona for the conversation
142
+ # 3. Commands are available based on your selected location(s)
143
+
144
+ codex:
145
+ name: Codex CLI
146
+ format: project-memory
147
+ file: AGENTS.md
148
+ instructions: |
149
+ # To use BMAD agents with Codex CLI:
150
+ # 1. The installer updates/creates AGENTS.md at your project root with BMAD agents and tasks.
151
+ # 2. Run `codex` in your project. Codex automatically reads AGENTS.md as project memory.
152
+ # 3. Mention agents in your prompt (e.g., "As dev, please implement ...") or reference tasks.
153
+ # 4. You can further customize global Codex behavior via ~/.codex/config.toml.
154
+
155
+ codex-web:
156
+ name: Codex Web Enabled
157
+ format: project-memory
158
+ file: AGENTS.md
159
+ instructions: |
160
+ # To enable BMAD agents for Codex Web (cloud):
161
+ # 1. The installer updates/creates AGENTS.md and ensures `.bmad-core` is NOT ignored by git.
162
+ # 2. Commit `.bmad-core/` and `AGENTS.md` to your repository.
163
+ # 3. Open the repo in Codex Web and reference agents naturally (e.g., "As dev, ...").
164
+ # 4. Re-run this installer to refresh agent sections when the core changes.
@@ -74,6 +74,15 @@ class IdeSetup extends BaseIdeSetup {
74
74
  case 'qwen-code': {
75
75
  return this.setupQwenCode(installDir, selectedAgent);
76
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
+ }
77
86
  default: {
78
87
  console.log(chalk.yellow(`\nIDE ${ide} not yet supported`));
79
88
  return false;
@@ -81,6 +90,175 @@ class IdeSetup extends BaseIdeSetup {
81
90
  }
82
91
  }
83
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 bmad-method install -f -i codex\`.\n\n`;
114
+
115
+ section += `### Helpful Commands\n\n`;
116
+ section += `- List agents: \`npx bmad-method list:agents\`\n`;
117
+ section += `- Reinstall BMAD core and regenerate AGENTS.md: \`npx bmad-method install -f -i codex\`\n`;
118
+ section += `- Validate configuration: \`npx bmad-method 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'] = 'bmad-method install -f -i codex';
207
+ if (!updated['bmad:list']) updated['bmad:list'] = 'bmad-method list:agents';
208
+ if (!updated['bmad:validate']) updated['bmad:validate'] = 'bmad-method 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
+
84
262
  async setupCursor(installDir, selectedAgent) {
85
263
  const cursorRulesDir = path.join(installDir, '.cursor', 'rules', 'bmad');
86
264
  const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
@@ -1436,6 +1614,96 @@ tools: ['changes', 'codebase', 'fetch', 'findTestFiles', 'githubRepo', 'problems
1436
1614
  console.log(chalk.dim(''));
1437
1615
  console.log(chalk.dim('You can modify these settings anytime in .vscode/settings.json'));
1438
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;
1706
+ }
1439
1707
  }
1440
1708
 
1441
1709
  module.exports = new IdeSetup();
@@ -408,7 +408,12 @@ class Installer {
408
408
  if (ides.length > 0) {
409
409
  for (const ide of ides) {
410
410
  spinner.text = `Setting up ${ide} integration...`;
411
- const preConfiguredSettings = ide === 'github-copilot' ? config.githubCopilotConfig : null;
411
+ let preConfiguredSettings = null;
412
+ if (ide === 'github-copilot') {
413
+ preConfiguredSettings = config.githubCopilotConfig;
414
+ } else if (ide === 'auggie-cli') {
415
+ preConfiguredSettings = config.augmentCodeConfig;
416
+ }
412
417
  await ideSetup.setup(ide, installDir, config.agent, spinner, preConfiguredSettings);
413
418
  }
414
419
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bmad-method",
3
- "version": "4.41.0",
3
+ "version": "4.43.0",
4
4
  "description": "BMad Method installer - AI-powered Agile development framework",
5
5
  "keywords": [
6
6
  "bmad",
@@ -0,0 +1,37 @@
1
+ #!/bin/bash
2
+
3
+ # Setup script for git hooks
4
+ echo "Setting up git hooks..."
5
+
6
+ # Install husky
7
+ npm install --save-dev husky
8
+
9
+ # Initialize husky
10
+ npx husky init
11
+
12
+ # Create pre-commit hook
13
+ cat > .husky/pre-commit << 'EOF'
14
+ #!/usr/bin/env sh
15
+ . "$(dirname -- "$0")/_/husky.sh"
16
+
17
+ # Run validation checks before commit
18
+ echo "Running pre-commit checks..."
19
+
20
+ npm run validate
21
+ npm run format:check
22
+ npm run lint
23
+
24
+ if [ $? -ne 0 ]; then
25
+ echo "āŒ Pre-commit checks failed. Please fix the issues before committing."
26
+ echo " Run 'npm run format' to fix formatting issues"
27
+ echo " Run 'npm run lint:fix' to fix some lint issues"
28
+ exit 1
29
+ fi
30
+
31
+ echo "āœ… Pre-commit checks passed!"
32
+ EOF
33
+
34
+ chmod +x .husky/pre-commit
35
+
36
+ echo "āœ… Git hooks setup complete!"
37
+ echo "Now commits will be validated before they're created."