Compare commits

...

4 Commits

Author SHA1 Message Date
Alex Suprun 51a3991283
Merge e9cce0f848 into c748f0f6cc 2026-01-02 02:05:45 +05:30
Brian Madison c748f0f6cc paths for workflow and sprint tatus files fixed 2026-01-01 21:20:14 +08:00
Andaman Lekawat 4142972b6a
fix: standardize variable naming from {project_root} to {project-root} (#1217)
Fixed inconsistent variable naming in workflow instruction files across
CIS, BMGD, and BMM modules. The standard variable format uses hyphens
({project-root}) not underscores ({project_root}).

Affected files:
- CIS: problem-solving, innovation-strategy, design-thinking, storytelling
- BMGD: brainstorm-game, narrative, create-story checklist
- BMM: excalidraw diagrams, create-story checklist

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Brian <bmadcode@gmail.com>
2026-01-01 21:14:21 +08:00
Alex Suprun e9cce0f848 feat(cli): add install-module command for custom module installation
Closes: #962
2025-12-31 13:30:40 +02:00
25 changed files with 229 additions and 36 deletions

View File

@ -161,7 +161,7 @@ Production workflows inherit from BMM and add game-specific overrides.
**Command:** `sprint-planning`
**Agent:** Game Scrum Master
**Input:** GDD with epics
**Output:** `{output_folder}/sprint-status.yaml`
**Output:** `{implementation_artifacts}/sprint-status.yaml`
**Description:**
Generates or updates sprint tracking from epic files. Sets up the sprint backlog and tracking.

View File

@ -1,4 +1,4 @@
<critical>The workflow execution engine is governed by: {project_root}/_bmad/core/tasks/workflow.xml</critical>
<critical>The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml</critical>
<critical>You MUST have already loaded and processed: {installed_path}/workflow.yaml</critical>
<critical>Communicate all responses in {communication_language}</critical>
<critical>This is a meta-workflow that orchestrates the CIS brainstorming workflow with game-specific context and additional game design techniques</critical>

View File

@ -2,7 +2,7 @@
<workflow>
<critical>The workflow execution engine is governed by: {project_root}/_bmad/core/tasks/workflow.xml</critical>
<critical>The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml</critical>
<critical>You MUST have already completed the GDD workflow</critical>
<critical>Communicate all responses in {communication_language}</critical>
<critical>This workflow creates detailed narrative content for story-driven games</critical>

View File

@ -12,7 +12,7 @@ user_skill_level: "{config_source}:user_skill_level"
document_output_language: "{config_source}:document_output_language"
date: system-generated
implementation_artifacts: "{config_source}:implementation_artifacts"
sprint_status: "{implementation_artifacts}/sprint-status.yaml || {output_folder}/sprint-status.yaml"
sprint_status: "{implementation_artifacts}/sprint-status.yaml"
# Workflow components
installed_path: "{project-root}/_bmad/bmgd/workflows/4-production/code-review"

View File

@ -11,7 +11,7 @@ user_skill_level: "{config_source}:user_skill_level"
document_output_language: "{config_source}:document_output_language"
date: system-generated
implementation_artifacts: "{config_source}:implementation_artifacts"
sprint_status: "{implementation_artifacts}/sprint-status.yaml || {output_folder}/sprint-status.yaml"
sprint_status: "{implementation_artifacts}/sprint-status.yaml"
# Smart input file references - handles both whole docs and sharded docs
# Priority: Whole document first, then sharded version

View File

@ -33,7 +33,7 @@ This is a COMPETITION to create the **ULTIMATE story context** that makes LLM de
### **When Running from Create-Story Workflow:**
- The `{project_root}/_bmad/core/tasks/validate-workflow.xml` framework will automatically:
- The `{project-root}/_bmad/core/tasks/validate-workflow.xml` framework will automatically:
- Load this checklist file
- Load the newly created story file (`{story_file_path}`)
- Load workflow variables from `{installed_path}/workflow.yaml`
@ -63,7 +63,7 @@ You will systematically re-do the entire story creation process, but with a crit
1. **Load the workflow configuration**: `{installed_path}/workflow.yaml` for variable inclusion
2. **Load the story file**: `{story_file_path}` (provided by user or discovered)
3. **Load validation framework**: `{project_root}/_bmad/core/tasks/validate-workflow.xml`
3. **Load validation framework**: `{project-root}/_bmad/core/tasks/validate-workflow.xml`
4. **Extract metadata**: epic_num, story_num, story_key, story_title from story file
5. **Resolve all workflow variables**: story_dir, output_folder, epics_file, architecture_file, etc.
6. **Understand current status**: What story implementation guidance is currently provided?

View File

@ -19,7 +19,7 @@ validation: "{installed_path}/checklist.md"
# Variables and inputs
variables:
sprint_status: "{implementation_artifacts}/sprint-status.yaml || {output_folder}/sprint-status.yaml" # Primary source for story tracking
sprint_status: "{implementation_artifacts}/sprint-status.yaml || {implementation_artifacts}/sprint-status.yaml" # Primary source for story tracking
epics_file: "{output_folder}/epics.md" # Preferred source for epic/story breakdown
prd_file: "{output_folder}/PRD.md" # Fallback for requirements
architecture_file: "{planning_artifacts}/architecture.md" # Optional architecture context

View File

@ -16,7 +16,7 @@ story_file: "" # Explicit story path; auto-discovered if empty
# Context file uses same story_key as story file (e.g., "1-2-user-authentication.context.xml")
context_file: "{story_dir}/{{story_key}}.context.xml"
implementation_artifacts: "{config_source}:implementation_artifacts"
sprint_status: "{implementation_artifacts}/sprint-status.yaml || {output_folder}/sprint-status.yaml"
sprint_status: "{implementation_artifacts}/sprint-status.yaml || {implementation_artifacts}/sprint-status.yaml"
# Smart input file references - handles both whole docs and sharded docs
# Priority: Whole document first, then sharded version

View File

@ -54,7 +54,7 @@ input_file_patterns:
load_strategy: "INDEX_GUIDED"
# Required files
sprint_status_file: "{implementation_artifacts}/sprint-status.yaml || {output_folder}/sprint-status.yaml"
sprint_status_file: "{implementation_artifacts}/sprint-status.yaml || {implementation_artifacts}/sprint-status.yaml"
story_directory: "{implementation_artifacts}"
retrospectives_folder: "{implementation_artifacts}"

View File

@ -18,14 +18,14 @@ instructions: "{installed_path}/instructions.md"
# Inputs
variables:
sprint_status_file: "{implementation_artifacts}/sprint-status.yaml || {output_folder}/sprint-status.yaml"
sprint_status_file: "{implementation_artifacts}/sprint-status.yaml || {implementation_artifacts}/sprint-status.yaml"
tracking_system: "file-system"
# Smart input file references
input_file_patterns:
sprint_status:
description: "Sprint status file generated by sprint-planning"
whole: "{implementation_artifacts}/sprint-status.yaml || {output_folder}/sprint-status.yaml"
whole: "{implementation_artifacts}/sprint-status.yaml || {implementation_artifacts}/sprint-status.yaml"
load_strategy: "FULL_LOAD"
# Standalone so IDE commands get generated

View File

@ -13,7 +13,7 @@ implementation_artifacts: "{config_source}:implementation_artifacts"
planning_artifacts: "{config_source}:planning_artifacts"
project_knowledge: "{config_source}:project_knowledge"
output_folder: "{implementation_artifacts}"
sprint_status: "{implementation_artifacts}/sprint-status.yaml || {output_folder}/sprint-status.yaml"
sprint_status: "{implementation_artifacts}/sprint-status.yaml"
# Smart input file references - handles both whole docs and sharded docs
# Priority: Whole document first, then sharded version

View File

@ -33,7 +33,7 @@ This is a COMPETITION to create the **ULTIMATE story context** that makes LLM de
### **When Running from Create-Story Workflow:**
- The `{project_root}/_bmad/core/tasks/validate-workflow.xml` framework will automatically:
- The `{project-root}/_bmad/core/tasks/validate-workflow.xml` framework will automatically:
- Load this checklist file
- Load the newly created story file (`{story_file_path}`)
- Load workflow variables from `{installed_path}/workflow.yaml`
@ -63,7 +63,7 @@ You will systematically re-do the entire story creation process, but with a crit
1. **Load the workflow configuration**: `{installed_path}/workflow.yaml` for variable inclusion
2. **Load the story file**: `{story_file_path}` (provided by user or discovered)
3. **Load validation framework**: `{project_root}/_bmad/core/tasks/validate-workflow.xml`
3. **Load validation framework**: `{project-root}/_bmad/core/tasks/validate-workflow.xml`
4. **Extract metadata**: epic_num, story_num, story_key, story_title from story file
5. **Resolve all workflow variables**: story_dir, output_folder, epics_file, architecture_file, etc.
6. **Understand current status**: What story implementation guidance is currently provided?

View File

@ -20,7 +20,7 @@ validation: "{installed_path}/checklist.md"
# Variables and inputs
variables:
sprint_status: "{implementation_artifacts}/sprint-status.yaml || {output_folder}/sprint-status.yaml" # Primary source for story tracking
sprint_status: "{implementation_artifacts}/sprint-status.yaml" # Primary source for story tracking
epics_file: "{planning_artifacts}/epics.md" # Enhanced epics+stories with BDD and source hints
prd_file: "{planning_artifacts}/prd.md" # Fallback for requirements (if not in epics file)
architecture_file: "{planning_artifacts}/architecture.md" # Fallback for constraints (if not in epics file)

View File

@ -19,14 +19,14 @@ instructions: "{installed_path}/instructions.md"
# Inputs
variables:
sprint_status_file: "{implementation_artifacts}/sprint-status.yaml || {output_folder}/sprint-status.yaml"
sprint_status_file: "{implementation_artifacts}/sprint-status.yaml"
tracking_system: "file-system"
# Smart input file references
input_file_patterns:
sprint_status:
description: "Sprint status file generated by sprint-planning"
whole: "{implementation_artifacts}/sprint-status.yaml || {output_folder}/sprint-status.yaml"
whole: "{implementation_artifacts}/sprint-status.yaml"
load_strategy: "FULL_LOAD"
# Standalone so IDE commands get generated

View File

@ -1,7 +1,7 @@
# Create Data Flow Diagram - Workflow Instructions
```xml
<critical>The workflow execution engine is governed by: {project_root}/_bmad/core/tasks/workflow.xml</critical>
<critical>The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml</critical>
<critical>You MUST have already loaded and processed: {installed_path}/workflow.yaml</critical>
<critical>This workflow creates data flow diagrams (DFD) in Excalidraw format.</critical>

View File

@ -1,7 +1,7 @@
# Create Diagram - Workflow Instructions
```xml
<critical>The workflow execution engine is governed by: {project_root}/_bmad/core/tasks/workflow.xml</critical>
<critical>The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml</critical>
<critical>You MUST have already loaded and processed: {installed_path}/workflow.yaml</critical>
<critical>This workflow creates system architecture diagrams, ERDs, UML diagrams, or general technical diagrams in Excalidraw format.</critical>

View File

@ -1,7 +1,7 @@
# Create Flowchart - Workflow Instructions
```xml
<critical>The workflow execution engine is governed by: {project_root}/_bmad/core/tasks/workflow.xml</critical>
<critical>The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml</critical>
<critical>You MUST have already loaded and processed: {installed_path}/workflow.yaml</critical>
<critical>This workflow creates a flowchart visualization in Excalidraw format for processes, pipelines, or logic flows.</critical>

View File

@ -1,7 +1,7 @@
# Create Wireframe - Workflow Instructions
```xml
<critical>The workflow execution engine is governed by: {project_root}/_bmad/core/tasks/workflow.xml</critical>
<critical>The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml</critical>
<critical>You MUST have already loaded and processed: {installed_path}/workflow.yaml</critical>
<critical>This workflow creates website or app wireframes in Excalidraw format.</critical>

View File

@ -25,11 +25,11 @@ The workflow auto-detects which mode to use based on project phase.
### Mode Detection
1. **Check for sprint-status.yaml**
- If `{output_folder}/bmm-sprint-status.yaml` exists → **Epic-Level Mode** (Phase 4)
- If `{implementation_artifacts}/sprint-status.yaml` exists → **Epic-Level Mode** (Phase 4)
- If NOT exists → Check workflow status
2. **Check workflow-status.yaml**
- Read `{output_folder}/bmm-workflow-status.yaml`
- Read `{planning_artifacts}/bmm-workflow-status.yaml`
- If `implementation-readiness: required` or `implementation-readiness: recommended`**System-Level Mode** (Phase 3)
- Otherwise → **Epic-Level Mode** (Phase 4 without sprint status yet)

View File

@ -197,7 +197,7 @@ Your choice:</ask>
<!-- ============================================= -->
<step n="10" goal="Validate mode - Check if calling workflow should proceed">
<action>Read {output_folder}/bmm-workflow-status.yaml if exists</action>
<action>Read {planning_artifacts}/bmm-workflow-status.yaml if exists</action>
<check if="status file not found">
<template-output>status_exists = false</template-output>
@ -261,7 +261,7 @@ Your choice:</ask>
</step>
<step n="20" goal="Data mode - Extract specific information">
<action>Read {output_folder}/bmm-workflow-status.yaml if exists</action>
<action>Read {planning_artifacts}/bmm-workflow-status.yaml if exists</action>
<check if="status file not found">
<template-output>status_exists = false</template-output>
@ -309,7 +309,7 @@ Your choice:</ask>
</step>
<step n="30" goal="Init-check mode - Simple existence check">
<action>Check if {output_folder}/bmm-workflow-status.yaml exists</action>
<action>Check if {planning_artifacts}/bmm-workflow-status.yaml exists</action>
<check if="exists">
<template-output>status_exists = true</template-output>
@ -325,7 +325,7 @@ Your choice:</ask>
</step>
<step n="40" goal="Update mode - Centralized status file updates">
<action>Read {output_folder}/bmm-workflow-status.yaml</action>
<action>Read {planning_artifacts}/bmm-workflow-status.yaml</action>
<check if="status file not found">
<template-output>success = false</template-output>

View File

@ -1,7 +1,7 @@
# Design Thinking Workflow Instructions
<critical>The workflow execution engine is governed by: {project_root}/_bmad/core/tasks/workflow.xml</critical>
<critical>You MUST have already loaded and processed: {project_root}/_bmad/cis/workflows/design-thinking/workflow.yaml</critical>
<critical>The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml</critical>
<critical>You MUST have already loaded and processed: {project-root}/_bmad/cis/workflows/design-thinking/workflow.yaml</critical>
<critical>Load and understand design methods from: {design_methods}</critical>
<critical>⚠️ ABSOLUTELY NO TIME ESTIMATES - NEVER mention hours, days, weeks, months, or ANY time-based predictions. AI has fundamentally changed development speed - what once took teams weeks/months can now be done by one person in hours. DO NOT give ANY time estimates whatsoever.</critical>
<critical>⚠️ CHECKPOINT PROTOCOL: After EVERY <template-output> tag, you MUST follow workflow.xml substep 2c: SAVE content to file immediately → SHOW checkpoint separator (━━━━━━━━━━━━━━━━━━━━━━━) → DISPLAY generated content → PRESENT options [a]Advanced Elicitation/[c]Continue/[p]Party-Mode/[y]YOLO → WAIT for user response. Never batch saves or skip checkpoints.</critical>

View File

@ -1,7 +1,7 @@
# Innovation Strategy Workflow Instructions
<critical>The workflow execution engine is governed by: {project_root}/_bmad/core/tasks/workflow.xml</critical>
<critical>You MUST have already loaded and processed: {project_root}/_bmad/cis/workflows/innovation-strategy/workflow.yaml</critical>
<critical>The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml</critical>
<critical>You MUST have already loaded and processed: {project-root}/_bmad/cis/workflows/innovation-strategy/workflow.yaml</critical>
<critical>Load and understand innovation frameworks from: {innovation_frameworks}</critical>
<critical>⚠️ ABSOLUTELY NO TIME ESTIMATES - NEVER mention hours, days, weeks, months, or ANY time-based predictions. AI has fundamentally changed development speed - what once took teams weeks/months can now be done by one person in hours. DO NOT give ANY time estimates whatsoever.</critical>
<critical>⚠️ CHECKPOINT PROTOCOL: After EVERY <template-output> tag, you MUST follow workflow.xml substep 2c: SAVE content to file immediately → SHOW checkpoint separator (━━━━━━━━━━━━━━━━━━━━━━━) → DISPLAY generated content → PRESENT options [a]Advanced Elicitation/[c]Continue/[p]Party-Mode/[y]YOLO → WAIT for user response. Never batch saves or skip checkpoints.</critical>

View File

@ -1,7 +1,7 @@
# Problem Solving Workflow Instructions
<critical>The workflow execution engine is governed by: {project_root}/_bmad/core/tasks/workflow.xml</critical>
<critical>You MUST have already loaded and processed: {project_root}/_bmad/cis/workflows/problem-solving/workflow.yaml</critical>
<critical>The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml</critical>
<critical>You MUST have already loaded and processed: {project-root}/_bmad/cis/workflows/problem-solving/workflow.yaml</critical>
<critical>Load and understand solving methods from: {solving_methods}</critical>
<critical>⚠️ ABSOLUTELY NO TIME ESTIMATES - NEVER mention hours, days, weeks, months, or ANY time-based predictions. AI has fundamentally changed development speed - what once took teams weeks/months can now be done by one person in hours. DO NOT give ANY time estimates whatsoever.</critical>
<critical>⚠️ CHECKPOINT PROTOCOL: After EVERY <template-output> tag, you MUST follow workflow.xml substep 2c: SAVE content to file immediately → SHOW checkpoint separator (━━━━━━━━━━━━━━━━━━━━━━━) → DISPLAY generated content → PRESENT options [a]Advanced Elicitation/[c]Continue/[p]Party-Mode/[y]YOLO → WAIT for user response. Never batch saves or skip checkpoints.</critical>

View File

@ -3,8 +3,8 @@
## Workflow
<workflow>
<critical>The workflow execution engine is governed by: {project_root}/_bmad/core/tasks/workflow.xml</critical>
<critical>You MUST have already loaded and processed: {project_root}/_bmad/cis/workflows/storytelling/workflow.yaml</critical>
<critical>The workflow execution engine is governed by: {project-root}/_bmad/core/tasks/workflow.xml</critical>
<critical>You MUST have already loaded and processed: {project-root}/_bmad/cis/workflows/storytelling/workflow.yaml</critical>
<critical>Communicate all responses in {communication_language}</critical>
<critical>⚠️ ABSOLUTELY NO TIME ESTIMATES - NEVER mention hours, days, weeks, months, or ANY time-based predictions. AI has fundamentally changed development speed - what once took teams weeks/months can now be done by one person in hours. DO NOT give ANY time estimates whatsoever.</critical>
<critical>⚠️ CHECKPOINT PROTOCOL: After EVERY <template-output> tag, you MUST follow workflow.xml substep 2c: SAVE content to file immediately → SHOW checkpoint separator (━━━━━━━━━━━━━━━━━━━━━━━) → DISPLAY generated content → PRESENT options [a]Advanced Elicitation/[c]Continue/[p]Party-Mode/[y]YOLO → WAIT for user response. Never batch saves or skip checkpoints.</critical>

View File

@ -0,0 +1,193 @@
const chalk = require('chalk');
const path = require('node:path');
const fs = require('fs-extra');
const yaml = require('yaml');
const ora = require('ora');
const { Installer } = require('../installers/lib/core/installer');
const { ModuleManager } = require('../installers/lib/modules/manager');
const { Manifest } = require('../installers/lib/core/manifest');
const { ManifestGenerator } = require('../installers/lib/core/manifest-generator');
module.exports = {
command: 'install-module <path>',
description: 'Install a custom BMAD module from local path',
options: [['-f, --force', 'Force reinstall if module already exists']],
action: async (modulePath, options) => {
const spinner = ora();
try {
// Step 1: Validate module path exists
const absolutePath = path.resolve(modulePath);
if (!(await fs.pathExists(absolutePath))) {
console.error(chalk.red(`Error: Path does not exist: ${absolutePath}`));
process.exit(1);
}
const moduleYamlPath = path.join(absolutePath, 'module.yaml');
if (!(await fs.pathExists(moduleYamlPath))) {
console.error(chalk.red(`Error: Invalid module - module.yaml not found at ${absolutePath}`));
process.exit(1);
}
// Read module.yaml to get module code
const moduleYamlContent = await fs.readFile(moduleYamlPath, 'utf8');
const moduleConfig = yaml.parse(moduleYamlContent);
const moduleCode = moduleConfig.code;
if (!moduleCode) {
console.error(chalk.red('Error: module.yaml must have a "code" field'));
process.exit(1);
}
console.log(chalk.cyan(`\n📦 Installing module: ${moduleConfig.name || moduleCode}`));
if (moduleConfig.version) {
console.log(chalk.dim(` Version: ${moduleConfig.version}`));
}
// Step 2: Find BMAD installation
const installer = new Installer();
const { bmadDir } = await installer.findBmadDir(process.cwd());
// Check if manifest exists (confirms BMAD is actually installed)
const manifest = new Manifest();
const manifestData = await manifest.read(bmadDir);
if (!manifestData) {
console.error(chalk.red('\nError: No BMAD installation found.'));
console.log(chalk.yellow('Run `npx bmad-method install` first to set up BMAD.'));
process.exit(1);
}
console.log(chalk.green(`✓ Found BMAD installation at ${bmadDir}`));
// Step 3: Check if already installed
if (manifestData.modules && manifestData.modules.includes(moduleCode) && !options.force) {
console.error(chalk.red(`\nError: Module '${moduleCode}' is already installed.`));
console.log(chalk.yellow('Use --force to reinstall.'));
process.exit(1);
}
// Step 4: Install module using ModuleManager
spinner.start('Installing module files...');
const moduleManager = new ModuleManager();
moduleManager.setCustomModulePaths(new Map([[moduleCode, absolutePath]]));
moduleManager.setBmadFolderName(path.basename(bmadDir));
await moduleManager.install(moduleCode, bmadDir, null, {
skipModuleInstaller: false,
moduleConfig: moduleConfig,
});
spinner.succeed('Module files installed');
// Step 5: Regenerate manifests
spinner.start('Regenerating manifests...');
const manifestGen = new ManifestGenerator();
// Get all modules including the new one
const allModules = [...(manifestData.modules || [])];
if (!allModules.includes(moduleCode)) {
allModules.push(moduleCode);
}
await manifestGen.generateManifests(bmadDir, allModules, [], {
ides: manifestData.ides || [],
});
spinner.succeed('Manifests regenerated');
// Step 6: Regenerate IDE commands
const projectDir = path.dirname(bmadDir);
const installedIDEs = manifestData.ides || [];
if (installedIDEs.includes('claude-code')) {
spinner.start('Generating Claude Code commands...');
const { WorkflowCommandGenerator } = require('../installers/lib/ide/shared/workflow-command-generator');
const { AgentCommandGenerator } = require('../installers/lib/ide/shared/agent-command-generator');
const { TaskToolCommandGenerator } = require('../installers/lib/ide/shared/task-tool-command-generator');
const bmadFolderName = path.basename(bmadDir);
const bmadCommandsDir = path.join(projectDir, '.claude', 'commands', 'bmad');
// Generate agent launchers
const agentGen = new AgentCommandGenerator(bmadFolderName);
const { artifacts: agentArtifacts } = await agentGen.collectAgentArtifacts(bmadDir, allModules);
// Create module directories
await fs.ensureDir(path.join(bmadCommandsDir, moduleCode, 'agents'));
await fs.ensureDir(path.join(bmadCommandsDir, moduleCode, 'workflows'));
// Write agent launchers
await agentGen.writeAgentLaunchers(bmadCommandsDir, agentArtifacts);
// Generate workflow commands
const wfGen = new WorkflowCommandGenerator(bmadFolderName);
const { artifacts: workflowArtifacts } = await wfGen.collectWorkflowArtifacts(bmadDir);
// Write workflow commands
for (const artifact of workflowArtifacts) {
if (artifact.type === 'workflow-command') {
const moduleWorkflowsDir = path.join(bmadCommandsDir, artifact.module, 'workflows');
await fs.ensureDir(moduleWorkflowsDir);
const commandPath = path.join(moduleWorkflowsDir, path.basename(artifact.relativePath));
await fs.writeFile(commandPath, artifact.content);
}
}
// Generate task/tool commands
const taskGen = new TaskToolCommandGenerator();
await taskGen.generateTaskToolCommands(projectDir, bmadDir);
spinner.succeed('Claude Code commands generated');
}
// Step 7: Update manifest
await manifest.addModule(bmadDir, moduleCode);
// Success message
console.log(chalk.green(`\n✨ Module '${moduleCode}' installed successfully!`));
// Show available commands
const commandsDir = path.join(projectDir, '.claude', 'commands', 'bmad', moduleCode);
if (await fs.pathExists(commandsDir)) {
console.log(chalk.cyan('\nAvailable commands:'));
const agentsDir = path.join(commandsDir, 'agents');
const workflowsDir = path.join(commandsDir, 'workflows');
if (await fs.pathExists(agentsDir)) {
const agents = await fs.readdir(agentsDir);
for (const agent of agents.filter((f) => f.endsWith('.md') && f !== 'README.md')) {
console.log(chalk.dim(` /${moduleCode}:${path.basename(agent, '.md')}`));
}
}
if (await fs.pathExists(workflowsDir)) {
const workflows = await fs.readdir(workflowsDir);
for (const wf of workflows.filter((f) => f.endsWith('.md') && f !== 'README.md')) {
console.log(chalk.dim(` /${moduleCode}:${path.basename(wf, '.md')}`));
}
}
}
process.exit(0);
} catch (error) {
spinner.fail('Installation failed');
if (error.fullMessage) {
console.error(error.fullMessage);
} else {
console.error(chalk.red('Error:'), error.message);
}
if (process.env.BMAD_VERBOSE_INSTALL === 'true') {
console.error(chalk.dim(error.stack));
}
process.exit(1);
}
},
};