Compare commits

...

5 Commits

Author SHA1 Message Date
Sjoerd Bozon daf8a07ee8
Merge 015c74c46f into 677a00280b 2026-01-09 13:54:40 +01:00
Phil 677a00280b
feat: refactor Cursor IDE setup to do command generation and cleanup instead of rules (#1283)
* feat: refactor Cursor IDE setup to do  command generation and cleanup instead of rules

- Added support for command generation in the Cursor IDE setup, including the creation of a new commands directory.
- Implemented cleanup for old BMAD commands alongside existing rules.
- Integrated TaskToolCommandGenerator for generating task and tool commands.
- Updated logging to reflect the number of agents, tasks, tools, and workflow commands generated during setup.

* style: adjust constructor formatting and update command path in Cursor IDE setup

- Reformatted the constructor method for consistency.
- Updated the command path syntax in the Cursor IDE setup to use a more standard format.

* fix: update Cursor command paths in documentation

- Changed the command path for Cursor IDE setup from `.cursor/rules/bmad/` to `.cursor/commands/bmad/` in both installers.md and modules.md.
- Updated file extension references to use `.md` instead of `.mdc` for consistency.
2026-01-09 16:39:32 +08:00
Sjoerd Bozon 015c74c46f
Merge branch 'bmad-code-org:main' into feat/workflow-prompt-recommendations 2026-01-05 10:24:53 +01:00
Sjoerd Bozon 9317ef5a62 fix: address Copilot review feedback on PR #1205
- Move step 6 before WORKFLOW COMPLETE marker (fixes workflow structure)
- Change PRD shortcut from PR to PD (avoids conflict with parallel-research)
- Clarify instructions for reading/updating VS Code settings
- Update phase 4 comment to match actual handoff flow
2025-12-29 00:16:38 +01:00
Sjoerd Bozon d662aee4b2 feat: add VS Code workflow prompt recommendations
Add chat.promptFilesRecommendations support for GitHub Copilot to show
workflow shortcuts as new chat starters.

- Add workflow-prompts-config.js with all BMM, BMGD, and core prompts
- Add workflow-prompt-generator.js to create .github/prompts/*.prompt.md
- Update github-copilot.js to generate prompts and configure VS Code
- Add phase-based prompt toggling to implementation-readiness workflow
- Add phase-based prompt toggling to sprint-planning workflow

When implementation-readiness passes or sprint-planning completes, the
workflows update VS Code settings to prioritize the 'keep going' cycle
(create-story → dev-story → code-review) over setup phase prompts.
2025-12-28 23:44:40 +01:00
8 changed files with 412 additions and 313 deletions

View File

@ -61,7 +61,7 @@
| -------------- | -------------- | ------------------------- | ----------------------------- |
| claude-code | Claude Code | .claude/commands/ | .md with frontmatter |
| codex | Codex | (varies) | .md |
| cursor | Cursor | .cursor/rules/bmad/ | .mdc with MDC frontmatter |
| cursor | Cursor | .cursor/commands/bmad/ | .md with YAML frontmatter |
| github-copilot | GitHub Copilot | .github/ | .md |
| opencode | OpenCode | .opencode/ | .md |
| windsurf | Windsurf | .windsurf/workflows/bmad/ | .md with workflow frontmatter |

View File

@ -128,7 +128,7 @@ module.exports = { NewIdeSetup };
| IDE | Config Pattern | File Extension |
| -------------- | ------------------------- | -------------- |
| Claude Code | .claude/commands/bmad/ | .md |
| Cursor | .cursor/rules/bmad/ | .mdc |
| Cursor | .cursor/commands/bmad/ | .md |
| Windsurf | .windsurf/workflows/bmad/ | .md |
| GitHub Copilot | .github/ | .md |

View File

@ -111,6 +111,29 @@ Report generated: {outputFile}
The assessment found [number] issues requiring attention. Review the detailed report for specific findings and recommendations."
### 6. Update IDE Prompt Recommendations
If the readiness status is **READY**, update `.vscode/settings.json` to prioritize the implementation cycle prompts.
Read the existing `chat.promptFilesRecommendations` object and modify these keys:
**Set to `true` (implementation cycle - "keep going" loop):**
- `bmd-create-story`
- `bmd-dev-story`
- `bmd-code-review`
- `bmd-retrospective`
- `bmd-correct-course`
**Set to `false` (setup phase - already completed):**
- `bmd-workflow-init`
- `bmd-brainstorm`
- `bmd-prd`
- `bmd-ux-design`
- `bmd-create-architecture`
- `bmd-epics-stories`
- `bmd-implementation-readiness`
- `bmd-sprint-planning`
## WORKFLOW COMPLETE
The implementation readiness workflow is now complete. The report contains all findings and recommendations for the user to consider.

View File

@ -179,6 +179,38 @@ development_status:
</step>
<step n="6" goal="Update IDE prompt recommendations for implementation phase">
<action>Read the existing `.vscode/settings.json` and update the `chat.promptFilesRecommendations` object.</action>
**Set to `true` (implementation cycle - "keep going" loop):**
- `bmd-create-story`
- `bmd-dev-story`
- `bmd-code-review`
- `bmd-retrospective`
- `bmd-correct-course`
**Set to `false` (setup phase - already completed):**
- `bmd-workflow-init`
- `bmd-brainstorm`
- `bmd-prd`
- `bmd-ux-design`
- `bmd-create-architecture`
- `bmd-epics-stories`
- `bmd-implementation-readiness`
- `bmd-sprint-planning`
<action>Inform {user_name}:</action>
**IDE Updated for Implementation Phase**
The "keep going" cycle prompts are now prioritized in VS Code:
- **@bmd-custom-bmm-sm → *create-story** (prepare a story)
- **@bmd-custom-bmm-dev → *dev-story** (implement it)
- **Same chat → *code-review** (review the code)
- **Repeat!**
</step>
</workflow>
## Additional Documentation

View File

@ -3,6 +3,7 @@ const { BaseIdeSetup } = require('./_base-ide');
const chalk = require('chalk');
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
const { WorkflowCommandGenerator } = require('./shared/workflow-command-generator');
const { TaskToolCommandGenerator } = require('./shared/task-tool-command-generator');
/**
* Cursor IDE setup handler
@ -12,6 +13,7 @@ class CursorSetup extends BaseIdeSetup {
super('cursor', 'Cursor', true); // preferred IDE
this.configDir = '.cursor';
this.rulesDir = 'rules';
this.commandsDir = 'commands';
}
/**
@ -21,11 +23,17 @@ class CursorSetup extends BaseIdeSetup {
async cleanup(projectDir) {
const fs = require('fs-extra');
const bmadRulesDir = path.join(projectDir, this.configDir, this.rulesDir, 'bmad');
const bmadCommandsDir = path.join(projectDir, this.configDir, this.commandsDir, 'bmad');
if (await fs.pathExists(bmadRulesDir)) {
await fs.remove(bmadRulesDir);
console.log(chalk.dim(` Removed old BMAD rules from ${this.name}`));
}
if (await fs.pathExists(bmadCommandsDir)) {
await fs.remove(bmadCommandsDir);
console.log(chalk.dim(` Removed old BMAD commands from ${this.name}`));
}
}
/**
@ -40,330 +48,76 @@ class CursorSetup extends BaseIdeSetup {
// Clean up old BMAD installation first
await this.cleanup(projectDir);
// Create .cursor/rules directory structure
// Create .cursor/commands directory structure
const cursorDir = path.join(projectDir, this.configDir);
const rulesDir = path.join(cursorDir, this.rulesDir);
const bmadRulesDir = path.join(rulesDir, 'bmad');
const commandsDir = path.join(cursorDir, this.commandsDir);
const bmadCommandsDir = path.join(commandsDir, 'bmad');
await this.ensureDir(bmadRulesDir);
await this.ensureDir(bmadCommandsDir);
// Generate agent launchers first
// Generate agent launchers using AgentCommandGenerator
// This creates small launcher files that reference the actual agents in _bmad/
const agentGen = new AgentCommandGenerator(this.bmadFolderName);
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
// Convert artifacts to agent format for index creation
const agents = agentArtifacts.map((a) => ({ module: a.module, name: a.name }));
// Get tasks, tools, and workflows (ALL workflows now generate commands)
const tasks = await this.getTasks(bmadDir, true);
const tools = await this.getTools(bmadDir, true);
// Get ALL workflows using the new workflow command generator
const workflowGenerator = new WorkflowCommandGenerator(this.bmadFolderName);
const { artifacts: workflowArtifacts, counts: workflowCounts } = await workflowGenerator.collectWorkflowArtifacts(bmadDir);
// Convert artifacts to workflow objects for directory creation
const workflows = workflowArtifacts
.filter((artifact) => artifact.type === 'workflow-command')
.map((artifact) => ({
module: artifact.module,
name: path.basename(artifact.relativePath, '.md'),
path: artifact.sourcePath,
}));
const { artifacts: agentArtifacts, counts: agentCounts } = await agentGen.collectAgentArtifacts(bmadDir, options.selectedModules || []);
// Create directories for each module
const modules = new Set();
for (const item of [...agents, ...tasks, ...tools, ...workflows]) modules.add(item.module);
for (const artifact of agentArtifacts) {
modules.add(artifact.module);
}
for (const module of modules) {
await this.ensureDir(path.join(bmadRulesDir, module));
await this.ensureDir(path.join(bmadRulesDir, module, 'agents'));
await this.ensureDir(path.join(bmadRulesDir, module, 'tasks'));
await this.ensureDir(path.join(bmadRulesDir, module, 'tools'));
await this.ensureDir(path.join(bmadRulesDir, module, 'workflows'));
await this.ensureDir(path.join(bmadCommandsDir, module));
await this.ensureDir(path.join(bmadCommandsDir, module, 'agents'));
}
// Process and write agent launchers with MDC format
let agentCount = 0;
for (const artifact of agentArtifacts) {
// Add MDC metadata header to launcher (but don't call processContent which adds activation headers)
const content = this.wrapLauncherWithMDC(artifact.content, {
module: artifact.module,
name: artifact.name,
});
// Write agent launcher files
const agentCount = await agentGen.writeAgentLaunchers(bmadCommandsDir, agentArtifacts);
const targetPath = path.join(bmadRulesDir, artifact.module, 'agents', `${artifact.name}.mdc`);
// Generate workflow commands from manifest (if it exists)
const workflowGen = new WorkflowCommandGenerator(this.bmadFolderName);
const { artifacts: workflowArtifacts } = await workflowGen.collectWorkflowArtifacts(bmadDir);
await this.writeFile(targetPath, content);
agentCount++;
}
// Process and copy tasks
let taskCount = 0;
for (const task of tasks) {
const content = await this.readAndProcess(task.path, {
module: task.module,
name: task.name,
});
const targetPath = path.join(bmadRulesDir, task.module, 'tasks', `${task.name}.mdc`);
await this.writeFile(targetPath, content);
taskCount++;
}
// Process and copy tools
let toolCount = 0;
for (const tool of tools) {
const content = await this.readAndProcess(tool.path, {
module: tool.module,
name: tool.name,
});
const targetPath = path.join(bmadRulesDir, tool.module, 'tools', `${tool.name}.mdc`);
await this.writeFile(targetPath, content);
toolCount++;
}
// Process and copy workflow commands (generated, not raw workflows)
let workflowCount = 0;
// Write only workflow-command artifacts, skip workflow-launcher READMEs
let workflowCommandCount = 0;
for (const artifact of workflowArtifacts) {
if (artifact.type === 'workflow-command') {
// Add MDC metadata header to workflow command
const content = this.wrapLauncherWithMDC(artifact.content, {
module: artifact.module,
name: path.basename(artifact.relativePath, '.md'),
});
const targetPath = path.join(bmadRulesDir, artifact.module, 'workflows', `${path.basename(artifact.relativePath, '.md')}.mdc`);
await this.writeFile(targetPath, content);
workflowCount++;
const moduleWorkflowsDir = path.join(bmadCommandsDir, artifact.module, 'workflows');
await this.ensureDir(moduleWorkflowsDir);
const commandPath = path.join(moduleWorkflowsDir, path.basename(artifact.relativePath));
await this.writeFile(commandPath, artifact.content);
workflowCommandCount++;
}
// Skip workflow-launcher READMEs as they would be treated as slash commands
}
// Create BMAD index file (but NOT .cursorrules - user manages that)
await this.createBMADIndex(bmadRulesDir, agents, tasks, tools, workflows, modules);
// Generate task and tool commands from manifests (if they exist)
const taskToolGen = new TaskToolCommandGenerator();
const taskToolResult = await taskToolGen.generateTaskToolCommands(projectDir, bmadDir, bmadCommandsDir);
console.log(chalk.green(`${this.name} configured:`));
console.log(chalk.dim(` - ${agentCount} agents installed`));
console.log(chalk.dim(` - ${taskCount} tasks installed`));
console.log(chalk.dim(` - ${toolCount} tools installed`));
console.log(chalk.dim(` - ${workflowCount} workflows installed`));
console.log(chalk.dim(` - Rules directory: ${path.relative(projectDir, bmadRulesDir)}`));
if (workflowCommandCount > 0) {
console.log(chalk.dim(` - ${workflowCommandCount} workflow commands generated`));
}
if (taskToolResult.generated > 0) {
console.log(
chalk.dim(
` - ${taskToolResult.generated} task/tool commands generated (${taskToolResult.tasks} tasks, ${taskToolResult.tools} tools)`,
),
);
}
console.log(chalk.dim(` - Commands directory: ${path.relative(projectDir, bmadCommandsDir)}`));
return {
success: true,
agents: agentCount,
tasks: taskCount,
tools: toolCount,
workflows: workflowCount,
tasks: taskToolResult.tasks || 0,
tools: taskToolResult.tools || 0,
workflows: workflowCommandCount,
};
}
/**
* Create BMAD index file for easy navigation
*/
async createBMADIndex(bmadRulesDir, agents, tasks, tools, workflows, modules) {
const indexPath = path.join(bmadRulesDir, 'index.mdc');
let content = `---
description: BMAD Method - Master Index
globs:
alwaysApply: true
---
# BMAD Method - Cursor Rules Index
This is the master index for all BMAD agents, tasks, tools, and workflows available in your project.
## Installation Complete!
BMAD rules have been installed to: \`.cursor/rules/bmad/\`
**Note:** BMAD does not modify your \`.cursorrules\` file. You manage that separately.
## How to Use
- Reference specific agents: @bmad/{module}/agents/{agent-name}
- Reference specific tasks: @bmad/{module}/tasks/{task-name}
- Reference specific tools: @bmad/{module}/tools/{tool-name}
- Reference specific workflows: @bmad/{module}/workflows/{workflow-name}
- Reference entire modules: @bmad/{module}
- Reference this index: @bmad/index
## Available Modules
`;
for (const module of modules) {
content += `### ${module.toUpperCase()}\n\n`;
// List agents for this module
const moduleAgents = agents.filter((a) => a.module === module);
if (moduleAgents.length > 0) {
content += `**Agents:**\n`;
for (const agent of moduleAgents) {
content += `- @bmad/${module}/agents/${agent.name} - ${agent.name}\n`;
}
content += '\n';
}
// List tasks for this module
const moduleTasks = tasks.filter((t) => t.module === module);
if (moduleTasks.length > 0) {
content += `**Tasks:**\n`;
for (const task of moduleTasks) {
content += `- @bmad/${module}/tasks/${task.name} - ${task.name}\n`;
}
content += '\n';
}
// List tools for this module
const moduleTools = tools.filter((t) => t.module === module);
if (moduleTools.length > 0) {
content += `**Tools:**\n`;
for (const tool of moduleTools) {
content += `- @bmad/${module}/tools/${tool.name} - ${tool.name}\n`;
}
content += '\n';
}
// List workflows for this module
const moduleWorkflows = workflows.filter((w) => w.module === module);
if (moduleWorkflows.length > 0) {
content += `**Workflows:**\n`;
for (const workflow of moduleWorkflows) {
content += `- @bmad/${module}/workflows/${workflow.name} - ${workflow.name}\n`;
}
content += '\n';
}
}
content += `
## Quick Reference
- All BMAD rules are Manual type - reference them explicitly when needed
- Agents provide persona-based assistance with specific expertise
- Tasks are reusable workflows for common operations
- Tools provide specialized functionality
- Workflows orchestrate multi-step processes
- Each agent includes an activation block for proper initialization
## Configuration
BMAD rules are configured as Manual rules (alwaysApply: false) to give you control
over when they're included in your context. Reference them explicitly when you need
specific agent expertise, task workflows, tools, or guided workflows.
`;
await this.writeFile(indexPath, content);
}
/**
* Read and process file content
*/
async readAndProcess(filePath, metadata) {
const fs = require('fs-extra');
const content = await fs.readFile(filePath, 'utf8');
return this.processContent(content, metadata);
}
/**
* Override processContent to add MDC metadata header for Cursor
* @param {string} content - File content
* @param {Object} metadata - File metadata
* @returns {string} Processed content with MDC header
*/
processContent(content, metadata = {}) {
// First apply base processing (includes activation injection for agents)
let processed = super.processContent(content, metadata);
// Strip any existing frontmatter from the processed content
// This prevents duplicate frontmatter blocks
const frontmatterRegex = /^---\s*\n[\s\S]*?\n---\s*\n/;
if (frontmatterRegex.test(processed)) {
processed = processed.replace(frontmatterRegex, '');
}
// Determine the type and description based on content
const isAgent = content.includes('<agent');
const isTask = content.includes('<task');
const isTool = content.includes('<tool');
const isWorkflow = content.includes('workflow:') || content.includes('name:');
let description = '';
let globs = '';
if (isAgent) {
// Extract agent title if available
const titleMatch = content.match(/title="([^"]+)"/);
const title = titleMatch ? titleMatch[1] : metadata.name;
description = `BMAD ${metadata.module.toUpperCase()} Agent: ${title}`;
globs = '';
} else if (isTask) {
// Extract task name if available
const nameMatch = content.match(/name="([^"]+)"/);
const taskName = nameMatch ? nameMatch[1] : metadata.name;
description = `BMAD ${metadata.module.toUpperCase()} Task: ${taskName}`;
globs = '';
} else if (isTool) {
// Extract tool name if available
const nameMatch = content.match(/name="([^"]+)"/);
const toolName = nameMatch ? nameMatch[1] : metadata.name;
description = `BMAD ${metadata.module.toUpperCase()} Tool: ${toolName}`;
globs = '';
} else if (isWorkflow) {
// Workflow
description = `BMAD ${metadata.module.toUpperCase()} Workflow: ${metadata.name}`;
globs = '';
} else {
description = `BMAD ${metadata.module.toUpperCase()}: ${metadata.name}`;
globs = '';
}
// Create MDC metadata header
const mdcHeader = `---
description: ${description}
globs: ${globs}
alwaysApply: false
---
`;
// Add the MDC header to the processed content
return mdcHeader + processed;
}
/**
* Wrap launcher content with MDC metadata (without base processing)
* Launchers are already complete and should not have activation headers injected
*/
wrapLauncherWithMDC(launcherContent, metadata = {}) {
// Strip the launcher's frontmatter - we'll replace it with MDC frontmatter
const frontmatterRegex = /^---\s*\n[\s\S]*?\n---\s*\n/;
const contentWithoutFrontmatter = launcherContent.replace(frontmatterRegex, '');
// Extract metadata from launcher frontmatter for MDC description
const nameMatch = launcherContent.match(/name:\s*"([^"]+)"/);
const name = nameMatch ? nameMatch[1] : metadata.name;
const description = `BMAD ${metadata.module.toUpperCase()} Agent: ${name}`;
// Create MDC metadata header
const mdcHeader = `---
description: ${description}
globs:
alwaysApply: false
---
`;
// Return MDC header + launcher content (without its original frontmatter)
return mdcHeader + contentWithoutFrontmatter;
}
/**
* Install a custom agent launcher for Cursor
* @param {string} projectDir - Project directory
@ -373,7 +127,7 @@ alwaysApply: false
* @returns {Object|null} Info about created command
*/
async installCustomAgentLauncher(projectDir, agentName, agentPath, metadata) {
const customAgentsDir = path.join(projectDir, this.configDir, this.rulesDir, 'bmad', 'custom', 'agents');
const customAgentsDir = path.join(projectDir, this.configDir, this.commandsDir, 'bmad', 'custom', 'agents');
if (!(await this.exists(path.join(projectDir, this.configDir)))) {
return null; // IDE not configured for this project
@ -393,22 +147,21 @@ alwaysApply: false
</agent-activation>
`;
// Cursor uses MDC format with metadata header
const mdcContent = `---
description: "${agentName} agent"
globs:
alwaysApply: false
// Cursor uses YAML frontmatter matching Claude Code format
const commandContent = `---
name: '${agentName}'
description: '${agentName} agent'
---
${launcherContent}
`;
const launcherPath = path.join(customAgentsDir, `${agentName}.mdc`);
await this.writeFile(launcherPath, mdcContent);
const launcherPath = path.join(customAgentsDir, `${agentName}.md`);
await this.writeFile(launcherPath, commandContent);
return {
path: launcherPath,
command: `@${agentName}`,
command: `/bmad/custom/agents/${agentName}`,
};
}
}

