bmad-method 4.41.0 → 4.42.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/.github/FORK_GUIDE.md +106 -0
- package/.github/workflows/discord.yaml +1 -0
- package/.github/workflows/format-check.yaml +2 -0
- package/.github/workflows/manual-release.yaml +1 -0
- package/.github/workflows/pr-validation.yaml +55 -0
- package/CONTRIBUTING.md +41 -0
- package/README.md +37 -1
- package/bmad-core/agents/bmad-master.md +4 -4
- package/bmad-core/agents/dev.md +1 -0
- package/bmad-core/workflows/brownfield-fullstack.yaml +2 -2
- package/bmad-core/workflows/brownfield-service.yaml +2 -2
- package/bmad-core/workflows/brownfield-ui.yaml +2 -2
- package/bmad-core/workflows/greenfield-fullstack.yaml +4 -4
- package/bmad-core/workflows/greenfield-service.yaml +2 -2
- package/bmad-core/workflows/greenfield-ui.yaml +3 -3
- package/dist/agents/dev.txt +1 -0
- package/dist/teams/team-all.txt +16 -15
- package/dist/teams/team-fullstack.txt +15 -15
- package/dist/teams/team-ide-minimal.txt +1 -0
- package/dist/teams/team-no-ui.txt +4 -4
- package/docs/user-guide.md +26 -0
- package/implement-fork-friendly-ci.sh +229 -0
- package/package.json +4 -1
- package/release_notes.md +12 -2
- package/test.md +1 -0
- package/tools/installer/bin/bmad.js +1 -1
- package/tools/installer/config/install.config.yaml +22 -0
- package/tools/installer/lib/ide-setup.js +175 -0
- package/tools/installer/package.json +1 -1
- package/tools/setup-hooks.sh +37 -0
|
@@ -74,6 +74,12 @@ class IdeSetup extends BaseIdeSetup {
|
|
|
74
74
|
case 'qwen-code': {
|
|
75
75
|
return this.setupQwenCode(installDir, selectedAgent);
|
|
76
76
|
}
|
|
77
|
+
case 'codex': {
|
|
78
|
+
return this.setupCodex(installDir, selectedAgent, { webEnabled: false });
|
|
79
|
+
}
|
|
80
|
+
case 'codex-web': {
|
|
81
|
+
return this.setupCodex(installDir, selectedAgent, { webEnabled: true });
|
|
82
|
+
}
|
|
77
83
|
default: {
|
|
78
84
|
console.log(chalk.yellow(`\nIDE ${ide} not yet supported`));
|
|
79
85
|
return false;
|
|
@@ -81,6 +87,175 @@ class IdeSetup extends BaseIdeSetup {
|
|
|
81
87
|
}
|
|
82
88
|
}
|
|
83
89
|
|
|
90
|
+
async setupCodex(installDir, selectedAgent, options) {
|
|
91
|
+
options = options ?? { webEnabled: false };
|
|
92
|
+
// Codex reads AGENTS.md at the project root as project memory (CLI & Web).
|
|
93
|
+
// Inject/update a BMAD section with guidance, directory, and details.
|
|
94
|
+
const filePath = path.join(installDir, 'AGENTS.md');
|
|
95
|
+
const startMarker = '<!-- BEGIN: BMAD-AGENTS -->';
|
|
96
|
+
const endMarker = '<!-- END: BMAD-AGENTS -->';
|
|
97
|
+
|
|
98
|
+
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
|
|
99
|
+
const tasks = await this.getAllTaskIds(installDir);
|
|
100
|
+
|
|
101
|
+
// Build BMAD section content
|
|
102
|
+
let section = '';
|
|
103
|
+
section += `${startMarker}\n`;
|
|
104
|
+
section += `# BMAD-METHOD Agents and Tasks\n\n`;
|
|
105
|
+
section += `This section is auto-generated by BMAD-METHOD for Codex. Codex merges this AGENTS.md into context.\n\n`;
|
|
106
|
+
section += `## How To Use With Codex\n\n`;
|
|
107
|
+
section += `- Codex CLI: run \`codex\` in this project. Reference an agent naturally, e.g., "As dev, implement ...".\n`;
|
|
108
|
+
section += `- Codex Web: open this repo and reference roles the same way; Codex reads \`AGENTS.md\`.\n`;
|
|
109
|
+
section += `- Commit \`.bmad-core\` and this \`AGENTS.md\` file to your repo so Codex (Web/CLI) can read full agent definitions.\n`;
|
|
110
|
+
section += `- Refresh this section after agent updates: \`npx bmad-method install -f -i codex\`.\n\n`;
|
|
111
|
+
|
|
112
|
+
section += `### Helpful Commands\n\n`;
|
|
113
|
+
section += `- List agents: \`npx bmad-method list:agents\`\n`;
|
|
114
|
+
section += `- Reinstall BMAD core and regenerate AGENTS.md: \`npx bmad-method install -f -i codex\`\n`;
|
|
115
|
+
section += `- Validate configuration: \`npx bmad-method validate\`\n\n`;
|
|
116
|
+
|
|
117
|
+
// Agents directory table
|
|
118
|
+
section += `## Agents\n\n`;
|
|
119
|
+
section += `### Directory\n\n`;
|
|
120
|
+
section += `| Title | ID | When To Use |\n|---|---|---|\n`;
|
|
121
|
+
const agentSummaries = [];
|
|
122
|
+
for (const agentId of agents) {
|
|
123
|
+
const agentPath = await this.findAgentPath(agentId, installDir);
|
|
124
|
+
if (!agentPath) continue;
|
|
125
|
+
const raw = await fileManager.readFile(agentPath);
|
|
126
|
+
const yamlMatch = raw.match(/```ya?ml\r?\n([\s\S]*?)```/);
|
|
127
|
+
const yamlBlock = yamlMatch ? yamlMatch[1].trim() : null;
|
|
128
|
+
const title = await this.getAgentTitle(agentId, installDir);
|
|
129
|
+
const whenToUse = yamlBlock?.match(/whenToUse:\s*"?([^\n"]+)"?/i)?.[1]?.trim() || '';
|
|
130
|
+
agentSummaries.push({ agentId, title, whenToUse, yamlBlock, raw, path: agentPath });
|
|
131
|
+
section += `| ${title} | ${agentId} | ${whenToUse || '—'} |\n`;
|
|
132
|
+
}
|
|
133
|
+
section += `\n`;
|
|
134
|
+
|
|
135
|
+
// Detailed agent sections
|
|
136
|
+
for (const { agentId, title, whenToUse, yamlBlock, raw, path: agentPath } of agentSummaries) {
|
|
137
|
+
const relativePath = path.relative(installDir, agentPath).replaceAll('\\', '/');
|
|
138
|
+
section += `### ${title} (id: ${agentId})\n`;
|
|
139
|
+
section += `Source: ${relativePath}\n\n`;
|
|
140
|
+
if (whenToUse) section += `- When to use: ${whenToUse}\n`;
|
|
141
|
+
section += `- How to activate: Mention "As ${agentId}, ..." or "Use ${title} to ..."\n\n`;
|
|
142
|
+
if (yamlBlock) {
|
|
143
|
+
section += '```yaml\n' + yamlBlock + '\n```\n\n';
|
|
144
|
+
} else {
|
|
145
|
+
section += '```md\n' + raw.trim() + '\n```\n\n';
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Tasks
|
|
150
|
+
if (tasks && tasks.length > 0) {
|
|
151
|
+
section += `## Tasks\n\n`;
|
|
152
|
+
section += `These are reusable task briefs you can reference directly in Codex.\n\n`;
|
|
153
|
+
for (const taskId of tasks) {
|
|
154
|
+
const taskPath = await this.findTaskPath(taskId, installDir);
|
|
155
|
+
if (!taskPath) continue;
|
|
156
|
+
const raw = await fileManager.readFile(taskPath);
|
|
157
|
+
const relativePath = path.relative(installDir, taskPath).replaceAll('\\', '/');
|
|
158
|
+
section += `### Task: ${taskId}\n`;
|
|
159
|
+
section += `Source: ${relativePath}\n`;
|
|
160
|
+
section += `- How to use: "Use task ${taskId} with the appropriate agent" and paste relevant parts as needed.\n\n`;
|
|
161
|
+
section += '```md\n' + raw.trim() + '\n```\n\n';
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
section += `${endMarker}\n`;
|
|
166
|
+
|
|
167
|
+
// Write or update AGENTS.md
|
|
168
|
+
let finalContent = '';
|
|
169
|
+
if (await fileManager.pathExists(filePath)) {
|
|
170
|
+
const existing = await fileManager.readFile(filePath);
|
|
171
|
+
if (existing.includes(startMarker) && existing.includes(endMarker)) {
|
|
172
|
+
// Replace existing BMAD block
|
|
173
|
+
const pattern = String.raw`${startMarker}[\s\S]*?${endMarker}`;
|
|
174
|
+
const replaced = existing.replace(new RegExp(pattern, 'm'), section);
|
|
175
|
+
finalContent = replaced;
|
|
176
|
+
} else {
|
|
177
|
+
// Append BMAD block to existing file
|
|
178
|
+
finalContent = existing.trimEnd() + `\n\n` + section;
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
// Create fresh AGENTS.md with a small header and BMAD block
|
|
182
|
+
finalContent += '# Project Agents\n\n';
|
|
183
|
+
finalContent += 'This file provides guidance and memory for Codex CLI.\n\n';
|
|
184
|
+
finalContent += section;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
await fileManager.writeFile(filePath, finalContent);
|
|
188
|
+
console.log(chalk.green('✓ Created/updated AGENTS.md for Codex CLI integration'));
|
|
189
|
+
console.log(
|
|
190
|
+
chalk.dim(
|
|
191
|
+
'Codex reads AGENTS.md automatically. Run `codex` in this project to use BMAD agents.',
|
|
192
|
+
),
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
// Optionally add helpful npm scripts if a package.json exists
|
|
196
|
+
try {
|
|
197
|
+
const pkgPath = path.join(installDir, 'package.json');
|
|
198
|
+
if (await fileManager.pathExists(pkgPath)) {
|
|
199
|
+
const pkgRaw = await fileManager.readFile(pkgPath);
|
|
200
|
+
const pkg = JSON.parse(pkgRaw);
|
|
201
|
+
pkg.scripts = pkg.scripts || {};
|
|
202
|
+
const updated = { ...pkg.scripts };
|
|
203
|
+
if (!updated['bmad:refresh']) updated['bmad:refresh'] = 'bmad-method install -f -i codex';
|
|
204
|
+
if (!updated['bmad:list']) updated['bmad:list'] = 'bmad-method list:agents';
|
|
205
|
+
if (!updated['bmad:validate']) updated['bmad:validate'] = 'bmad-method validate';
|
|
206
|
+
const changed = JSON.stringify(updated) !== JSON.stringify(pkg.scripts);
|
|
207
|
+
if (changed) {
|
|
208
|
+
const newPkg = { ...pkg, scripts: updated };
|
|
209
|
+
await fileManager.writeFile(pkgPath, JSON.stringify(newPkg, null, 2) + '\n');
|
|
210
|
+
console.log(chalk.green('✓ Added npm scripts: bmad:refresh, bmad:list, bmad:validate'));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
} catch {
|
|
214
|
+
console.log(
|
|
215
|
+
chalk.yellow('⚠︎ Skipped adding npm scripts (package.json not writable or invalid)'),
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Adjust .gitignore behavior depending on Codex mode
|
|
220
|
+
try {
|
|
221
|
+
const gitignorePath = path.join(installDir, '.gitignore');
|
|
222
|
+
const ignoreLines = ['# BMAD (local only)', '.bmad-core/', '.bmad-*/'];
|
|
223
|
+
const exists = await fileManager.pathExists(gitignorePath);
|
|
224
|
+
if (options.webEnabled) {
|
|
225
|
+
if (exists) {
|
|
226
|
+
let gi = await fileManager.readFile(gitignorePath);
|
|
227
|
+
// Remove lines that ignore BMAD dot-folders
|
|
228
|
+
const updated = gi
|
|
229
|
+
.split(/\r?\n/)
|
|
230
|
+
.filter((l) => !/^\s*\.bmad-core\/?\s*$/.test(l) && !/^\s*\.bmad-\*\/?\s*$/.test(l))
|
|
231
|
+
.join('\n');
|
|
232
|
+
if (updated !== gi) {
|
|
233
|
+
await fileManager.writeFile(gitignorePath, updated.trimEnd() + '\n');
|
|
234
|
+
console.log(chalk.green('✓ Updated .gitignore to include .bmad-core in commits'));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
} else {
|
|
238
|
+
// Local-only: add ignores if missing
|
|
239
|
+
let base = exists ? await fileManager.readFile(gitignorePath) : '';
|
|
240
|
+
const haveCore = base.includes('.bmad-core/');
|
|
241
|
+
const haveStar = base.includes('.bmad-*/');
|
|
242
|
+
if (!haveCore || !haveStar) {
|
|
243
|
+
const sep = base.endsWith('\n') || base.length === 0 ? '' : '\n';
|
|
244
|
+
const add = [!haveCore || !haveStar ? ignoreLines.join('\n') : '']
|
|
245
|
+
.filter(Boolean)
|
|
246
|
+
.join('\n');
|
|
247
|
+
const out = base + sep + add + '\n';
|
|
248
|
+
await fileManager.writeFile(gitignorePath, out);
|
|
249
|
+
console.log(chalk.green('✓ Added .bmad-core/* to .gitignore for local-only Codex setup'));
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
} catch {
|
|
253
|
+
console.log(chalk.yellow('⚠︎ Could not update .gitignore (skipping)'));
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return true;
|
|
257
|
+
}
|
|
258
|
+
|
|
84
259
|
async setupCursor(installDir, selectedAgent) {
|
|
85
260
|
const cursorRulesDir = path.join(installDir, '.cursor', 'rules', 'bmad');
|
|
86
261
|
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
|
|
@@ -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."
|