Compare commits

...

7 Commits

Author SHA1 Message Date
murat
9260a65baa fix: tea relative links 2026-01-28 08:52:47 -06:00
Brian Madison
dd8c54cc9f no double agent files and .agent.md file extensions. 2026-01-27 23:08:26 -08:00
Brian Madison
4ded43d707 fix paths in prd edit flow 2026-01-27 22:03:53 -08:00
Davor Racic
181aeac04a fix(ide): add support for Gemini CLI TOML format (#1431)
* fix(ide): add support for Gemini CLI TOML format

* fix(ide): Added normalization for config.extension, added .yml to the extension array

---------

Co-authored-by: Brian <bmadcode@gmail.com>
2026-01-27 21:56:12 -08:00
Murat K Ozcan
f7466c2530 feat: added tea module as an external module (#1430) 2026-01-27 17:29:34 -08:00
The Chef
7d3d51ff4f docs: fix typos in README and customization guide (#1424)
- Remove duplicate "for" in README example command
- Fix "this is" to "thing is" in README
- Remove extra "at" in "star project icon at near" in README
- Fix "MEthod" to "Method" in customize-bmad.md
2026-01-26 23:25:08 -08:00
Vladimir Hrusovsky
4c92e0cc88 Fix: Correct workflow_path in bmad-quick-flow/quick-spec steps (#1368)
- Fix workflow_path in step-01-understand.md, step-02-investigate.md, and step-03-generate.md
- Changed from non-existent 'create-tech-spec' to correct 'quick-spec'
- Aligns with step-04-review.md which already had correct path

Co-authored-by: Your Name <you@example.com>
Co-authored-by: Brian <bmadcode@gmail.com>
2026-01-26 23:15:22 -08:00
25 changed files with 249 additions and 199 deletions

View File

@@ -32,10 +32,10 @@ Follow the installer prompts, then open your AI IDE (Claude Code, Cursor, Windsu
> **Not sure what to do?** Run `/bmad-help` — it tells you exactly what's next and what's optional. You can also ask it questions like:
- `/bmad-help How should I build a web app for for my TShirt Business that can scale to millions?`
- `/bmad-help How should I build a web app for my TShirt Business that can scale to millions?`
- `/bmad-help I just finished the architecture, I am not sure what to do next`
And the amazing this is BMad Help evolves depending on what modules you install also!
And the amazing thing is BMad Help evolves depending on what modules you install also!
- `/bmad-help Im interested in really exploring creative ways to demo BMad at work, what do you recommend to help plan a great slide deck and compelling narrative?`, and if you have the Creative Intelligence Suite installed, it will offer you different or complimentary advice than if you just have BMad Method Module installed!
The workflows below show the fastest path to working code. You can also load agents directly for a more structured process, extensive planning, or to learn about agile development practices — the agents guide you with menus, explanations, and elicitation at each step.
@@ -96,7 +96,7 @@ BMad Method extends with official modules for specialized domains. Modules are a
BMad is free for everyone — and always will be. If you'd like to support development:
- ⭐ Please click the star project icon at near the top right of this page
- ⭐ Please click the star project icon near the top right of this page
- ☕ [Buy Me a Coffee](https://buymeacoffee.com/bmad) — Fuel the development
- 🏢 Corporate sponsorship — DM on Discord
- 🎤 Speaking & Media — Available for conferences, podcasts, interviews (BM on Discord)

View File

@@ -151,7 +151,7 @@ prompts:
## Workflow Customization
Information about customizing existing BMad MEthod workflows and skills are coming soon.
Information about customizing existing BMad Method workflows and skills are coming soon.
## Module Customization

View File

@@ -4,7 +4,7 @@ description: 'Discovery & Understanding - Understand what user wants to edit and
# File references (ONLY variables used in this step)
altStepFile: './step-e-01b-legacy-conversion.md'
prdPurpose: '{project-root}/src/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md'
prdPurpose: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md'
advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml'
partyModeWorkflow: '{project-root}/_bmad/core/workflows/party-mode/workflow.md'
---

View File

@@ -5,7 +5,7 @@ description: 'Legacy PRD Conversion Assessment - Analyze legacy PRD and propose
# File references (ONLY variables used in this step)
nextStepFile: './step-e-02-review.md'
prdFile: '{prd_file_path}'
prdPurpose: '{project-root}/src/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md'
prdPurpose: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md'
---
# Step E-1B: Legacy PRD Conversion Assessment

View File

@@ -6,7 +6,7 @@ description: 'Deep Review & Analysis - Thoroughly review existing PRD and prepar
nextStepFile: './step-e-03-edit.md'
prdFile: '{prd_file_path}'
validationReport: '{validation_report_path}' # If provided
prdPurpose: '{project-root}/src/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md'
prdPurpose: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md'
advancedElicitationTask: '{project-root}/_bmad/core/workflows/advanced-elicitation/workflow.xml'
---

View File

@@ -5,7 +5,7 @@ description: 'Edit & Update - Apply changes to PRD following approved change pla
# File references (ONLY variables used in this step)
nextStepFile: './step-e-04-complete.md'
prdFile: '{prd_file_path}'
prdPurpose: '{project-root}/src/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md'
prdPurpose: '{project-root}/_bmad/bmm/workflows/2-plan-workflows/create-prd/data/prd-purpose.md'
---
# Step E-3: Edit & Update

View File

@@ -2,7 +2,7 @@
name: 'step-01-understand'
description: 'Analyze the requirement delta between current state and what user wants to build'
workflow_path: '{project-root}/_bmad/bmm/workflows/bmad-quick-flow/create-tech-spec'
workflow_path: '{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-spec'
nextStepFile: './step-02-investigate.md'
skipToStepFile: './step-03-generate.md'
templateFile: '{workflow_path}/tech-spec-template.md'

View File

@@ -2,7 +2,7 @@
name: 'step-02-investigate'
description: 'Map technical constraints and anchor points within the codebase'
workflow_path: '{project-root}/_bmad/bmm/workflows/bmad-quick-flow/create-tech-spec'
workflow_path: '{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-spec'
nextStepFile: './step-03-generate.md'
wipFile: '{implementation_artifacts}/tech-spec-wip.md'
---

View File

@@ -2,7 +2,7 @@
name: 'step-03-generate'
description: 'Build the implementation plan based on the technical mapping of constraints'
workflow_path: '{project-root}/_bmad/bmm/workflows/bmad-quick-flow/create-tech-spec'
workflow_path: '{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-spec'
nextStepFile: './step-04-review.md'
wipFile: '{implementation_artifacts}/tech-spec-wip.md'
---

View File

@@ -25,7 +25,7 @@ variables:
# Directory paths
test_dir: "{project-root}/tests" # Root test directory
source_dir: "{project-root}/src" # Source code directory
source_dir: "{project-root}" # Source code directory (customize if needed, e.g., {project-root}/src or {project-root}/lib)
# Output configuration
default_output_file: "{output_folder}/automation-summary.md"

View File

@@ -21,7 +21,7 @@ template: "{installed_path}/trace-template.md"
variables:
# Directory paths
test_dir: "{project-root}/tests" # Root test directory
source_dir: "{project-root}/src" # Source code directory
source_dir: "{project-root}" # Source code directory (customize if needed, e.g., {project-root}/src or {project-root}/lib)
# Workflow behavior
coverage_levels: "e2e,api,component,unit" # Which test levels to trace

View File

@@ -32,6 +32,16 @@ modules:
type: bmad-org
npmPackage: bmad-game-dev-studio
bmad-method-test-architecture-enterprise:
url: https://github.com/bmad-code-org/bmad-method-test-architecture-enterprise
module-definition: src/module.yaml
code: tea
name: "Test Architect"
description: "Master Test Architect for quality strategy, test automation, and release gates"
defaultSelected: false
type: bmad-org
npmPackage: bmad-method-test-architecture-enterprise
# TODO: Enable once fixes applied:
# whiteport-design-system:

View File

@@ -132,12 +132,12 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup {
*/
async writeAgentArtifacts(targetPath, artifacts, templateType, config = {}) {
// Try to load platform-specific template, fall back to default-agent
const template = await this.loadTemplate(templateType, 'agent', config, 'default-agent');
const { content: template, extension } = await this.loadTemplate(templateType, 'agent', config, 'default-agent');
let count = 0;
for (const artifact of artifacts) {
const content = this.renderTemplate(template, artifact);
const filename = this.generateFilename(artifact, 'agent');
const filename = this.generateFilename(artifact, 'agent', extension);
const filePath = path.join(targetPath, filename);
await this.writeFile(filePath, content);
count++;
@@ -167,9 +167,10 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup {
// Fall back to default templates if specific ones don't exist
const finalTemplateType = artifact.isYamlWorkflow ? 'default-workflow-yaml' : 'default-workflow';
const template = await this.loadTemplate(workflowTemplateType, 'workflow', config, finalTemplateType);
// workflowTemplateType already contains full name (e.g., 'gemini-workflow-yaml'), so pass empty artifactType
const { content: template, extension } = await this.loadTemplate(workflowTemplateType, '', config, finalTemplateType);
const content = this.renderTemplate(template, artifact);
const filename = this.generateFilename(artifact, 'workflow');
const filename = this.generateFilename(artifact, 'workflow', extension);
const filePath = path.join(targetPath, filename);
await this.writeFile(filePath, content);
count++;
@@ -185,34 +186,47 @@ class ConfigDrivenIdeSetup extends BaseIdeSetup {
* @param {string} artifactType - Artifact type (agent, workflow, task, tool)
* @param {Object} config - Installation configuration
* @param {string} fallbackTemplateType - Fallback template type if requested template not found
* @returns {Promise<string>} Template content
* @returns {Promise<{content: string, extension: string}>} Template content and extension
*/
async loadTemplate(templateType, artifactType, config = {}, fallbackTemplateType = null) {
const { header_template, body_template } = config;
// Check for separate header/body templates
if (header_template || body_template) {
return await this.loadSplitTemplates(templateType, artifactType, header_template, body_template);
const content = await this.loadSplitTemplates(templateType, artifactType, header_template, body_template);
// Allow config to override extension, default to .md
const ext = config.extension || '.md';
const normalizedExt = ext.startsWith('.') ? ext : `.${ext}`;
return { content, extension: normalizedExt };
}
// Load combined template
const templateName = `${templateType}-${artifactType}.md`;
const templatePath = path.join(__dirname, 'templates', 'combined', templateName);
// Load combined template - try multiple extensions
// If artifactType is empty, templateType already contains full name (e.g., 'gemini-workflow-yaml')
const templateBaseName = artifactType ? `${templateType}-${artifactType}` : templateType;
const templateDir = path.join(__dirname, 'templates', 'combined');
const extensions = ['.md', '.toml', '.yaml', '.yml'];
if (await fs.pathExists(templatePath)) {
return await fs.readFile(templatePath, 'utf8');
for (const ext of extensions) {
const templatePath = path.join(templateDir, templateBaseName + ext);
if (await fs.pathExists(templatePath)) {
const content = await fs.readFile(templatePath, 'utf8');
return { content, extension: ext };
}
}
// Fall back to default template (if provided)
if (fallbackTemplateType) {
const fallbackPath = path.join(__dirname, 'templates', 'combined', `${fallbackTemplateType}.md`);
if (await fs.pathExists(fallbackPath)) {
return await fs.readFile(fallbackPath, 'utf8');
for (const ext of extensions) {
const fallbackPath = path.join(templateDir, `${fallbackTemplateType}${ext}`);
if (await fs.pathExists(fallbackPath)) {
const content = await fs.readFile(fallbackPath, 'utf8');
return { content, extension: ext };
}
}
}
// Ultimate fallback - minimal template
return this.getDefaultTemplate(artifactType);
return { content: this.getDefaultTemplate(artifactType), extension: '.md' };
}
/**
@@ -326,13 +340,26 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
* Generate filename for artifact
* @param {Object} artifact - Artifact data
* @param {string} artifactType - Artifact type (agent, workflow, task, tool)
* @param {string} extension - File extension to use (e.g., '.md', '.toml')
* @returns {string} Generated filename
*/
generateFilename(artifact, artifactType) {
generateFilename(artifact, artifactType, extension = '.md') {
const { toDashPath } = require('./shared/path-utils');
// toDashPath already handles the .agent.md suffix for agents correctly
// No need to add it again here
return toDashPath(artifact.relativePath);
// Reuse central logic to ensure consistent naming conventions
const standardName = toDashPath(artifact.relativePath);
// Clean up potential double extensions from source files (e.g. .yaml.md -> .md)
const baseName = standardName.replace(/\.(yaml|yml)\.md$/, '.md');
// If using default markdown, preserve the bmad-agent- prefix for agents
if (extension === '.md') {
return baseName;
}
// For other extensions (e.g., .toml), replace .md extension
// Note: agent prefix is preserved even with non-markdown extensions
return baseName.replace(/\.md$/, extension);
}
/**

View File

@@ -14,18 +14,14 @@
# installer: Installation configuration (optional - omit for custom installers)
platforms:
# ============================================================================
# CLI Tools
# ============================================================================
claude-code:
name: "Claude Code"
preferred: true
category: cli
description: "Anthropic's official CLI for Claude"
antigravity:
name: "Google Antigravity"
preferred: false
category: ide
description: "Google's AI development environment"
installer:
target_dir: .claude/commands
template_type: default
target_dir: .agent/workflows
template_type: antigravity
auggie:
name: "Auggie"
@@ -36,37 +32,15 @@ platforms:
target_dir: .augment/commands
template_type: default
gemini:
name: "Gemini CLI"
preferred: false
claude-code:
name: "Claude Code"
preferred: true
category: cli
description: "Google's CLI for Gemini"
description: "Anthropic's official CLI for Claude"
installer:
target_dir: .gemini/commands
template_type: gemini
# ============================================================================
# IDEs
# ============================================================================
cursor:
name: "Cursor"
preferred: true
category: ide
description: "AI-first code editor"
installer:
target_dir: .cursor/commands
target_dir: .claude/commands
template_type: default
windsurf:
name: "Windsurf"
preferred: true
category: ide
description: "AI-powered IDE with cascade flows"
installer:
target_dir: .windsurf/workflows
template_type: windsurf
cline:
name: "Cline"
preferred: false
@@ -76,15 +50,40 @@ platforms:
target_dir: .clinerules/workflows
template_type: windsurf
roo:
name: "Roo Cline"
codex:
name: "Codex"
preferred: false
category: cli
description: "OpenAI Codex integration"
# No installer config - uses custom codex.js
crush:
name: "Crush"
preferred: false
category: ide
description: "Enhanced Cline fork"
description: "AI development assistant"
installer:
target_dir: .roo/commands
target_dir: .crush/commands
template_type: default
cursor:
name: "Cursor"
preferred: true
category: ide
description: "AI-first code editor"
installer:
target_dir: .cursor/commands
template_type: default
gemini:
name: "Gemini CLI"
preferred: false
category: cli
description: "Google's CLI for Gemini"
installer:
target_dir: .gemini/commands
template_type: gemini
github-copilot:
name: "GitHub Copilot"
preferred: false
@@ -99,24 +98,6 @@ platforms:
template_type: vscode_settings
artifact_types: []
opencode:
name: "OpenCode"
preferred: false
category: ide
description: "OpenCode terminal coding assistant"
installer:
target_dir: .opencode/command
template_type: opencode
crush:
name: "Crush"
preferred: false
category: ide
description: "AI development assistant"
installer:
target_dir: .crush/commands
template_type: default
iflow:
name: "iFlow"
preferred: false
@@ -126,6 +107,29 @@ platforms:
target_dir: .iflow/commands
template_type: default
kilo:
name: "KiloCoder"
preferred: false
category: ide
description: "AI coding platform"
# No installer config - uses custom kilo.js (creates .kilocodemodes file)
kiro-cli:
name: "Kiro CLI"
preferred: false
category: cli
description: "Kiro command-line interface"
# No installer config - uses custom kiro-cli.js (YAML→JSON conversion)
opencode:
name: "OpenCode"
preferred: false
category: ide
description: "OpenCode terminal coding assistant"
installer:
target_dir: .opencode/command
template_type: opencode
qwen:
name: "QwenCoder"
preferred: false
@@ -135,6 +139,15 @@ platforms:
target_dir: .qwen/commands
template_type: default
roo:
name: "Roo Cline"
preferred: false
category: ide
description: "Enhanced Cline fork"
installer:
target_dir: .roo/commands
template_type: default
rovo-dev:
name: "Rovo Dev"
preferred: false
@@ -153,41 +166,14 @@ platforms:
target_dir: .trae/rules
template_type: trae
antigravity:
name: "Google Antigravity"
preferred: false
windsurf:
name: "Windsurf"
preferred: true
category: ide
description: "Google's AI development environment"
description: "AI-powered IDE with cascade flows"
installer:
target_dir: .agent/workflows
template_type: antigravity
# Note: Antigravity uses .agent/workflows/ directory (not .antigravity/)
# ============================================================================
# Custom Installers (no installer config - use custom file)
# These have unique installation logic that doesn't fit the config-driven model
# ============================================================================
codex:
name: "Codex"
preferred: false
category: cli
description: "OpenAI Codex integration"
# No installer config - uses custom codex.js
kilo:
name: "KiloCoder"
preferred: false
category: ide
description: "AI coding platform"
# No installer config - uses custom kilo.js (creates .kilocodemodes file)
kiro-cli:
name: "Kiro CLI"
preferred: false
category: cli
description: "Kiro command-line interface"
# No installer config - uses custom kiro-cli.js (YAML→JSON conversion)
target_dir: .windsurf/workflows
template_type: windsurf
# ============================================================================
# Installer Config Schema

View File

@@ -32,7 +32,9 @@ class AgentCommandGenerator {
// Use relativePath if available (for nested agents), otherwise just name with .md
const agentPathInModule = agent.relativePath || `${agent.name}.md`;
// Calculate the relative agent path (e.g., bmm/agents/pm.md)
let agentRelPath = agent.path;
let agentRelPath = agent.path || '';
// Normalize path separators for cross-platform compatibility
agentRelPath = agentRelPath.replaceAll('\\', '/');
// Remove _bmad/ prefix if present to get relative path from project root
// Handle both absolute paths (/path/to/_bmad/...) and relative paths (_bmad/...)
if (agentRelPath.includes('_bmad/')) {
@@ -132,9 +134,9 @@ class AgentCommandGenerator {
/**
* Write agent launcher artifacts using dash format (NEW STANDARD)
* Creates flat files like: bmad-bmm-pm.agent.md
* Creates flat files like: bmad-agent-bmm-pm.md
*
* The .agent.md suffix distinguishes agents from workflows/tasks/tools.
* The bmad-agent- prefix distinguishes agents from workflows/tasks/tools.
*
* @param {string} baseCommandsDir - Base commands directory for the IDE
* @param {Array} artifacts - Agent launcher artifacts
@@ -145,7 +147,7 @@ class AgentCommandGenerator {
for (const artifact of artifacts) {
if (artifact.type === 'agent-launcher') {
// Convert relativePath to dash format: bmm/agents/pm.md → bmad-bmm-pm.agent.md
// Convert relativePath to dash format: bmm/agents/pm.md → bmad-agent-bmm-pm.md
const flatName = toDashPath(artifact.relativePath);
const launcherPath = path.join(baseCommandsDir, flatName);
await fs.ensureDir(path.dirname(launcherPath));

View File

@@ -4,14 +4,14 @@
* Provides utilities to convert hierarchical paths to flat naming conventions.
*
* DASH-BASED NAMING (new standard):
* - Agents: bmad-module-name.agent.md (with .agent.md suffix)
* - Agents: bmad-agent-module-name.md (with bmad-agent- prefix)
* - Workflows/Tasks/Tools: bmad-module-name.md
*
* Example outputs:
* - cis/agents/storymaster.md → bmad-cis-storymaster.agent.md
* - cis/agents/storymaster.md → bmad-agent-cis-storymaster.md
* - bmm/workflows/plan-project.md → bmad-bmm-plan-project.md
* - bmm/tasks/create-story.md → bmad-bmm-create-story.md
* - core/agents/brainstorming.md → bmad-brainstorming.agent.md
* - core/agents/brainstorming.md → bmad-agent-brainstorming.md (core agents skip module name)
*/
// Type segments - agents are included in naming, others are filtered out
@@ -20,37 +20,38 @@ const AGENT_SEGMENT = 'agents';
/**
* Convert hierarchical path to flat dash-separated name (NEW STANDARD)
* Converts: 'bmm', 'agents', 'pm' → 'bmad-bmm-pm.agent.md'
* Converts: 'bmm', 'agents', 'pm' → 'bmad-agent-bmm-pm.md'
* Converts: 'bmm', 'workflows', 'correct-course' → 'bmad-bmm-correct-course.md'
* Converts: 'core', 'agents', 'brainstorming' → 'bmad-brainstorming.agent.md' (core items skip module prefix)
* Converts: 'core', 'agents', 'brainstorming' → 'bmad-agent-brainstorming.md' (core agents skip module name)
*
* @param {string} module - Module name (e.g., 'bmm', 'core')
* @param {string} type - Artifact type ('agents', 'workflows', 'tasks', 'tools')
* @param {string} name - Artifact name (e.g., 'pm', 'brainstorming')
* @returns {string} Flat filename like 'bmad-bmm-pm.agent.md' or 'bmad-bmm-correct-course.md'
* @returns {string} Flat filename like 'bmad-agent-bmm-pm.md' or 'bmad-bmm-correct-course.md'
*/
function toDashName(module, type, name) {
const isAgent = type === AGENT_SEGMENT;
// For core module, skip the module prefix: use 'bmad-name.md' instead of 'bmad-core-name.md'
// For core module, skip the module name: use 'bmad-agent-name.md' instead of 'bmad-agent-core-name.md'
if (module === 'core') {
return isAgent ? `bmad-${name}.agent.md` : `bmad-${name}.md`;
return isAgent ? `bmad-agent-${name}.md` : `bmad-${name}.md`;
}
// Module artifacts: bmad-module-name.md or bmad-module-name.agent.md
// Module artifacts: bmad-module-name.md or bmad-agent-module-name.md
// eslint-disable-next-line unicorn/prefer-string-replace-all -- regex replace is intentional here
const dashName = name.replace(/\//g, '-'); // Flatten nested paths
return isAgent ? `bmad-${module}-${dashName}.agent.md` : `bmad-${module}-${dashName}.md`;
return isAgent ? `bmad-agent-${module}-${dashName}.md` : `bmad-${module}-${dashName}.md`;
}
/**
* Convert relative path to flat dash-separated name
* Converts: 'bmm/agents/pm.md' → 'bmad-bmm-pm.agent.md'
* Converts: 'bmm/agents/pm.md' → 'bmad-agent-bmm-pm.md'
* Converts: 'bmm/agents/tech-writer/tech-writer.md' → 'bmad-agent-bmm-tech-writer.md' (uses folder name)
* Converts: 'bmm/workflows/correct-course.md' → 'bmad-bmm-correct-course.md'
* Converts: 'core/agents/brainstorming.md' → 'bmad-brainstorming.agent.md' (core items skip module prefix)
* Converts: 'core/agents/brainstorming.md' → 'bmad-agent-brainstorming.md' (core agents skip module name)
*
* @param {string} relativePath - Path like 'bmm/agents/pm.md'
* @returns {string} Flat filename like 'bmad-bmm-pm.agent.md' or 'bmad-brainstorming.md'
* @returns {string} Flat filename like 'bmad-agent-bmm-pm.md' or 'bmad-brainstorming.md'
*/
function toDashPath(relativePath) {
if (!relativePath || typeof relativePath !== 'string') {
@@ -63,20 +64,30 @@ function toDashPath(relativePath) {
const module = parts[0];
const type = parts[1];
const name = parts.slice(2).join('-');
let name;
// For agents, if nested in a folder (more than 3 parts), use the folder name only
// e.g., 'bmm/agents/tech-writer/tech-writer' → 'tech-writer' (not 'tech-writer-tech-writer')
if (type === 'agents' && parts.length > 3) {
// Use the folder name (parts[2]) as the name, ignore the file name
name = parts[2];
} else {
// For non-nested or non-agents, join all parts after type
name = parts.slice(2).join('-');
}
return toDashName(module, type, name);
}
/**
* Create custom agent dash name
* Creates: 'bmad-custom-fred-commit-poet.agent.md'
* Creates: 'bmad-custom-agent-fred-commit-poet.md'
*
* @param {string} agentName - Custom agent name
* @returns {string} Flat filename like 'bmad-custom-fred-commit-poet.agent.md'
* @returns {string} Flat filename like 'bmad-custom-agent-fred-commit-poet.md'
*/
function customAgentDashName(agentName) {
return `bmad-custom-${agentName}.agent.md`;
return `bmad-custom-agent-${agentName}.md`;
}
/**
@@ -90,9 +101,9 @@ function isDashFormat(filename) {
/**
* Extract parts from a dash-formatted filename
* Parses: 'bmad-bmm-pm.agent.md' → { prefix: 'bmad', module: 'bmm', type: 'agents', name: 'pm' }
* Parses: 'bmad-agent-bmm-pm.md' → { prefix: 'bmad', module: 'bmm', type: 'agents', name: 'pm' }
* Parses: 'bmad-bmm-correct-course.md' → { prefix: 'bmad', module: 'bmm', type: 'workflows', name: 'correct-course' }
* Parses: 'bmad-brainstorming.agent.md' → { prefix: 'bmad', module: 'core', type: 'agents', name: 'brainstorming' } (core agents)
* Parses: 'bmad-agent-brainstorming.md' → { prefix: 'bmad', module: 'core', type: 'agents', name: 'brainstorming' } (core agents)
* Parses: 'bmad-brainstorming.md' → { prefix: 'bmad', module: 'core', type: 'workflows', name: 'brainstorming' } (core workflows)
*
* @param {string} filename - Dash-formatted filename
@@ -106,27 +117,27 @@ function parseDashName(filename) {
return null;
}
// Check if this is an agent file (has .agent suffix)
const isAgent = withoutExt.endsWith('.agent');
// Check if this is an agent file (has 'agent' as second part)
const isAgent = parts[1] === 'agent';
if (isAgent) {
// This is an agent file
// Format: bmad-name.agent (core) or bmad-module-name.agent
// Format: bmad-agent-name (core) or bmad-agent-module-name
if (parts.length === 3) {
// Core agent: bmad-name.agent
// Core agent: bmad-agent-name
return {
prefix: parts[0],
module: 'core',
type: 'agents',
name: parts[1],
name: parts[2],
};
} else {
// Module agent: bmad-module-name.agent
// Module agent: bmad-agent-module-name
return {
prefix: parts[0],
module: parts[1],
module: parts[2],
type: 'agents',
name: parts.slice(2).join('-'),
name: parts.slice(3).join('-'),
};
}
}

View File

@@ -242,7 +242,7 @@ Follow all instructions in the ${type} file exactly as written.
* Write task/tool artifacts using dash format (NEW STANDARD)
* Creates flat files like: bmad-bmm-bmad-help.md
*
* Note: Tasks/tools do NOT have .agent.md suffix - only agents do.
* Note: Tasks/tools do NOT have bmad-agent- prefix - only agents do.
*
* @param {string} baseCommandsDir - Base commands directory for the IDE
* @param {Array} artifacts - Task/tool artifacts with relativePath

View File

@@ -68,7 +68,9 @@ class WorkflowCommandGenerator {
for (const workflow of allWorkflows) {
const commandContent = await this.generateCommandContent(workflow, bmadDir);
// Calculate the relative workflow path (e.g., bmm/workflows/4-implementation/sprint-planning/workflow.yaml)
let workflowRelPath = workflow.path;
let workflowRelPath = workflow.path || '';
// Normalize path separators for cross-platform compatibility
workflowRelPath = workflowRelPath.replaceAll('\\', '/');
// Remove _bmad/ prefix if present to get relative path from project root
// Handle both absolute paths (/path/to/_bmad/...) and relative paths (_bmad/...)
if (workflowRelPath.includes('_bmad/')) {
@@ -76,9 +78,15 @@ class WorkflowCommandGenerator {
if (parts.length > 1) {
workflowRelPath = parts.slice(1).join('/');
}
} else if (workflowRelPath.includes('/src/')) {
// Normalize source paths (e.g. .../src/bmm/...) to relative module path (e.g. bmm/...)
const match = workflowRelPath.match(/\/src\/([^/]+)\/(.+)/);
if (match) {
workflowRelPath = `${match[1]}/${match[2]}`;
}
}
// Determine if this is a YAML workflow
const isYamlWorkflow = workflow.path.endsWith('.yaml') || workflow.path.endsWith('.yml');
// Determine if this is a YAML workflow (use normalized path which is guaranteed to be a string)
const isYamlWorkflow = workflowRelPath.endsWith('.yaml') || workflowRelPath.endsWith('.yml');
artifacts.push({
type: 'workflow-command',
isYamlWorkflow: isYamlWorkflow, // For template selection
@@ -284,7 +292,7 @@ When running any workflow:
* Write workflow command artifacts using dash format (NEW STANDARD)
* Creates flat files like: bmad-bmm-correct-course.md
*
* Note: Workflows do NOT have .agent.md suffix - only agents do.
* Note: Workflows do NOT have bmad-agent- prefix - only agents do.
*
* @param {string} baseCommandsDir - Base commands directory for the IDE
* @param {Array} artifacts - Workflow artifacts

View File

@@ -0,0 +1,14 @@
description = "Activates the {{name}} agent from the BMad Method."
prompt = """
CRITICAL: You are now the BMad '{{name}}' agent.
PRE-FLIGHT CHECKLIST:
1. [ ] IMMEDIATE ACTION: Load and parse {project-root}/{{bmadFolderName}}/{{module}}/config.yaml - store ALL config values in memory for use throughout the session.
2. [ ] IMMEDIATE ACTION: Read and internalize the full agent definition at {project-root}/{{bmadFolderName}}/{{path}}.
3. [ ] CONFIRM: The user's name from config is {user_name}.
Only after all checks are complete, greet the user by name and display the menu.
Acknowledge this checklist is complete in your first response.
AGENT DEFINITION: {project-root}/{{bmadFolderName}}/{{path}}
"""

View File

@@ -0,0 +1,16 @@
description = """{{description}}"""
prompt = """
Execute the BMAD '{{name}}' workflow.
CRITICAL: This is a structured YAML workflow. Follow these steps precisely:
1. LOAD the workflow definition from {project-root}/{{bmadFolderName}}/{{workflow_path}}
2. PARSE the YAML structure to understand:
- Workflow phases and steps
- Required inputs and outputs
- Dependencies between steps
3. EXECUTE each step in order
4. VALIDATE outputs before proceeding to next step
WORKFLOW FILE: {project-root}/{{bmadFolderName}}/{{workflow_path}}
"""

View File

@@ -0,0 +1,14 @@
description = """{{description}}"""
prompt = """
Execute the BMAD '{{name}}' workflow.
CRITICAL: You must load and follow the workflow definition exactly.
WORKFLOW INSTRUCTIONS:
1. LOAD the workflow file from {project-root}/{{bmadFolderName}}/{{workflow_path}}
2. READ its entire contents
3. FOLLOW every step precisely as specified
4. DO NOT skip or modify any steps
WORKFLOW FILE: {project-root}/{{bmadFolderName}}/{{workflow_path}}
"""

View File

@@ -1,14 +0,0 @@
description = "Activates the {{title}} agent from the BMad Method."
prompt = """
CRITICAL: You are now the BMad '{{title}}' agent.
PRE-FLIGHT CHECKLIST:
1. [ ] IMMEDIATE ACTION: Load and parse @{_bmad}/{{module}}/config.yaml - store ALL config values in memory for use throughout the session.
2. [ ] IMMEDIATE ACTION: Read and internalize the full agent definition at @{_bmad}/{{module}}/agents/{{name}}.md.
3. [ ] CONFIRM: The user's name from config is {user_name}.
Only after all checks are complete, greet the user by name and display the menu.
Acknowledge this checklist is complete in your first response.
AGENT DEFINITION: @{_bmad}/{{module}}/agents/{{name}}.md
"""

View File

@@ -1,12 +0,0 @@
description = "Executes the {{taskName}} task from the BMad Method."
prompt = """
Execute the following BMad Method task workflow:
PRE-FLIGHT CHECKLIST:
1. [ ] IMMEDIATE ACTION: Load and parse @{_bmad}/{{module}}/config.yaml.
2. [ ] IMMEDIATE ACTION: Read and load the task definition at @{_bmad}/{{module}}/tasks/{{filename}}.
Follow all instructions and complete the task as defined.
TASK DEFINITION: @{_bmad}/{{module}}/tasks/{{filename}}
"""

View File

@@ -1,10 +0,0 @@
You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
<agent-activation CRITICAL="TRUE">
1. LOAD the FULL agent file from {project-root}/_bmad/{{path}}
2. READ its entire contents - this contains the complete agent persona, menu, and instructions
3. FOLLOW every step in the <activation> section precisely
4. DISPLAY the welcome/greeting as instructed
5. PRESENT the numbered menu
6. WAIT for user input before proceeding
</agent-activation>

View File

@@ -1,2 +0,0 @@
name = "{{name}}"
description = "{{description}}"