View File

@ -2,6 +2,7 @@ const path = require('node:path');
const { BaseIdeSetup } = require('./_base-ide');
const chalk = require('chalk');
const { AgentCommandGenerator } = require('./shared/agent-command-generator');
const { WorkflowPromptGenerator } = require('./shared/workflow-prompt-generator');
/**
* GitHub Copilot setup handler
@ -12,6 +13,7 @@ class GitHubCopilotSetup extends BaseIdeSetup {
super('github-copilot', 'GitHub Copilot', true); // preferred IDE
this.configDir = '.github';
this.agentsDir = 'agents';
this.promptsDir = 'prompts';
this.vscodeDir = '.vscode';
}
@ -94,14 +96,12 @@ class GitHubCopilotSetup extends BaseIdeSetup {
async setup(projectDir, bmadDir, options = {}) {
console.log(chalk.cyan(`Setting up ${this.name}...`));
// Configure VS Code settings using pre-collected config if available
const config = options.preCollectedConfig || {};
await this.configureVsCodeSettings(projectDir, { ...options, ...config });
// Create .github/agents directory
const githubDir = path.join(projectDir, this.configDir);
const agentsDir = path.join(githubDir, this.agentsDir);
const promptsDir = path.join(githubDir, this.promptsDir);
await this.ensureDir(agentsDir);
await this.ensureDir(promptsDir);
// Clean up any existing BMAD files before reinstalling
await this.cleanup(projectDir);
@ -117,22 +117,37 @@ class GitHubCopilotSetup extends BaseIdeSetup {
const agentContent = await this.createAgentContent({ module: artifact.module, name: artifact.name }, content);
// Use bmd- prefix: bmd-custom-{module}-{name}.agent.md
const targetPath = path.join(agentsDir, `bmd-custom-${artifact.module}-${artifact.name}.agent.md`);
const agentFileName = `bmd-custom-${artifact.module}-${artifact.name}`;
const targetPath = path.join(agentsDir, `${agentFileName}.agent.md`);
await this.writeFile(targetPath, agentContent);
agentCount++;
console.log(chalk.green(` ✓ Created agent: bmd-custom-${artifact.module}-${artifact.name}`));
console.log(chalk.green(` ✓ Created agent: ${agentFileName}`));
}
// Generate workflow prompts from config (shared logic)
// Each prompt includes nextSteps guidance for the agent to suggest next workflows
const promptGen = new WorkflowPromptGenerator();
const promptRecommendations = await promptGen.generatePromptFiles(promptsDir, options.selectedModules || []);
const promptCount = Object.keys(promptRecommendations).length;
// Configure VS Code settings using pre-collected config if available
const config = options.preCollectedConfig || {};
await this.configureVsCodeSettings(projectDir, { ...options, ...config, promptRecommendations });
console.log(chalk.green(`${this.name} configured:`));
console.log(chalk.dim(` - ${agentCount} agents created`));
console.log(chalk.dim(` - ${promptCount} workflow prompts configured`));
console.log(chalk.dim(` - Agents directory: ${path.relative(projectDir, agentsDir)}`));
console.log(chalk.dim(` - Prompts directory: ${path.relative(projectDir, promptsDir)}`));
console.log(chalk.dim(` - VS Code settings configured`));
console.log(chalk.dim('\n Agents available in VS Code Chat view'));
console.log(chalk.dim(' Workflow prompts show as new chat starters'));
return {
success: true,
agents: agentCount,
prompts: promptCount,
settings: true,
};
}
@ -199,6 +214,11 @@ class GitHubCopilotSetup extends BaseIdeSetup {
};
}
// Add prompt file recommendations for new chat starters
if (options.promptRecommendations && Object.keys(options.promptRecommendations).length > 0) {
bmadSettings['chat.promptFilesRecommendations'] = options.promptRecommendations;
}
// Merge settings (existing take precedence)
const mergedSettings = { ...bmadSettings, ...existingSettings };
@ -307,6 +327,24 @@ ${cleanContent}
console.log(chalk.dim(` Cleaned up ${removed} existing BMAD agents`));
}
}
// Clean up prompts directory
const promptsDir = path.join(projectDir, this.configDir, this.promptsDir);
if (await fs.pathExists(promptsDir)) {
const files = await fs.readdir(promptsDir);
let removed = 0;
for (const file of files) {
if (file.startsWith('bmd-') && file.endsWith('.prompt.md')) {
await fs.remove(path.join(promptsDir, file));
removed++;
}
}
if (removed > 0) {
console.log(chalk.dim(` Cleaned up ${removed} existing BMAD prompt files`));
}
}
}
/**

View File

@ -0,0 +1,61 @@
const path = require('node:path');
const fs = require('fs-extra');
const { workflowPromptsConfig } = require('./workflow-prompts-config');
/**
* Generate workflow prompt recommendations for IDE new chat starters
* Uses static configuration from workflow-prompts-config.js which mirrors
* the workflows documented in quick-start.md
*
* The implementation-readiness and sprint-planning workflows update
* VS Code settings to toggle which prompts are shown based on project phase.
*/
class WorkflowPromptGenerator {
/**
* Get workflow prompts for selected modules
* @param {Array<string>} selectedModules - Modules to include (e.g., ['bmm', 'bmgd'])
* @returns {Array<Object>} Array of workflow prompt configurations
*/
getWorkflowPrompts(selectedModules = []) {
const allPrompts = [];
// Always include core prompts
if (workflowPromptsConfig.core) {
allPrompts.push(...workflowPromptsConfig.core);
}
// Add prompts for each selected module
for (const moduleName of selectedModules) {
if (workflowPromptsConfig[moduleName]) {
allPrompts.push(...workflowPromptsConfig[moduleName]);
}
}
return allPrompts;
}
/**
* Generate prompt files for an IDE
* @param {string} promptsDir - Directory to write prompt files
* @param {Array<string>} selectedModules - Modules to include
* @returns {Object} Map of prompt names to true for VS Code settings
*/
async generatePromptFiles(promptsDir, selectedModules = []) {
const prompts = this.getWorkflowPrompts(selectedModules);
const recommendations = {};
for (const prompt of prompts) {
const promptContent = ['---', `agent: ${prompt.agent}`, `description: "${prompt.description}"`, '---', '', prompt.prompt, ''].join(
'\n',
);
const promptFilePath = path.join(promptsDir, `bmd-${prompt.name}.prompt.md`);
await fs.writeFile(promptFilePath, promptContent);
recommendations[`bmd-${prompt.name}`] = true;
}
return recommendations;
}
}
module.exports = { WorkflowPromptGenerator };

