bmad-method 4.33.1 → 4.35.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.
- package/CHANGELOG.md +14 -2
- package/README.md +1 -1
- package/bmad-core/user-guide.md +3 -3
- package/package.json +1 -1
- package/tools/installer/bin/bmad.js +3 -1
- package/tools/installer/config/install.config.yaml +22 -1
- package/tools/installer/lib/ide-setup.js +201 -2
- package/tools/installer/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
# [4.35.0](https://github.com/bmadcode/BMAD-METHOD/compare/v4.34.0...v4.35.0) (2025-08-04)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* add qwen-code ide support to bmad installer. ([#392](https://github.com/bmadcode/BMAD-METHOD/issues/392)) ([a72b790](https://github.com/bmadcode/BMAD-METHOD/commit/a72b790f3be6c77355511ace2d63e6bec4d751f1))
|
|
2
7
|
|
|
8
|
+
# [4.34.0](https://github.com/bmadcode/BMAD-METHOD/compare/v4.33.1...v4.34.0) (2025-08-03)
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
- add KiloCode integration support to BMAD installer ([#390](https://github.com/bmadcode/BMAD-METHOD/issues/390)) ([dcebe91](https://github.com/bmadcode/BMAD-METHOD/commit/dcebe91d5ea68e69aa27183411a81639d444efd7))
|
|
13
|
+
|
|
14
|
+
## [4.33.1](https://github.com/bmadcode/BMAD-METHOD/compare/v4.33.0...v4.33.1) (2025-07-29)
|
|
3
15
|
|
|
4
16
|
### Bug Fixes
|
|
5
17
|
|
|
6
|
-
|
|
18
|
+
- dev agent yaml syntax for develop-story command ([#362](https://github.com/bmadcode/BMAD-METHOD/issues/362)) ([bcb3728](https://github.com/bmadcode/BMAD-METHOD/commit/bcb3728f8868c0f83bca3d61fbd7e15c4e114526))
|
|
7
19
|
|
|
8
20
|
# [4.33.0](https://github.com/bmadcode/BMAD-METHOD/compare/v4.32.0...v4.33.0) (2025-07-28)
|
|
9
21
|
|
package/README.md
CHANGED
|
@@ -40,7 +40,7 @@ This two-phase approach eliminates both **planning inconsistency** and **context
|
|
|
40
40
|
|
|
41
41
|
- **[Install and Build software with Full Stack Agile AI Team](#quick-start)** → Quick Start Instruction
|
|
42
42
|
- **[Learn how to use BMad](bmad-core/user-guide.md)** → Complete user guide and walkthrough
|
|
43
|
-
- **[See available AI agents](
|
|
43
|
+
- **[See available AI agents](/bmad-core/agents))** → Specialized roles for your team
|
|
44
44
|
- **[Explore non-technical uses](#-beyond-software-development---expansion-packs)** → Creative writing, business, wellness, education
|
|
45
45
|
- **[Create my own AI agents](#creating-your-own-expansion-pack)** → Build agents for your domain
|
|
46
46
|
- **[Browse ready-made expansion packs](expansion-packs/)** → Game dev, DevOps, infrastructure and get inspired with ideas and examples
|
package/bmad-core/user-guide.md
CHANGED
|
@@ -85,9 +85,9 @@ Once planning is complete and documents are sharded, BMad follows a structured d
|
|
|
85
85
|
graph TD
|
|
86
86
|
A["Development Phase Start"] --> B["SM: Reviews Previous Story Dev/QA Notes"]
|
|
87
87
|
B --> B2["SM: Drafts Next Story from Sharded Epic + Architecture"]
|
|
88
|
-
B2 --> B3{"
|
|
89
|
-
B3 -->|
|
|
90
|
-
B3 -->|Skip
|
|
88
|
+
B2 --> B3{"PO: Validate Story Draft (Optional)"}
|
|
89
|
+
B3 -->|Validation Requested| B4["PO: Validate Story Against Artifacts"]
|
|
90
|
+
B3 -->|Skip Validation| C{"User Approval"}
|
|
91
91
|
B4 --> C
|
|
92
92
|
C -->|Approved| D["Dev: Sequential Task Execution"]
|
|
93
93
|
C -->|Needs Changes| B2
|
package/package.json
CHANGED
|
@@ -41,7 +41,7 @@ program
|
|
|
41
41
|
.option('-f, --full', 'Install complete BMad Method')
|
|
42
42
|
.option('-x, --expansion-only', 'Install only expansion packs (no bmad-core)')
|
|
43
43
|
.option('-d, --directory <path>', 'Installation directory')
|
|
44
|
-
.option('-i, --ide <ide...>', 'Configure for specific IDE(s) - can specify multiple (cursor, claude-code, windsurf, trae, roo, cline, gemini, github-copilot, other)')
|
|
44
|
+
.option('-i, --ide <ide...>', 'Configure for specific IDE(s) - can specify multiple (cursor, claude-code, windsurf, trae, roo, kilo, cline, gemini, qwen-code, github-copilot, other)')
|
|
45
45
|
.option('-e, --expansion-packs <packs...>', 'Install specific expansion packs (can specify multiple)')
|
|
46
46
|
.action(async (options) => {
|
|
47
47
|
try {
|
|
@@ -311,8 +311,10 @@ async function promptInstallation() {
|
|
|
311
311
|
{ name: 'Windsurf', value: 'windsurf' },
|
|
312
312
|
{ name: 'Trae', value: 'trae' }, // { name: 'Trae', value: 'trae'}
|
|
313
313
|
{ name: 'Roo Code', value: 'roo' },
|
|
314
|
+
{ name: 'Kilo Code', value: 'kilo' },
|
|
314
315
|
{ name: 'Cline', value: 'cline' },
|
|
315
316
|
{ name: 'Gemini CLI', value: 'gemini' },
|
|
317
|
+
{ name: 'Qwen Code', value: 'qwen-code' },
|
|
316
318
|
{ name: 'Github Copilot', value: 'github-copilot' }
|
|
317
319
|
]
|
|
318
320
|
}
|
|
@@ -89,4 +89,25 @@ ide-configurations:
|
|
|
89
89
|
# 3. The agent will adopt that persona for the conversation
|
|
90
90
|
# 4. Requires VS Code 1.101+ with `chat.agent.enabled: true` in settings
|
|
91
91
|
# 5. Agent files are stored in .github/chatmodes/
|
|
92
|
-
# 6. Use `*help` to see available commands and agents
|
|
92
|
+
# 6. Use `*help` to see available commands and agents
|
|
93
|
+
kilo:
|
|
94
|
+
name: Kilo Code
|
|
95
|
+
format: custom-modes
|
|
96
|
+
file: .kilocodemodes
|
|
97
|
+
instructions: |
|
|
98
|
+
# To use BMAD agents in Kilo Code:
|
|
99
|
+
# 1. Open the mode selector in VSCode
|
|
100
|
+
# 2. Select a bmad-{agent} mode (e.g. "bmad-dev")
|
|
101
|
+
# 3. The AI adopts that agent's persona and capabilities
|
|
102
|
+
|
|
103
|
+
qwen-code:
|
|
104
|
+
name: Qwen Code
|
|
105
|
+
rule-dir: .qwen/bmad-method/
|
|
106
|
+
format: single-file
|
|
107
|
+
command-suffix: .md
|
|
108
|
+
instructions: |
|
|
109
|
+
# To use BMad agents with Qwen Code:
|
|
110
|
+
# 1. The installer creates a .qwen/bmad-method/ directory in your project.
|
|
111
|
+
# 2. It concatenates all agent files into a single QWEN.md file.
|
|
112
|
+
# 3. Simply mention the agent in your prompt (e.g., "As *dev, ...").
|
|
113
|
+
# 4. The Qwen Code CLI will automatically have the context for that agent.
|
|
@@ -53,10 +53,14 @@ class IdeSetup extends BaseIdeSetup {
|
|
|
53
53
|
return this.setupRoo(installDir, selectedAgent);
|
|
54
54
|
case "cline":
|
|
55
55
|
return this.setupCline(installDir, selectedAgent);
|
|
56
|
+
case "kilo":
|
|
57
|
+
return this.setupKilocode(installDir, selectedAgent);
|
|
56
58
|
case "gemini":
|
|
57
59
|
return this.setupGeminiCli(installDir, selectedAgent);
|
|
58
60
|
case "github-copilot":
|
|
59
61
|
return this.setupGitHubCopilot(installDir, selectedAgent, spinner, preConfiguredSettings);
|
|
62
|
+
case "qwen-code":
|
|
63
|
+
return this.setupQwenCode(installDir, selectedAgent);
|
|
60
64
|
default:
|
|
61
65
|
console.log(chalk.yellow(`\nIDE ${ide} not yet supported`));
|
|
62
66
|
return false;
|
|
@@ -675,11 +679,17 @@ class IdeSetup extends BaseIdeSetup {
|
|
|
675
679
|
? roleDefinitionMatch[1].trim()
|
|
676
680
|
: `You are a ${title} specializing in ${title.toLowerCase()} tasks and responsibilities.`;
|
|
677
681
|
|
|
682
|
+
|
|
683
|
+
// Add permissions based on agent type
|
|
684
|
+
const permissions = agentPermissions[agentId];
|
|
678
685
|
// Build mode entry with proper formatting (matching exact indentation)
|
|
679
686
|
// Avoid double "bmad-" prefix for agents that already have it
|
|
680
687
|
const slug = agentId.startsWith('bmad-') ? agentId : `bmad-${agentId}`;
|
|
681
688
|
newModesContent += ` - slug: ${slug}\n`;
|
|
682
689
|
newModesContent += ` name: '${icon} ${title}'\n`;
|
|
690
|
+
if (permissions) {
|
|
691
|
+
newModesContent += ` description: '${permissions.description}'\n`;
|
|
692
|
+
}
|
|
683
693
|
newModesContent += ` roleDefinition: ${roleDefinition}\n`;
|
|
684
694
|
newModesContent += ` whenToUse: ${whenToUse}\n`;
|
|
685
695
|
// Get relative path from installDir to agent file
|
|
@@ -688,8 +698,6 @@ class IdeSetup extends BaseIdeSetup {
|
|
|
688
698
|
newModesContent += ` groups:\n`;
|
|
689
699
|
newModesContent += ` - read\n`;
|
|
690
700
|
|
|
691
|
-
// Add permissions based on agent type
|
|
692
|
-
const permissions = agentPermissions[agentId];
|
|
693
701
|
if (permissions) {
|
|
694
702
|
newModesContent += ` - - edit\n`;
|
|
695
703
|
newModesContent += ` - fileRegex: ${permissions.fileRegex}\n`;
|
|
@@ -722,7 +730,98 @@ class IdeSetup extends BaseIdeSetup {
|
|
|
722
730
|
|
|
723
731
|
return true;
|
|
724
732
|
}
|
|
733
|
+
|
|
734
|
+
async setupKilocode(installDir, selectedAgent) {
|
|
735
|
+
const filePath = path.join(installDir, ".kilocodemodes");
|
|
736
|
+
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
|
|
737
|
+
|
|
738
|
+
let existingModes = [], existingContent = "";
|
|
739
|
+
if (await fileManager.pathExists(filePath)) {
|
|
740
|
+
existingContent = await fileManager.readFile(filePath);
|
|
741
|
+
for (const match of existingContent.matchAll(/- slug: ([\w-]+)/g)) {
|
|
742
|
+
existingModes.push(match[1]);
|
|
743
|
+
}
|
|
744
|
+
console.log(chalk.yellow(`Found existing .kilocodemodes file with ${existingModes.length} modes`));
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
const config = await this.loadIdeAgentConfig();
|
|
748
|
+
const permissions = config['roo-permissions'] || {}; // reuse same roo permissions block (Kilo Code understands same mode schema)
|
|
749
|
+
|
|
750
|
+
let newContent = "";
|
|
751
|
+
|
|
752
|
+
for (const agentId of agents) {
|
|
753
|
+
const slug = agentId.startsWith('bmad-') ? agentId : `bmad-${agentId}`;
|
|
754
|
+
if (existingModes.includes(slug)) {
|
|
755
|
+
console.log(chalk.dim(`Skipping ${agentId} - already exists in .kilocodemodes`));
|
|
756
|
+
continue;
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
const agentPath = await this.findAgentPath(agentId, installDir);
|
|
760
|
+
if (!agentPath) {
|
|
761
|
+
console.log(chalk.red(`✗ Could not find agent file for ${agentId}`));
|
|
762
|
+
continue;
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
const agentContent = await fileManager.readFile(agentPath);
|
|
766
|
+
const yamlMatch = agentContent.match(/```ya?ml\r?\n([\s\S]*?)```/);
|
|
767
|
+
if (!yamlMatch) {
|
|
768
|
+
console.log(chalk.red(`✗ Could not extract YAML block for ${agentId}`));
|
|
769
|
+
continue;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
const yaml = yamlMatch[1];
|
|
773
|
+
|
|
774
|
+
// Robust fallback for title and icon
|
|
775
|
+
const title = (yaml.match(/title:\s*(.+)/)?.[1]?.trim()) || await this.getAgentTitle(agentId, installDir);
|
|
776
|
+
const icon = (yaml.match(/icon:\s*(.+)/)?.[1]?.trim()) || '🤖';
|
|
777
|
+
const whenToUse = (yaml.match(/whenToUse:\s*"(.+)"/)?.[1]?.trim()) || `Use for ${title} tasks`;
|
|
778
|
+
const roleDefinition = (yaml.match(/roleDefinition:\s*"(.+)"/)?.[1]?.trim()) ||
|
|
779
|
+
`You are a ${title} specializing in ${title.toLowerCase()} tasks and responsibilities.`;
|
|
780
|
+
|
|
781
|
+
const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
|
|
782
|
+
const customInstructions = `CRITICAL Read the full YAML from ${relativePath} start activation to alter your state of being follow startup section instructions stay in this being until told to exit this mode`;
|
|
783
|
+
|
|
784
|
+
// Add permissions from config if they exist
|
|
785
|
+
const agentPermission = permissions[agentId];
|
|
786
|
+
|
|
787
|
+
// Begin .kilocodemodes block
|
|
788
|
+
newContent += ` - slug: ${slug}\n`;
|
|
789
|
+
newContent += ` name: '${icon} ${title}'\n`;
|
|
790
|
+
if (agentPermission) {
|
|
791
|
+
newContent += ` description: '${agentPermission.description}'\n`;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
newContent += ` roleDefinition: ${roleDefinition}\n`;
|
|
795
|
+
newContent += ` whenToUse: ${whenToUse}\n`;
|
|
796
|
+
newContent += ` customInstructions: ${customInstructions}\n`;
|
|
797
|
+
newContent += ` groups:\n`;
|
|
798
|
+
newContent += ` - read\n`;
|
|
725
799
|
|
|
800
|
+
|
|
801
|
+
if (agentPermission) {
|
|
802
|
+
newContent += ` - - edit\n`;
|
|
803
|
+
newContent += ` - fileRegex: ${agentPermission.fileRegex}\n`;
|
|
804
|
+
newContent += ` description: ${agentPermission.description}\n`;
|
|
805
|
+
} else {
|
|
806
|
+
// Fallback to generic edit
|
|
807
|
+
newContent += ` - edit\n`;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
console.log(chalk.green(`✓ Added Kilo mode: ${slug} (${icon} ${title})`));
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
const finalContent = existingContent
|
|
814
|
+
? existingContent.trim() + "\n" + newContent
|
|
815
|
+
: "customModes:\n" + newContent;
|
|
816
|
+
|
|
817
|
+
await fileManager.writeFile(filePath, finalContent);
|
|
818
|
+
console.log(chalk.green("✓ Created .kilocodemodes file in project root"));
|
|
819
|
+
console.log(chalk.green(`✓ KiloCode setup complete!`));
|
|
820
|
+
console.log(chalk.dim("Custom modes will be available when you open this project in KiloCode"));
|
|
821
|
+
|
|
822
|
+
return true;
|
|
823
|
+
}
|
|
824
|
+
|
|
726
825
|
async setupCline(installDir, selectedAgent) {
|
|
727
826
|
const clineRulesDir = path.join(installDir, ".clinerules");
|
|
728
827
|
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
|
|
@@ -880,6 +979,106 @@ class IdeSetup extends BaseIdeSetup {
|
|
|
880
979
|
return true;
|
|
881
980
|
}
|
|
882
981
|
|
|
982
|
+
async setupQwenCode(installDir, selectedAgent) {
|
|
983
|
+
const qwenDir = path.join(installDir, ".qwen");
|
|
984
|
+
const bmadMethodDir = path.join(qwenDir, "bmad-method");
|
|
985
|
+
await fileManager.ensureDirectory(bmadMethodDir);
|
|
986
|
+
|
|
987
|
+
// Update logic for existing settings.json
|
|
988
|
+
const settingsPath = path.join(qwenDir, "settings.json");
|
|
989
|
+
if (await fileManager.pathExists(settingsPath)) {
|
|
990
|
+
try {
|
|
991
|
+
const settingsContent = await fileManager.readFile(settingsPath);
|
|
992
|
+
const settings = JSON.parse(settingsContent);
|
|
993
|
+
let updated = false;
|
|
994
|
+
|
|
995
|
+
// Handle contextFileName property
|
|
996
|
+
if (settings.contextFileName && Array.isArray(settings.contextFileName)) {
|
|
997
|
+
const originalLength = settings.contextFileName.length;
|
|
998
|
+
settings.contextFileName = settings.contextFileName.filter(
|
|
999
|
+
(fileName) => !fileName.startsWith("agents/")
|
|
1000
|
+
);
|
|
1001
|
+
if (settings.contextFileName.length !== originalLength) {
|
|
1002
|
+
updated = true;
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
if (updated) {
|
|
1007
|
+
await fileManager.writeFile(
|
|
1008
|
+
settingsPath,
|
|
1009
|
+
JSON.stringify(settings, null, 2)
|
|
1010
|
+
);
|
|
1011
|
+
console.log(chalk.green("✓ Updated .qwen/settings.json - removed agent file references"));
|
|
1012
|
+
}
|
|
1013
|
+
} catch (error) {
|
|
1014
|
+
console.warn(
|
|
1015
|
+
chalk.yellow("Could not update .qwen/settings.json"),
|
|
1016
|
+
error
|
|
1017
|
+
);
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
// Remove old agents directory
|
|
1022
|
+
const agentsDir = path.join(qwenDir, "agents");
|
|
1023
|
+
if (await fileManager.pathExists(agentsDir)) {
|
|
1024
|
+
await fileManager.removeDirectory(agentsDir);
|
|
1025
|
+
console.log(chalk.green("✓ Removed old .qwen/agents directory"));
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// Get all available agents
|
|
1029
|
+
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
|
|
1030
|
+
let concatenatedContent = "";
|
|
1031
|
+
|
|
1032
|
+
for (const agentId of agents) {
|
|
1033
|
+
// Find the source agent file
|
|
1034
|
+
const agentPath = await this.findAgentPath(agentId, installDir);
|
|
1035
|
+
|
|
1036
|
+
if (agentPath) {
|
|
1037
|
+
const agentContent = await fileManager.readFile(agentPath);
|
|
1038
|
+
|
|
1039
|
+
// Create properly formatted agent rule content (similar to gemini)
|
|
1040
|
+
let agentRuleContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
|
|
1041
|
+
agentRuleContent += `This rule is triggered when the user types \`*${agentId}\` and activates the ${await this.getAgentTitle(
|
|
1042
|
+
agentId,
|
|
1043
|
+
installDir
|
|
1044
|
+
)} agent persona.\n\n`;
|
|
1045
|
+
agentRuleContent += "## Agent Activation\n\n";
|
|
1046
|
+
agentRuleContent +=
|
|
1047
|
+
"CRITICAL: Read the full YAML, start activation to alter your state of being, follow startup section instructions, stay in this being until told to exit this mode:\n\n";
|
|
1048
|
+
agentRuleContent += "```yaml\n";
|
|
1049
|
+
// Extract just the YAML content from the agent file
|
|
1050
|
+
const yamlContent = extractYamlFromAgent(agentContent);
|
|
1051
|
+
if (yamlContent) {
|
|
1052
|
+
agentRuleContent += yamlContent;
|
|
1053
|
+
}
|
|
1054
|
+
else {
|
|
1055
|
+
// If no YAML found, include the whole content minus the header
|
|
1056
|
+
agentRuleContent += agentContent.replace(/^#.*$/m, "").trim();
|
|
1057
|
+
}
|
|
1058
|
+
agentRuleContent += "\n```\n\n";
|
|
1059
|
+
agentRuleContent += "## File Reference\n\n";
|
|
1060
|
+
const relativePath = path.relative(installDir, agentPath).replace(/\\/g, '/');
|
|
1061
|
+
agentRuleContent += `The complete agent definition is available in [${relativePath}](${relativePath}).\n\n`;
|
|
1062
|
+
agentRuleContent += "## Usage\n\n";
|
|
1063
|
+
agentRuleContent += `When the user types \`*${agentId}\`, activate this ${await this.getAgentTitle(
|
|
1064
|
+
agentId,
|
|
1065
|
+
installDir
|
|
1066
|
+
)} persona and follow all instructions defined in the YAML configuration above.\n`;
|
|
1067
|
+
|
|
1068
|
+
// Add to concatenated content with separator
|
|
1069
|
+
concatenatedContent += agentRuleContent + "\n\n---\n\n";
|
|
1070
|
+
console.log(chalk.green(`✓ Added context for *${agentId}`));
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
// Write the concatenated content to QWEN.md
|
|
1075
|
+
const qwenMdPath = path.join(bmadMethodDir, "QWEN.md");
|
|
1076
|
+
await fileManager.writeFile(qwenMdPath, concatenatedContent);
|
|
1077
|
+
console.log(chalk.green(`\n✓ Created QWEN.md in ${bmadMethodDir}`));
|
|
1078
|
+
|
|
1079
|
+
return true;
|
|
1080
|
+
}
|
|
1081
|
+
|
|
883
1082
|
async setupGitHubCopilot(installDir, selectedAgent, spinner = null, preConfiguredSettings = null) {
|
|
884
1083
|
// Configure VS Code workspace settings first to avoid UI conflicts with loading spinners
|
|
885
1084
|
await this.configureVsCodeSettings(installDir, spinner, preConfiguredSettings);
|