mirror of
https://github.com/bmad-code-org/BMAD-METHOD.git
synced 2026-01-30 04:32:02 +00:00
no double agent files and .agent.md file extensions.
This commit is contained in:
@@ -352,14 +352,14 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}}
|
||||
// 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 original behavior (keeps .agent.md suffix)
|
||||
// If using default markdown, preserve the bmad-agent- prefix for agents
|
||||
if (extension === '.md') {
|
||||
return baseName;
|
||||
}
|
||||
|
||||
// For other extensions (e.g., .toml), remove .agent suffix as well
|
||||
// Gemini doesn't support double-dot patterns like .agent.toml
|
||||
return baseName.replace(/(\.agent)?(\.md|\.yaml|\.yml)$/, extension);
|
||||
// For other extensions (e.g., .toml), replace .md extension
|
||||
// Note: agent prefix is preserved even with non-markdown extensions
|
||||
return baseName.replace(/\.md$/, extension);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -134,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
|
||||
@@ -147,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));
|
||||
|
||||
@@ -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('-'),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -292,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
|
||||
|
||||
Reference in New Issue
Block a user