View File

@ -0,0 +1,192 @@
/**
* Workflow prompt configuration for IDE new chat starters
*
* This configuration defines the workflow prompts that appear as suggestions
* when starting a new chat in VS Code (via chat.promptFilesRecommendations).
*
* The implementation-readiness and sprint-planning workflows update the
* VS Code settings to toggle which prompts are shown based on project phase.
*
* Reference: docs/modules/bmm-bmad-method/quick-start.md
*/
const workflowPromptsConfig = {
// BMad Method Module (bmm) - Standard development workflow
bmm: [
// ═══════════════════════════════════════════════════════════════════════
// Phase 1 - Analysis (Optional)
// ═══════════════════════════════════════════════════════════════════════
{
name: 'workflow-init',
agent: 'bmd-custom-bmm-analyst',
shortcut: 'WI',
description: '[WI] Initialize workflow and choose planning track',
prompt: '*workflow-init',
},
{
name: 'brainstorm',
agent: 'bmd-custom-bmm-analyst',
shortcut: 'BP',
description: '[BP] Brainstorm project ideas and concepts',
prompt: '*brainstorm-project',
},
{
name: 'workflow-status',
agent: 'bmd-custom-bmm-pm',
shortcut: 'WS',
description: '[WS] Check current workflow status and next steps',
prompt: '*workflow-status',
},
// ═══════════════════════════════════════════════════════════════════════
// Phase 2 - Planning (Required)
// ═══════════════════════════════════════════════════════════════════════
{
name: 'prd',
agent: 'bmd-custom-bmm-pm',
shortcut: 'PD',
description: '[PD] Create Product Requirements Document (PRD)',
prompt: '*prd',
},
{
name: 'ux-design',
agent: 'bmd-custom-bmm-ux-designer',
shortcut: 'UD',
description: '[UD] Create UX Design specification',
prompt: '*ux-design',
},
// ═══════════════════════════════════════════════════════════════════════
// Phase 3 - Solutioning
// ═══════════════════════════════════════════════════════════════════════
{
name: 'create-architecture',
agent: 'bmd-custom-bmm-architect',
shortcut: 'CA',
description: '[CA] Create system architecture document',
prompt: '*create-architecture',
},
{
name: 'epics-stories',
agent: 'bmd-custom-bmm-pm',
shortcut: 'ES',
description: '[ES] Create Epics and User Stories from PRD',
prompt: '*epics-stories',
},
{
name: 'implementation-readiness',
agent: 'bmd-custom-bmm-architect',
shortcut: 'IR',
description: '[IR] Check implementation readiness across all docs',
prompt: '*implementation-readiness',
},
{
name: 'sprint-planning',
agent: 'bmd-custom-bmm-sm',
shortcut: 'SP',
description: '[SP] Initialize sprint planning from epics',
prompt: '*sprint-planning',
},
// ═══════════════════════════════════════════════════════════════════════
// Phase 4 - Implementation: The "Keep Going" Cycle
// SM → create-story → DEV → dev-story → code-review → (create-story | retrospective)
// ═══════════════════════════════════════════════════════════════════════
{
name: 'create-story',
agent: 'bmd-custom-bmm-sm',
shortcut: 'CS',
description: '[CS] Create developer-ready story from epic',
prompt: '*create-story',
},
{
name: 'dev-story',
agent: 'bmd-custom-bmm-dev',
shortcut: 'DS',
description: '[DS] Implement the current story',
prompt: '*dev-story',
},
{
name: 'code-review',
agent: 'bmd-custom-bmm-dev',
shortcut: 'CR',
description: '[CR] Perform code review on implementation',
prompt: '*code-review',
},
{
name: 'retrospective',
agent: 'bmd-custom-bmm-sm',
shortcut: 'ER',
description: '[ER] Run epic retrospective after completion',
prompt: '*epic-retrospective',
},
{
name: 'correct-course',
agent: 'bmd-custom-bmm-sm',
shortcut: 'CC',
description: '[CC] Course correction when things go off track',
prompt: '*correct-course',
},
],
// BMad Game Development Module (bmgd)
bmgd: [
// Implementation cycle
{
name: 'game-implement',
agent: 'bmd-custom-bmgd-game-dev',
shortcut: 'GI',
description: '[GI] Implement game feature',
prompt: '*game-implement',
},
{
name: 'game-qa',
agent: 'bmd-custom-bmgd-game-qa',
shortcut: 'GQ',
description: '[GQ] Test and QA game feature',
prompt: '*game-qa',
},
// Planning & Design
{
name: 'game-design',
agent: 'bmd-custom-bmgd-game-designer',
shortcut: 'GD',
description: '[GD] Design game mechanics and systems',
prompt: '*game-design',
},
{
name: 'game-architecture',
agent: 'bmd-custom-bmgd-game-architect',
shortcut: 'GA',
description: '[GA] Create game technical architecture',
prompt: '*game-architecture',
},
{
name: 'game-sprint',
agent: 'bmd-custom-bmgd-game-scrum-master',
shortcut: 'GS',
description: '[GS] Plan game development sprint',
prompt: '*game-sprint',
},
],
// Core agents (always available)
core: [
{
name: 'list-tasks',
agent: 'bmd-custom-core-bmad-master',
shortcut: 'LT',
description: '[LT] List available tasks',
prompt: '*list-tasks',
},
{
name: 'list-workflows',
agent: 'bmd-custom-core-bmad-master',
shortcut: 'LW',
description: '[LW] List available workflows',
prompt: '*list-workflows',
},
],
};
module.exports = { workflowPromptsConfig };