Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
blank_issues_enabled: false

Check failure on line 1 in .github/ISSUE_TEMPLATE/config.yml

View workflow job for this annotation

GitHub Actions / validate

Expected extension '.yaml' but used extension '.yml'

Check failure on line 1 in .github/ISSUE_TEMPLATE/config.yml

View workflow job for this annotation

GitHub Actions / eslint

Expected extension '.yaml' but used extension '.yml'
contact_links:
- name: Discord Community Support
url: https://discord.gg/gk8jAdXWmj
about: Please join our Discord server for general questions and community discussion before opening an issue.
2 changes: 1 addition & 1 deletion .github/workflows/manual-release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
token: ${{ secrets.GH_PAT }}

- name: Setup Node.js
uses: actions/setup-node@v4
Expand Down
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
# BMAD-METHOD™: Universal AI Agent Framework

> ## 🚨 **IMPORTANT VERSION ANNOUNCEMENT** 🚨
>
> ### Current Stable: v4.x | Next Major: v6 Alpha
>
> - **v4.x** - The current stable release version available via npm
> - **v5** - Skipped (replaced by v6)
> - **[v6-alpha](https://github.com/bmad-code-org/BMAD-METHOD/tree/v6-alpha)** - **NOW AVAILABLE FOR EARLY TESTING!**
>
> ### 🧪 Try v6 Alpha (Early Adopters Only)
>
> The next major version of BMAD-METHOD is now available for early experimentation and testing. This is a complete rewrite with significant architectural changes.
>
> **⚠️ WARNING: v6-alpha is for early adopters who are comfortable with:**
>
> - Potential breaking changes
> - Daily updates and instability
> - Incomplete features
> - Experimental functionality
>
> **📅 Timeline:** Official beta version will be merged mid-October 2025
>
> **To try v6-alpha:**
>
> ```bash
> git clone https://github.com/bmad-code-org/BMAD-METHOD.git
> cd BMAD-METHOD
> git checkout v6-alpha
> ```
>
> ---

[![Version](https://img.shields.io/npm/v/bmad-method?color=blue&label=version)](https://www.npmjs.com/package/bmad-method)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Node.js Version](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen)](https://nodejs.org)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/package.json",
"name": "bmad-method",
"version": "4.43.0",
"version": "4.44.0",
"description": "Breakthrough Method of Agile AI-driven Development",
"keywords": [
"agile",
Expand Down
3 changes: 2 additions & 1 deletion tools/installer/bin/bmad.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ program
.option('-d, --directory <path>', 'Installation directory')
.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, codex, codex-web, auggie-cli, iflow-cli, opencode, other)',
'Configure for specific IDE(s) - can specify multiple (cursor, claude-code, windsurf, trae, roo, kilo, kiro, cline, gemini, qwen-code, github-copilot, codex, codex-web, auggie-cli, iflow-cli, opencode, other)',
)
.option(
'-e, --expansion-packs <packs...>',
Expand Down Expand Up @@ -402,6 +402,7 @@ async function promptInstallation() {
{ name: 'Trae', value: 'trae' }, // { name: 'Trae', value: 'trae'}
{ name: 'Roo Code', value: 'roo' },
{ name: 'Kilo Code', value: 'kilo' },
{ name: 'Kiro IDE', value: 'kiro' },
{ name: 'Cline', value: 'cline' },
{ name: 'Gemini CLI', value: 'gemini' },
{ name: 'Qwen Code', value: 'qwen-code' },
Expand Down
24 changes: 17 additions & 7 deletions tools/installer/config/install.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ installation-options:
description: Select and install a single agent with its dependencies
action: copy-agent
ide-configurations:
kiro:
name: Kiro IDE
rule-dir: .kiro/steering/
format: multi-file
command-suffix: .md
instructions: |
# To use BMad agents in Kiro IDE:
# 1. The installer creates agent files in `.kiro/steering/`.
# 2. The steering file `bmad.md` is always included.
# 3. Type *agent-name (e.g., "*agent-dev", "*agent-pm") to activate the agent.
cursor:
name: Cursor
rule-dir: .cursor/rules/bmad/
Expand Down Expand Up @@ -121,15 +131,15 @@ ide-configurations:

qwen-code:
name: Qwen Code
rule-dir: .qwen/bmad-method/
format: single-file
command-suffix: .md
rule-dir: .qwen/commands/BMad/
format: multi-file
command-suffix: .toml
instructions: |
# To use BMad agents with Qwen Code:
# 1. The installer creates a .qwen/bmad-method/ directory in your project.
# 2. It concatenates all agent files into a single QWEN.md file.
# 3. Simply mention the agent in your prompt (e.g., "As *dev, ...").
# 4. The Qwen Code CLI will automatically have the context for that agent.
# 1. The installer creates a `BMad` folder in `.qwen/commands`.
# 2. This adds custom commands for each agent and task.
# 3. Type /BMad:agents:<agent-name> (e.g., "/BMad:agents:dev", "/BMad:agents:pm") or /BMad:tasks:<task-name> (e.g., "/BMad:tasks:create-doc").
# 4. The agent will adopt that persona for the conversation or perform the task.

auggie-cli:
name: Auggie CLI (Augment Code)
Expand Down
177 changes: 101 additions & 76 deletions tools/installer/lib/ide-setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ class IdeSetup extends BaseIdeSetup {
case 'cline': {
return this.setupCline(installDir, selectedAgent);
}
case 'kiro': {
return this.setupKiro(installDir, selectedAgent);
}
case 'kilo': {
return this.setupKilocode(installDir, selectedAgent);
}
Expand Down Expand Up @@ -1391,6 +1394,36 @@ class IdeSetup extends BaseIdeSetup {
}
}

async setupKiro(installDir, selectedAgent) {
const kiroSteeringDir = path.join(installDir, '.kiro', 'steering');
await fileManager.ensureDirectory(kiroSteeringDir);

// Get all agent IDs
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
const agentLinks = [];

for (const agentId of agents) {
// Find the agent file
const agentPath = await this.findAgentPath(agentId, installDir);
if (agentPath) {
const agentContent = await fileManager.readFile(agentPath);
const mdPath = path.join(kiroSteeringDir, `${agentId}.md`);
await fileManager.writeFile(mdPath, agentContent);
agentLinks.push(`- [*agent-${agentId}](./${agentId}.md)`);
console.log(chalk.green(`✓ Created steering file: ${agentId}.md`));
}
}

// Create bmad-method.md and readme.md with inclusion header and agent links
const inclusionHeader = '---\ninclusion: always\n---\n';
const intro =
"i'll open the next file that is under the .kiro/steering/ dir based on the user's input file name\n";
const content = `${inclusionHeader}\n${intro}\n${agentLinks.join('\n')}\n`;
await fileManager.writeFile(path.join(kiroSteeringDir, 'bmad.md'), content);
console.log(chalk.green('✓ Created bmad.md for Kiro steering.'));
return true;
}

async findAgentPath(agentId, installDir) {
// Try to find the agent file in various locations
const possiblePaths = [
Expand Down Expand Up @@ -2056,94 +2089,86 @@ CRITICAL: You are to execute the BMad Task defined below.
}

async setupQwenCode(installDir, selectedAgent) {
const qwenDir = path.join(installDir, '.qwen');
const bmadMethodDir = path.join(qwenDir, 'bmad-method');
await fileManager.ensureDirectory(bmadMethodDir);
const ideConfig = await configLoader.getIdeConfiguration('qwen-code');
const bmadCommandsDir = path.join(installDir, ideConfig['rule-dir']);

// Update logic for existing settings.json
const settingsPath = path.join(qwenDir, 'settings.json');
if (await fileManager.pathExists(settingsPath)) {
try {
const settingsContent = await fileManager.readFile(settingsPath);
const settings = JSON.parse(settingsContent);
let updated = false;

// Handle contextFileName property
if (settings.contextFileName && Array.isArray(settings.contextFileName)) {
const originalLength = settings.contextFileName.length;
settings.contextFileName = settings.contextFileName.filter(
(fileName) => !fileName.startsWith('agents/'),
);
if (settings.contextFileName.length !== originalLength) {
updated = true;
}
}
const agentCommandsDir = path.join(bmadCommandsDir, 'agents');
const taskCommandsDir = path.join(bmadCommandsDir, 'tasks');
await fileManager.ensureDirectory(agentCommandsDir);
await fileManager.ensureDirectory(taskCommandsDir);

if (updated) {
await fileManager.writeFile(settingsPath, JSON.stringify(settings, null, 2));
console.log(chalk.green('✓ Updated .qwen/settings.json - removed agent file references'));
}
} catch (error) {
console.warn(chalk.yellow('Could not update .qwen/settings.json'), error);
// Process Agents
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
for (const agentId of agents) {
const agentPath = await this.findAgentPath(agentId, installDir);
if (!agentPath) {
console.log(chalk.yellow(`✗ Agent file not found for ${agentId}, skipping.`));
continue;
}
}

// Remove old agents directory
const agentsDir = path.join(qwenDir, 'agents');
if (await fileManager.pathExists(agentsDir)) {
await fileManager.removeDirectory(agentsDir);
console.log(chalk.green('✓ Removed old .qwen/agents directory'));
}
const agentTitle = await this.getAgentTitle(agentId, installDir);
const commandPath = path.join(agentCommandsDir, `${agentId}.toml`);

// Get all available agents
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
let concatenatedContent = '';
// Get relative path from installDir to agent file for @{file} reference
const relativeAgentPath = path.relative(installDir, agentPath).replaceAll('\\', '/');

for (const agentId of agents) {
// Find the source agent file
const agentPath = await this.findAgentPath(agentId, installDir);
// Read the agent content
const agentContent = await fileManager.readFile(agentPath);

if (agentPath) {
const agentContent = await fileManager.readFile(agentPath);
const tomlContent = `description = " Activates the ${agentTitle} agent from the BMad Method."
prompt = """
CRITICAL: You are now the BMad '${agentTitle}' agent. Adopt its persona, follow its instructions, and use its capabilities.

// Create properly formatted agent rule content (similar to gemini)
let agentRuleContent = `# ${agentId.toUpperCase()} Agent Rule\n\n`;
agentRuleContent += `This rule is triggered when the user types \`*${agentId}\` and activates the ${await this.getAgentTitle(
agentId,
installDir,
)} agent persona.\n\n`;
agentRuleContent += '## Agent Activation\n\n';
agentRuleContent +=
'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';
agentRuleContent += '```yaml\n';
// Extract just the YAML content from the agent file
const yamlContent = extractYamlFromAgent(agentContent);
if (yamlContent) {
agentRuleContent += yamlContent;
} else {
// If no YAML found, include the whole content minus the header
agentRuleContent += agentContent.replace(/^#.*$/m, '').trim();
}
agentRuleContent += '\n```\n\n';
agentRuleContent += '## File Reference\n\n';
const relativePath = path.relative(installDir, agentPath).replaceAll('\\', '/');
agentRuleContent += `The complete agent definition is available in [${relativePath}](${relativePath}).\n\n`;
agentRuleContent += '## Usage\n\n';
agentRuleContent += `When the user types \`*${agentId}\`, activate this ${await this.getAgentTitle(
agentId,
installDir,
)} persona and follow all instructions defined in the YAML configuration above.\n`;
READ THIS BEFORE ANSWERING AS THE PERSONA!

// Add to concatenated content with separator
concatenatedContent += agentRuleContent + '\n\n---\n\n';
console.log(chalk.green(`✓ Added context for *${agentId}`));
${agentContent}
"""`;

await fileManager.writeFile(commandPath, tomlContent);
console.log(chalk.green(`✓ Created agent command: /bmad:agents:${agentId}`));
}

// Process Tasks
const tasks = await this.getAllTaskIds(installDir);
for (const taskId of tasks) {
const taskPath = await this.findTaskPath(taskId, installDir);
if (!taskPath) {
console.log(chalk.yellow(`✗ Task file not found for ${taskId}, skipping.`));
continue;
}

const taskTitle = taskId
.split('-')
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
const commandPath = path.join(taskCommandsDir, `${taskId}.toml`);

// Get relative path from installDir to task file for @{file} reference
const relativeTaskPath = path.relative(installDir, taskPath).replaceAll('\\', '/');

// Read the task content
const taskContent = await fileManager.readFile(taskPath);

const tomlContent = `description = " Executes the BMad Task: ${taskTitle}"
prompt = """
CRITICAL: You are to execute the BMad Task defined below.

READ THIS BEFORE EXECUTING THE TASK AS THE INSTRUCTIONS SPECIFIED!

${taskContent}
"""`;

await fileManager.writeFile(commandPath, tomlContent);
console.log(chalk.green(`✓ Created task command: /bmad:tasks:${taskId}`));
}

// Write the concatenated content to QWEN.md
const qwenMdPath = path.join(bmadMethodDir, 'QWEN.md');
await fileManager.writeFile(qwenMdPath, concatenatedContent);
console.log(chalk.green(`\n✓ Created QWEN.md in ${bmadMethodDir}`));
console.log(
chalk.green(`
✓ Created Qwen Code extension in ${bmadCommandsDir}`),
);
console.log(
chalk.dim('You can now use commands like /bmad:agents:dev or /bmad:tasks:create-doc.'),
);

return true;
}
Expand Down
Loading