From ae9851acab502f6f0d1e28e5e1038f7b74966bd2 Mon Sep 17 00:00:00 2001 From: Brian Madison Date: Sat, 13 Dec 2025 19:41:09 +0800 Subject: [PATCH] _cfg -> _config --- docs/agent-customization-guide.md | 14 +- .../installers-modules-platforms-reference.md | 6 +- docs/v4-to-v6-upgrade.md | 10 +- docs/web-bundles-gemini-gpt-guide.md | 2 +- src/core/agents/bmad-master.agent.yaml | 4 +- src/core/tasks/advanced-elicitation.xml | 2 +- .../party-mode/steps/step-01-agent-loading.md | 4 +- src/core/workflows/party-mode/workflow.md | 4 +- .../bmb/docs/agents/agent-menu-patterns.md | 2 +- .../docs/agents/module-agent-architecture.md | 4 +- .../create-agent/steps/step-09-customize.md | 2 +- .../bmb/workflows/create-agent/workflow.md | 2 +- .../bmgd/agents/game-scrum-master.agent.yaml | 2 +- .../4-production/retrospective/workflow.yaml | 2 +- src/modules/bmm/agents/sm.agent.yaml | 2 +- src/modules/bmm/docs/agents-guide.md | 8 +- src/modules/bmm/docs/faq.md | 2 +- src/modules/bmm/docs/party-mode.md | 4 +- .../retrospective/workflow.yaml | 2 +- tools/cli/commands/build.js | 8 +- .../installers/lib/core/config-collector.js | 10 +- .../lib/core/custom-module-cache.js | 4 +- tools/cli/installers/lib/core/detector.js | 10 +- .../installers/lib/core/ide-config-manager.js | 4 +- tools/cli/installers/lib/core/installer.js | 146 +++++++++++++----- .../installers/lib/core/manifest-generator.js | 6 +- tools/cli/installers/lib/core/manifest.js | 8 +- tools/cli/installers/lib/custom/handler.js | 2 +- tools/cli/installers/lib/ide/_base-ide.js | 10 +- .../ide/shared/task-tool-command-generator.js | 4 +- .../ide/shared/workflow-command-generator.js | 2 +- tools/cli/installers/lib/modules/manager.js | 10 +- tools/cli/lib/agent-party-generator.js | 2 +- tools/cli/lib/agent/installer.js | 10 +- tools/cli/lib/ui.js | 4 +- tools/cli/lib/yaml-xml-builder.js | 2 +- tools/migrate-custom-module-paths.js | 2 +- 37 files changed, 192 insertions(+), 130 deletions(-) diff --git a/docs/agent-customization-guide.md b/docs/agent-customization-guide.md index 8d8616f6..24f54716 100644 --- a/docs/agent-customization-guide.md +++ b/docs/agent-customization-guide.md @@ -9,7 +9,7 @@ Customize BMad agents without modifying core files. All customizations persist t After installation, find agent customization files in: ``` -_bmad/_cfg/agents/ +_bmad/_config/agents/ ├── core-bmad-master.customize.yaml ├── bmm-dev.customize.yaml ├── bmm-pm.customize.yaml @@ -119,7 +119,7 @@ prompts: **Example 1: Customize Developer Agent for TDD** ```yaml -# _bmad/_cfg/agents/bmm-dev.customize.yaml +# _bmad/_config/agents/bmm-dev.customize.yaml agent: metadata: name: 'TDD Developer' @@ -135,7 +135,7 @@ critical_actions: **Example 2: Add Custom Deployment Workflow** ```yaml -# _bmad/_cfg/agents/bmm-dev.customize.yaml +# _bmad/_config/agents/bmm-dev.customize.yaml menu: - trigger: deploy-staging workflow: '{project-root}/_bmad/deploy-staging.yaml' @@ -148,7 +148,7 @@ menu: **Example 3: Multilingual Product Manager** ```yaml -# _bmad/_cfg/agents/bmm-pm.customize.yaml +# _bmad/_config/agents/bmm-pm.customize.yaml persona: role: 'Bilingual Product Manager' identity: 'Expert in US and LATAM markets' @@ -166,15 +166,15 @@ memories: - **Start Small:** Customize one section at a time and rebuild to test - **Backup:** Copy customization files before major changes -- **Update-Safe:** Your customizations in `_cfg/` survive all BMad updates +- **Update-Safe:** Your customizations in `_config/` survive all BMad updates - **Per-Project:** Customization files are per-project, not global -- **Version Control:** Consider committing `_cfg/` to share customizations with your team +- **Version Control:** Consider committing `_config/` to share customizations with your team ## Module vs. Global Config **Module-Level (Recommended):** -- Customize agents per-project in `_bmad/_cfg/agents/` +- Customize agents per-project in `_bmad/_config/agents/` - Different projects can have different agent behaviors **Global Config (Coming Soon):** diff --git a/docs/installers-bundlers/installers-modules-platforms-reference.md b/docs/installers-bundlers/installers-modules-platforms-reference.md index efee049b..3167045f 100644 --- a/docs/installers-bundlers/installers-modules-platforms-reference.md +++ b/docs/installers-bundlers/installers-modules-platforms-reference.md @@ -28,7 +28,7 @@ BMad Core is a modular AI agent framework with intelligent installation, platfor ``` project-root/ ├── _bmad/ # Centralized installation -│ ├── _cfg/ # Configuration +│ ├── _config/ # Configuration │ │ ├── agents/ # Agent configs │ │ └── agent-manifest.csv # Agent manifest │ ├── core/ # Core module @@ -265,7 +265,7 @@ Extractable config nodes: ``` -Generated in: `bmad/_cfg/agents/{module}-{agent}.md` +Generated in: `bmad/_config/agents/{module}-{agent}.md` ## Troubleshooting @@ -290,7 +290,7 @@ bmad status -v # Detailed status ### Best Practices 1. Run from project root -2. Backup `_bmad/_cfg/` before updates +2. Backup `_bmad/_config/` before updates 3. Use interactive mode for guidance 4. Review generated configs post-install diff --git a/docs/v4-to-v6-upgrade.md b/docs/v4-to-v6-upgrade.md index dbc6f35d..788d570a 100644 --- a/docs/v4-to-v6-upgrade.md +++ b/docs/v4-to-v6-upgrade.md @@ -68,7 +68,7 @@ your-project/ ├── bmm/ # BMad Method (software/game dev) ├── bmb/ # BMad Builder (create agents/workflows) ├── cis/ # Creative Intelligence Suite - └── _cfg/ # Your customizations + └── _config/ # Your customizations └── agents/ # Agent customization files ``` @@ -114,11 +114,11 @@ In v4, you may have modified agent files directly in `_bmad-*` folders. ### v6 Agent Customization -**All customizations** now go in `_bmad/_cfg/agents/` using customize files: +**All customizations** now go in `_bmad/_config/agents/` using customize files: **Example: Renaming an agent and changing communication style** -File: `_bmad/_cfg/agents/bmm-pm.customize.yaml` +File: `_bmad/_config/agents/bmm-pm.customize.yaml` ```yaml # Customize the PM agent @@ -134,7 +134,7 @@ persona: **How it works:** - Base agent: `_bmad/bmm/agents/pm.md` -- Customization: `_bmad/_cfg/agents/bmm-pm.customize.yaml` +- Customization: `_bmad/_config/agents/bmm-pm.customize.yaml` - Result: Agent uses your custom name and style, but updates don't overwrite your changes --- @@ -214,7 +214,7 @@ Since you are migrating an existing project from v4, it's most likely **Level 3 - [ ] v4 folders backed up to `v4-backup/` - [ ] v6 installed to `_bmad/` folder - [ ] `workflow-init` run with correct project level selected -- [ ] Agent customizations migrated to `_bmad/_cfg/agents/` if needed +- [ ] Agent customizations migrated to `_bmad/_config/agents/` if needed - [ ] IDE integration working (test by listing agents) - [ ] For active development: `sprint-planning` workflow executed diff --git a/docs/web-bundles-gemini-gpt-guide.md b/docs/web-bundles-gemini-gpt-guide.md index 3b2b00cd..cad1cb88 100644 --- a/docs/web-bundles-gemini-gpt-guide.md +++ b/docs/web-bundles-gemini-gpt-guide.md @@ -336,7 +336,7 @@ Agents adapt their menus based on project phase and available workflows. Customize agents using the [Agent Customization Guide](./agent-customization-guide.md): -1. Edit `_bmad/_cfg/agents/.customize.yaml` +1. Edit `_bmad/_config/agents/.customize.yaml` 2. Rebuild: `npx bmad-method build ` 3. Generate bundles: `npm run bundle` diff --git a/src/core/agents/bmad-master.agent.yaml b/src/core/agents/bmad-master.agent.yaml index ed0e74ff..ae89108e 100644 --- a/src/core/agents/bmad-master.agent.yaml +++ b/src/core/agents/bmad-master.agent.yaml @@ -24,11 +24,11 @@ agent: # Agent menu items menu: - trigger: "list-tasks" - action: "list all tasks from {project-root}/_bmad/_cfg/task-manifest.csv" + action: "list all tasks from {project-root}/_bmad/_config/task-manifest.csv" description: "List Available Tasks" - trigger: "list-workflows" - action: "list all workflows from {project-root}/_bmad/_cfg/workflow-manifest.csv" + action: "list all workflows from {project-root}/_bmad/_config/workflow-manifest.csv" description: "List Workflows" - trigger: "party-mode" diff --git a/src/core/tasks/advanced-elicitation.xml b/src/core/tasks/advanced-elicitation.xml index 598a96c9..3263dddf 100644 --- a/src/core/tasks/advanced-elicitation.xml +++ b/src/core/tasks/advanced-elicitation.xml @@ -1,6 +1,6 @@ + agent-party="{project-root}/_bmad/_config/agent-manifest.csv"> MANDATORY: Execute ALL steps in the flow section IN EXACT ORDER DO NOT skip steps or change the sequence diff --git a/src/core/workflows/party-mode/steps/step-01-agent-loading.md b/src/core/workflows/party-mode/steps/step-01-agent-loading.md index 569d6bd1..acd02879 100644 --- a/src/core/workflows/party-mode/steps/step-01-agent-loading.md +++ b/src/core/workflows/party-mode/steps/step-01-agent-loading.md @@ -18,7 +18,7 @@ ## CONTEXT BOUNDARIES: -- Agent manifest CSV is available at `{project-root}/_bmad/_cfg/agent-manifest.csv` +- Agent manifest CSV is available at `{project-root}/_bmad/_config/agent-manifest.csv` - User configuration from config.yaml is loaded and resolved - Party mode is standalone interactive workflow - All agent data is available for conversation orchestration @@ -37,7 +37,7 @@ Begin agent loading process: **Agent Manifest Loading:**" -Load and parse the agent manifest CSV from `{project-root}/_bmad/_cfg/agent-manifest.csv` +Load and parse the agent manifest CSV from `{project-root}/_bmad/_config/agent-manifest.csv` ### 2. Extract Agent Data diff --git a/src/core/workflows/party-mode/workflow.md b/src/core/workflows/party-mode/workflow.md index fb15f567..558c5e1e 100644 --- a/src/core/workflows/party-mode/workflow.md +++ b/src/core/workflows/party-mode/workflow.md @@ -32,12 +32,12 @@ Load config from `{project-root}/_bmad/core/config.yaml` and resolve: - `project_name`, `output_folder`, `user_name` - `communication_language`, `document_output_language`, `user_skill_level` - `date` as a system-generated value -- Agent manifest path: `{project-root}/_bmad/_cfg/agent-manifest.csv` +- Agent manifest path: `{project-root}/_bmad/_config/agent-manifest.csv` ### Paths - `installed_path` = `{project-root}/_bmad/core/workflows/party-mode` -- `agent_manifest_path` = `{project-root}/_bmad/_cfg/agent-manifest.csv` +- `agent_manifest_path` = `{project-root}/_bmad/_config/agent-manifest.csv` - `standalone_mode` = `true` (party mode is an interactive workflow) --- diff --git a/src/modules/bmb/docs/agents/agent-menu-patterns.md b/src/modules/bmb/docs/agents/agent-menu-patterns.md index 85ee67ca..df5a4bd1 100644 --- a/src/modules/bmb/docs/agents/agent-menu-patterns.md +++ b/src/modules/bmb/docs/agents/agent-menu-patterns.md @@ -132,7 +132,7 @@ Universal attribute for supplementary information. menu: - trigger: team-standup exec: '{project-root}/_bmad/bmm/tasks/standup.xml' - data: '{project-root}/_bmad/_cfg/agent-manifest.csv' + data: '{project-root}/_bmad/_config/agent-manifest.csv' description: 'Run team standup' - trigger: analyze-metrics diff --git a/src/modules/bmb/docs/agents/module-agent-architecture.md b/src/modules/bmb/docs/agents/module-agent-architecture.md index 8bd55054..774e7125 100644 --- a/src/modules/bmb/docs/agents/module-agent-architecture.md +++ b/src/modules/bmb/docs/agents/module-agent-architecture.md @@ -63,7 +63,7 @@ agent: - trigger: with-data exec: '{project-root}/_bmad/{module-code}/tasks/{task-name}.xml' - data: '{project-root}/_bmad/_cfg/agent-manifest.csv' + data: '{project-root}/_bmad/_config/agent-manifest.csv' description: 'Execute task with data file' ``` @@ -136,7 +136,7 @@ Combines task execution with template file. menu: - trigger: team-standup exec: '{project-root}/_bmad/bmm/tasks/standup.xml' - data: '{project-root}/_bmad/_cfg/agent-manifest.csv' + data: '{project-root}/_bmad/_config/agent-manifest.csv' description: 'Run team standup with agent roster' ``` diff --git a/src/modules/bmb/workflows/create-agent/steps/step-09-customize.md b/src/modules/bmb/workflows/create-agent/steps/step-09-customize.md index de9370ae..240cb36c 100644 --- a/src/modules/bmb/workflows/create-agent/steps/step-09-customize.md +++ b/src/modules/bmb/workflows/create-agent/steps/step-09-customize.md @@ -10,7 +10,7 @@ thisStepFile: '{workflow_path}/steps/step-09-customize.md' nextStepFile: '{workflow_path}/steps/step-10-build-tools.md' workflowFile: '{workflow_path}/workflow.md' outputFile: '{output_folder}/agent-customization-{project_name}.md' -configOutputFile: '{project-root}/_bmad/_cfg/agents/{target_module}-{agent_filename}.customize.yaml' +configOutputFile: '{project-root}/_bmad/_config/agents/{target_module}-{agent_filename}.customize.yaml' # Template References customizationTemplate: '{workflow_path}/templates/agent-customization.md' diff --git a/src/modules/bmb/workflows/create-agent/workflow.md b/src/modules/bmb/workflows/create-agent/workflow.md index 99b77caa..604f05a2 100644 --- a/src/modules/bmb/workflows/create-agent/workflow.md +++ b/src/modules/bmb/workflows/create-agent/workflow.md @@ -88,4 +88,4 @@ module_output_file: "{project-root}/\_bmad/{target_module}/agents/{agent_filenam standalone_output_folder: "{custom_agent_location}/{agent_filename}" standalone_output_file: "{standalone_output_folder}/{agent_filename}.agent.yaml" standalone_info_guide: "{standalone_output_folder}/info-and-installation-guide.md" -config_output_file: "{project-root}/\_bmad/\_cfg/agents/{target_module}-{agent_filename}.customize.yaml" +config_output_file: "{project-root}/\_bmad/\_config/agents/{target_module}-{agent_filename}.customize.yaml" diff --git a/src/modules/bmgd/agents/game-scrum-master.agent.yaml b/src/modules/bmgd/agents/game-scrum-master.agent.yaml index c67f72f4..22e786d8 100644 --- a/src/modules/bmgd/agents/game-scrum-master.agent.yaml +++ b/src/modules/bmgd/agents/game-scrum-master.agent.yaml @@ -58,7 +58,7 @@ agent: - trigger: epic-retrospective workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml" workflow-install: "{project-root}/_bmad/bmgd/workflows/4-production/retrospective/workflow.yaml" - data: "{project-root}/_bmad/_cfg/agent-manifest.csv" + data: "{project-root}/_bmad/_config/agent-manifest.csv" description: (Optional) Facilitate team retrospective after a game development epic is completed - trigger: correct-course diff --git a/src/modules/bmgd/workflows/4-production/retrospective/workflow.yaml b/src/modules/bmgd/workflows/4-production/retrospective/workflow.yaml index 65a6f733..13e50d4b 100644 --- a/src/modules/bmgd/workflows/4-production/retrospective/workflow.yaml +++ b/src/modules/bmgd/workflows/4-production/retrospective/workflow.yaml @@ -17,7 +17,7 @@ template: false instructions: "{installed_path}/instructions.md" required_inputs: - - agent_manifest: "{project-root}/_bmad/_cfg/agent-manifest.csv" + - agent_manifest: "{project-root}/_bmad/_config/agent-manifest.csv" # Smart input file references - handles both whole docs and sharded docs # Priority: Whole document first, then sharded version diff --git a/src/modules/bmm/agents/sm.agent.yaml b/src/modules/bmm/agents/sm.agent.yaml index a43f355f..26e2fe06 100644 --- a/src/modules/bmm/agents/sm.agent.yaml +++ b/src/modules/bmm/agents/sm.agent.yaml @@ -38,7 +38,7 @@ agent: - trigger: epic-retrospective workflow: "{project-root}/_bmad/bmm/workflows/4-implementation/retrospective/workflow.yaml" - data: "{project-root}/_bmad/_cfg/agent-manifest.csv" + data: "{project-root}/_bmad/_config/agent-manifest.csv" description: Facilitate team retrospective after an epic is completed (Optional) - trigger: correct-course diff --git a/src/modules/bmm/docs/agents-guide.md b/src/modules/bmm/docs/agents-guide.md index ce6d0923..b8643f34 100644 --- a/src/modules/bmm/docs/agents-guide.md +++ b/src/modules/bmm/docs/agents-guide.md @@ -663,14 +663,14 @@ You can customize any agent's personality without modifying core agent files. ### Location -**Customization Directory:** `{project-root}/_bmad/_cfg/agents/` +**Customization Directory:** `{project-root}/_bmad/_config/agents/` **Naming Convention:** `{module}-{agent-name}.customize.yaml` **Examples:** ``` -_bmad/_cfg/agents/ +_bmad/_config/agents/ ├── bmm-pm.customize.yaml ├── bmm-dev.customize.yaml ├── cis-storyteller.customize.yaml @@ -770,9 +770,9 @@ Other agents collaborate with PM's specialized perspective. ```bash # Create customization file at: -# {project-root}/_bmad/_cfg/agents/{module}-{agent-name}.customize.yaml +# {project-root}/_bmad/_config/agents/{module}-{agent-name}.customize.yaml -# Example: _bmad/_cfg/agents/bmm-pm.customize.yaml +# Example: _bmad/_config/agents/bmm-pm.customize.yaml ``` **Step 2: Regenerate Agent Manifest** diff --git a/src/modules/bmm/docs/faq.md b/src/modules/bmm/docs/faq.md index 0f1298fb..f9d9365d 100644 --- a/src/modules/bmm/docs/faq.md +++ b/src/modules/bmm/docs/faq.md @@ -358,7 +358,7 @@ See [IDE Setup Guides](https://github.com/bmad-code-org/BMAD-METHOD/tree/main/do ### Q: Can I customize agents? -**A:** Yes! Agents are installed as markdown files with XML-style content (optimized for LLMs, readable by any model). Create customization files in `_bmad/_cfg/agents/[agent-name].customize.yaml` to override default behaviors while keeping core functionality intact. See agent documentation for customization options. +**A:** Yes! Agents are installed as markdown files with XML-style content (optimized for LLMs, readable by any model). Create customization files in `_bmad/_config/agents/[agent-name].customize.yaml` to override default behaviors while keeping core functionality intact. See agent documentation for customization options. **Note:** While source agents in this repo are YAML, they install as `.md` files with XML-style tags - a format any LLM can read and follow. diff --git a/src/modules/bmm/docs/party-mode.md b/src/modules/bmm/docs/party-mode.md index 613bf360..287e5022 100644 --- a/src/modules/bmm/docs/party-mode.md +++ b/src/modules/bmm/docs/party-mode.md @@ -27,7 +27,7 @@ Type `/bmad:core:workflows:party-mode` (or `*party-mode` from any agent), and su **The basics:** -1. Party mode reads `_bmad/_cfg/agent-manifest.csv` +1. Party mode reads `_bmad/_config/agent-manifest.csv` 2. Loads ALL installed agents (already includes your customizations from install) 3. BMad Master orchestrates - picks 2-3 relevant agents per message based on topic 4. Agents respond in character, can agree/disagree/build on each other's ideas @@ -130,7 +130,7 @@ Party mode uses agents from `_bmad/[module]/agents/*.md` - these already include **To customize agents for party mode:** -1. Create customization file: `_bmad/_cfg/agents/bmm-pm.customize.yaml` +1. Create customization file: `_bmad/_config/agents/bmm-pm.customize.yaml` 2. Run `npx bmad-method install` to rebuild agents 3. Customizations now active in party mode diff --git a/src/modules/bmm/workflows/4-implementation/retrospective/workflow.yaml b/src/modules/bmm/workflows/4-implementation/retrospective/workflow.yaml index 291b7698..1dab9765 100644 --- a/src/modules/bmm/workflows/4-implementation/retrospective/workflow.yaml +++ b/src/modules/bmm/workflows/4-implementation/retrospective/workflow.yaml @@ -17,7 +17,7 @@ template: false instructions: "{installed_path}/instructions.md" required_inputs: - - agent_manifest: "{project-root}/_bmad/_cfg/agent-manifest.csv" + - agent_manifest: "{project-root}/_bmad/_config/agent-manifest.csv" # Smart input file references - handles both whole docs and sharded docs # Priority: Whole document first, then sharded version diff --git a/tools/cli/commands/build.js b/tools/cli/commands/build.js index ff4419cc..467fcd65 100644 --- a/tools/cli/commands/build.js +++ b/tools/cli/commands/build.js @@ -99,7 +99,7 @@ async function buildAgent(projectDir, agentName) { // Build the standalone agent console.log(chalk.cyan(` Building standalone agent ${agentName}...`)); - const customizePath = path.join(projectDir, '_bmad', '_cfg', 'agents', `${agentName}.customize.yaml`); + const customizePath = path.join(projectDir, '_bmad', '_config', 'agents', `${agentName}.customize.yaml`); const customizeExists = await fs.pathExists(customizePath); await builder.buildAgent(standaloneYamlPath, customizeExists ? customizePath : null, outputPath, { includeMetadata: true }); @@ -125,7 +125,7 @@ async function buildAgent(projectDir, agentName) { // Build the agent console.log(chalk.cyan(` Building ${agentName}...`)); - const customizePath = path.join(projectDir, '.claude', '_cfg', 'agents', `${agentName}.customize.yaml`); + const customizePath = path.join(projectDir, '.claude', '_config', 'agents', `${agentName}.customize.yaml`); const customizeExists = await fs.pathExists(customizePath); await builder.buildAgent(agentYamlPath, customizeExists ? customizePath : null, outputPath, { includeMetadata: true }); @@ -177,7 +177,7 @@ async function buildAllAgents(projectDir) { console.log(chalk.cyan(` Building standalone agent ${agentName}...`)); - const customizePath = path.join(projectDir, '_bmad', '_cfg', 'agents', `${agentName}.customize.yaml`); + const customizePath = path.join(projectDir, '_bmad', '_config', 'agents', `${agentName}.customize.yaml`); const customizeExists = await fs.pathExists(customizePath); await builder.buildAgent(agentYamlPath, customizeExists ? customizePath : null, outputPath, { includeMetadata: true }); @@ -213,7 +213,7 @@ async function buildAllAgents(projectDir) { console.log(chalk.cyan(` Building ${agentName}...`)); - const customizePath = path.join(projectDir, '.claude', '_cfg', 'agents', `${agentName}.customize.yaml`); + const customizePath = path.join(projectDir, '.claude', '_config', 'agents', `${agentName}.customize.yaml`); const customizeExists = await fs.pathExists(customizePath); await builder.buildAgent(agentYamlPath, customizeExists ? customizePath : null, outputPath, { includeMetadata: true }); diff --git a/tools/cli/installers/lib/core/config-collector.js b/tools/cli/installers/lib/core/config-collector.js index d82e345f..095c44e1 100644 --- a/tools/cli/installers/lib/core/config-collector.js +++ b/tools/cli/installers/lib/core/config-collector.js @@ -15,7 +15,7 @@ class ConfigCollector { /** * Find the bmad installation directory in a project - * V6+ installations can use ANY folder name but ALWAYS have _cfg/manifest.yaml + * V6+ installations can use ANY folder name but ALWAYS have _config/manifest.yaml * @param {string} projectDir - Project directory * @returns {Promise} Path to bmad directory */ @@ -26,13 +26,13 @@ class ConfigCollector { return path.join(projectDir, 'bmad'); } - // V6+ strategy: Look for ANY directory with _cfg/manifest.yaml + // V6+ strategy: Look for ANY directory with _config/manifest.yaml // This is the definitive marker of a V6+ installation try { const entries = await fs.readdir(projectDir, { withFileTypes: true }); for (const entry of entries) { if (entry.isDirectory()) { - const manifestPath = path.join(projectDir, entry.name, '_cfg', 'manifest.yaml'); + const manifestPath = path.join(projectDir, entry.name, '_config', 'manifest.yaml'); if (await fs.pathExists(manifestPath)) { // Found a V6+ installation return path.join(projectDir, entry.name); @@ -59,12 +59,12 @@ class ConfigCollector { return null; } - // Look for ANY directory with _cfg/manifest.yaml + // Look for ANY directory with _config/manifest.yaml try { const entries = await fs.readdir(projectDir, { withFileTypes: true }); for (const entry of entries) { if (entry.isDirectory()) { - const manifestPath = path.join(projectDir, entry.name, '_cfg', 'manifest.yaml'); + const manifestPath = path.join(projectDir, entry.name, '_config', 'manifest.yaml'); if (await fs.pathExists(manifestPath)) { // Found a V6+ installation, return just the folder name return entry.name; diff --git a/tools/cli/installers/lib/core/custom-module-cache.js b/tools/cli/installers/lib/core/custom-module-cache.js index a3945039..e138f774 100644 --- a/tools/cli/installers/lib/core/custom-module-cache.js +++ b/tools/cli/installers/lib/core/custom-module-cache.js @@ -1,6 +1,6 @@ /** * Custom Module Source Cache - * Caches custom module sources under _cfg/custom/ to ensure they're never lost + * Caches custom module sources under _config/custom/ to ensure they're never lost * and can be checked into source control */ @@ -11,7 +11,7 @@ const crypto = require('node:crypto'); class CustomModuleCache { constructor(bmadDir) { this.bmadDir = bmadDir; - this.customCacheDir = path.join(bmadDir, '_cfg', 'custom'); + this.customCacheDir = path.join(bmadDir, '_config', 'custom'); this.manifestPath = path.join(this.customCacheDir, 'cache-manifest.yaml'); } diff --git a/tools/cli/installers/lib/core/detector.js b/tools/cli/installers/lib/core/detector.js index f87034e0..1fe76104 100644 --- a/tools/cli/installers/lib/core/detector.js +++ b/tools/cli/installers/lib/core/detector.js @@ -92,7 +92,7 @@ class Detector { // Fallback: scan directory for modules (legacy installations without manifest) const entries = await fs.readdir(bmadDir, { withFileTypes: true }); for (const entry of entries) { - if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_cfg') { + if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_config') { const modulePath = path.join(bmadDir, entry.name); const moduleConfigPath = path.join(modulePath, 'config.yaml'); @@ -205,7 +205,7 @@ class Detector { /** * Detect legacy BMAD v4 footprints (case-sensitive path checks) * V4 used _bmad-method as default folder name - * V6+ uses configurable folder names and ALWAYS has _cfg/manifest.yaml with installation.version + * V6+ uses configurable folder names and ALWAYS has _config/manifest.yaml with installation.version * @param {string} projectDir - Project directory to check * @returns {{ hasLegacyV4: boolean, offenders: string[] }} */ @@ -232,7 +232,7 @@ class Detector { // Helper: check if a directory is a V6+ installation const isV6Installation = async (dirPath) => { - const manifestPath = path.join(dirPath, '_cfg', 'manifest.yaml'); + const manifestPath = path.join(dirPath, '_config', 'manifest.yaml'); if (!(await fs.pathExists(manifestPath))) { return false; } @@ -250,7 +250,7 @@ class Detector { const offenders = []; // Strategy: - // 1. First scan for ANY V6+ installation (_cfg/manifest.yaml) + // 1. First scan for ANY V6+ installation (_config/manifest.yaml) // 2. If V6+ found → don't flag anything (user is already on V6+) // 3. If NO V6+ found → flag folders with "bmad" in name as potential V4 legacy @@ -271,7 +271,7 @@ class Detector { continue; // Skip empty folders } - // Check if it's a V6+ installation by looking for _cfg/manifest.yaml + // Check if it's a V6+ installation by looking for _config/manifest.yaml // This works for ANY folder name (not just bmad-prefixed) const isV6 = await isV6Installation(fullPath); diff --git a/tools/cli/installers/lib/core/ide-config-manager.js b/tools/cli/installers/lib/core/ide-config-manager.js index 91ca2b79..2e83c6de 100644 --- a/tools/cli/installers/lib/core/ide-config-manager.js +++ b/tools/cli/installers/lib/core/ide-config-manager.js @@ -4,7 +4,7 @@ const yaml = require('yaml'); /** * Manages IDE configuration persistence - * Saves and loads IDE-specific configurations to/from bmad/_cfg/ides/ + * Saves and loads IDE-specific configurations to/from bmad/_config/ides/ */ class IdeConfigManager { constructor() {} @@ -15,7 +15,7 @@ class IdeConfigManager { * @returns {string} Path to IDE config directory */ getIdeConfigDir(bmadDir) { - return path.join(bmadDir, '_cfg', 'ides'); + return path.join(bmadDir, '_config', 'ides'); } /** diff --git a/tools/cli/installers/lib/core/installer.js b/tools/cli/installers/lib/core/installer.js index b749e0d4..402b5f98 100644 --- a/tools/cli/installers/lib/core/installer.js +++ b/tools/cli/installers/lib/core/installer.js @@ -38,27 +38,40 @@ class Installer { /** * Find the bmad installation directory in a project - * V6+ installations can use ANY folder name but ALWAYS have _cfg/manifest.yaml + * V6+ installations can use ANY folder name but ALWAYS have _config/manifest.yaml + * Also checks for legacy _cfg folder for migration * @param {string} projectDir - Project directory - * @returns {Promise} Path to bmad directory + * @returns {Promise} { bmadDir: string, hasLegacyCfg: boolean } */ async findBmadDir(projectDir) { // Check if project directory exists if (!(await fs.pathExists(projectDir))) { // Project doesn't exist yet, return default - return path.join(projectDir, '_bmad'); + return { bmadDir: path.join(projectDir, '_bmad'), hasLegacyCfg: false }; } - // V6+ strategy: Look for ANY directory with _cfg/manifest.yaml - // This is the definitive marker of a V6+ installation + // V6+ strategy: Look for ANY directory with _config/manifest.yaml or legacy _cfg/manifest.yaml + let bmadDir = null; + let hasLegacyCfg = false; + try { const entries = await fs.readdir(projectDir, { withFileTypes: true }); for (const entry of entries) { if (entry.isDirectory()) { - const manifestPath = path.join(projectDir, entry.name, '_cfg', 'manifest.yaml'); + const bmadPath = path.join(projectDir, entry.name); + + // Check for current _config folder + const manifestPath = path.join(bmadPath, '_config', 'manifest.yaml'); if (await fs.pathExists(manifestPath)) { - // Found a V6+ installation - return path.join(projectDir, entry.name); + // Found a V6+ installation with current _config folder + return { bmadDir: bmadPath, hasLegacyCfg: false }; + } + + // Check for legacy _cfg folder + const legacyManifestPath = path.join(bmadPath, '_cfg', 'manifest.yaml'); + if (await fs.pathExists(legacyManifestPath)) { + bmadDir = bmadPath; + hasLegacyCfg = true; } } } @@ -66,9 +79,14 @@ class Installer { // Ignore errors, fall through to default } + // If we found a bmad directory (with or without legacy _cfg) + if (bmadDir) { + return { bmadDir, hasLegacyCfg }; + } + // No V6+ installation found, return default // This will be used for new installations - return path.join(projectDir, '_bmad'); + return { bmadDir: path.join(projectDir, '_bmad'), hasLegacyCfg: false }; } /** @@ -473,10 +491,13 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: let existingBmadDir = null; let existingBmadFolderName = null; + let hasLegacyCfg = false; if (await fs.pathExists(projectDir)) { - existingBmadDir = await this.findBmadDir(projectDir); + const result = await this.findBmadDir(projectDir); + existingBmadDir = result.bmadDir; existingBmadFolderName = path.basename(existingBmadDir); + hasLegacyCfg = result.hasLegacyCfg; } // Create a project directory if it doesn't exist (user already confirmed) @@ -501,6 +522,44 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: const bmadDir = path.join(projectDir, bmadFolderName); + // Check for legacy _cfg folder and prompt for rename + if (hasLegacyCfg && !config._quickUpdate) { + spinner.stop(); + + console.log(chalk.yellow('\n⚠️ Legacy configuration folder detected')); + console.log(chalk.dim(` Found: ${path.join(bmadDir, '_cfg')}`)); + console.log(chalk.dim(' The configuration folder has been renamed from "_cfg" to "_config"')); + + const inquirer = require('inquirer'); + const { shouldRename } = await inquirer.prompt([ + { + type: 'confirm', + name: 'shouldRename', + message: 'Would you like the installer to rename "_cfg" to "_config" for you?', + default: true, + }, + ]); + + if (!shouldRename) { + console.log(chalk.red('\n❌ Installation cancelled')); + console.log(chalk.dim('You must manually rename the "_cfg" folder to "_config" before proceeding.')); + return { success: false, cancelled: true }; + } + + // Perform the rename + spinner.start('Renaming configuration folder...'); + try { + const oldCfgPath = path.join(bmadDir, '_cfg'); + const newCfgPath = path.join(bmadDir, '_config'); + await fs.move(oldCfgPath, newCfgPath); + spinner.succeed('Configuration folder renamed successfully'); + } catch (error) { + spinner.fail('Failed to rename configuration folder'); + console.error(chalk.red(`Error: ${error.message}`)); + return { success: false, error: error.message }; + } + } + // Check existing installation spinner.text = 'Checking for existing installation...'; const existingInstall = await this.detector.detect(bmadDir); @@ -834,8 +893,11 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: customInfo = config._customModuleSources.get(moduleName); isCustomModule = true; - // Check if this is a cached module (source path starts with _cfg) - if (customInfo.sourcePath && (customInfo.sourcePath.startsWith('_cfg') || customInfo.sourcePath.includes('_cfg/custom'))) { + // Check if this is a cached module (source path starts with _config) + if ( + customInfo.sourcePath && + (customInfo.sourcePath.startsWith('_config') || customInfo.sourcePath.includes('_config/custom')) + ) { useCache = true; // Make sure we have the right path structure if (!customInfo.path) { @@ -939,9 +1001,9 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: if (finalCustomContent && finalCustomContent.cachedModules) { sourcePath = finalCustomContent.cachedModules.find((m) => m.id === moduleName)?.relativePath; } else { - // During update, the sourcePath is already cache-relative if it starts with _cfg + // During update, the sourcePath is already cache-relative if it starts with _config sourcePath = - customInfo.sourcePath && customInfo.sourcePath.startsWith('_cfg') + customInfo.sourcePath && customInfo.sourcePath.startsWith('_config') ? customInfo.sourcePath : path.relative(bmadDir, customInfo.path || customInfo.sourcePath); } @@ -1061,7 +1123,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: // Customize templates are now created in processAgentFiles when building YAML agents // Pre-register manifest files that will be created (except files-manifest.csv to avoid recursion) - const cfgDir = path.join(bmadDir, '_cfg'); + const cfgDir = path.join(bmadDir, '_config'); this.installedFiles.push( path.join(cfgDir, 'manifest.yaml'), path.join(cfgDir, 'workflow-manifest.csv'), @@ -1329,7 +1391,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: try { const projectDir = path.resolve(config.directory); - const bmadDir = await this.findBmadDir(projectDir); + const { bmadDir } = await this.findBmadDir(projectDir); const existingInstall = await this.detector.detect(bmadDir); if (!existingInstall.installed) { @@ -1414,7 +1476,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: */ async getStatus(directory) { const projectDir = path.resolve(directory); - const bmadDir = await this.findBmadDir(projectDir); + const { bmadDir } = await this.findBmadDir(projectDir); return await this.detector.detect(bmadDir); } @@ -1430,7 +1492,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: */ async uninstall(directory) { const projectDir = path.resolve(directory); - const bmadDir = await this.findBmadDir(projectDir); + const { bmadDir } = await this.findBmadDir(projectDir); if (await fs.pathExists(bmadDir)) { await fs.remove(bmadDir); @@ -1447,9 +1509,9 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: */ async createDirectoryStructure(bmadDir) { await fs.ensureDir(bmadDir); - await fs.ensureDir(path.join(bmadDir, '_cfg')); - await fs.ensureDir(path.join(bmadDir, '_cfg', 'agents')); - await fs.ensureDir(path.join(bmadDir, '_cfg', 'custom')); + await fs.ensureDir(path.join(bmadDir, '_config')); + await fs.ensureDir(path.join(bmadDir, '_config', 'agents')); + await fs.ensureDir(path.join(bmadDir, '_config', 'custom')); } /** @@ -1466,7 +1528,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: // Get all installed module directories const entries = await fs.readdir(bmadDir, { withFileTypes: true }); const installedModules = entries - .filter((entry) => entry.isDirectory() && entry.name !== '_cfg' && entry.name !== 'docs') + .filter((entry) => entry.isDirectory() && entry.name !== '_config' && entry.name !== 'docs') .map((entry) => entry.name); // Generate config.yaml for each installed module @@ -1826,9 +1888,9 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: // Determine project directory (parent of bmad/ directory) const bmadDir = path.dirname(modulePath); const projectDir = path.dirname(bmadDir); - const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents'); + const cfgAgentsDir = path.join(bmadDir, '_config', 'agents'); - // Ensure _cfg/agents directory exists + // Ensure _config/agents directory exists await fs.ensureDir(cfgAgentsDir); // Get all agent files @@ -1917,7 +1979,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: */ async buildStandaloneAgents(bmadDir, projectDir) { const standaloneAgentsPath = path.join(bmadDir, 'agents'); - const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents'); + const cfgAgentsDir = path.join(bmadDir, '_config', 'agents'); // Check if standalone agents directory exists if (!(await fs.pathExists(standaloneAgentsPath))) { @@ -2018,7 +2080,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: // Determine project directory (parent of bmad/ directory) const bmadDir = path.dirname(modulePath); const projectDir = path.dirname(bmadDir); - const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents'); + const cfgAgentsDir = path.join(bmadDir, '_config', 'agents'); const targetAgentsPath = path.join(modulePath, 'agents'); // Ensure target directory exists @@ -2143,7 +2205,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: async compileAgents(config) { try { const projectDir = path.resolve(config.directory); - const bmadDir = await this.findBmadDir(projectDir); + const { bmadDir } = await this.findBmadDir(projectDir); // Check if bmad directory exists if (!(await fs.pathExists(bmadDir))) { @@ -2151,7 +2213,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: } // Get installed modules from manifest - const manifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml'); + const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml'); let installedModules = []; let manifest = null; if (await fs.pathExists(manifestPath)) { @@ -2181,7 +2243,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: const entries = await fs.readdir(bmadDir, { withFileTypes: true }); for (const entry of entries) { - if (entry.isDirectory() && entry.name !== '_cfg' && entry.name !== 'docs') { + if (entry.isDirectory() && entry.name !== '_config' && entry.name !== 'docs') { const modulePath = path.join(bmadDir, entry.name); // Special handling for standalone agents in bmad/agents/ directory @@ -2264,7 +2326,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: try { const projectDir = path.resolve(config.directory); - const bmadDir = await this.findBmadDir(projectDir); + const { bmadDir } = await this.findBmadDir(projectDir); // Check if bmad directory exists if (!(await fs.pathExists(bmadDir))) { @@ -2287,8 +2349,8 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: // Ensure we have an absolute sourcePath let absoluteSourcePath = customModule.sourcePath; - // Check if sourcePath is a cache-relative path (starts with _cfg/) - if (absoluteSourcePath && absoluteSourcePath.startsWith('_cfg')) { + // Check if sourcePath is a cache-relative path (starts with _config/) + if (absoluteSourcePath && absoluteSourcePath.startsWith('_config')) { // Convert cache-relative path to absolute path absoluteSourcePath = path.join(bmadDir, absoluteSourcePath); } @@ -2695,7 +2757,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: * @returns {Array} Array of file entries from files-manifest.csv */ async readFilesManifest(bmadDir) { - const filesManifestPath = path.join(bmadDir, '_cfg', 'files-manifest.csv'); + const filesManifestPath = path.join(bmadDir, '_config', 'files-manifest.csv'); if (!(await fs.pathExists(filesManifestPath))) { return []; } @@ -2798,12 +2860,12 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: const relativePath = path.relative(bmadDir, fullPath); const fileName = path.basename(fullPath); - // Skip _cfg directory EXCEPT for modified agent customizations - if (relativePath.startsWith('_cfg/') || relativePath.startsWith('_cfg\\')) { + // Skip _config directory EXCEPT for modified agent customizations + if (relativePath.startsWith('_config/') || relativePath.startsWith('_config\\')) { // Special handling for .customize.yaml files - only preserve if modified if (relativePath.includes('/agents/') && fileName.endsWith('.customize.yaml')) { // Check if the customization file has been modified from manifest - const manifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml'); + const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml'); if (await fs.pathExists(manifestPath)) { const crypto = require('node:crypto'); const currentContent = await fs.readFile(fullPath, 'utf8'); @@ -2824,7 +2886,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: } // Skip config.yaml files - these are regenerated on each install/update - // Users should use _cfg/agents/ override files instead + // Users should use _config/agents/ override files instead if (fileName === 'config.yaml') { continue; } @@ -2832,8 +2894,8 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: if (!fileInfo) { // File not in manifest = custom file // EXCEPT: Agent .md files in module folders are generated files, not custom - // Only treat .md files under _cfg/agents/ as custom - if (!(fileName.endsWith('.md') && relativePath.includes('/agents/') && !relativePath.startsWith('_cfg/'))) { + // Only treat .md files under _config/agents/ as custom + if (!(fileName.endsWith('.md') && relativePath.includes('/agents/') && !relativePath.startsWith('_config/'))) { customFiles.push(fullPath); } } else if (manifestHasHashes && fileInfo.hash) { @@ -2866,7 +2928,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: * @param {Object} userInfo - User information including name and language */ async createAgentConfigs(bmadDir, userInfo = null) { - const agentConfigDir = path.join(bmadDir, '_cfg', 'agents'); + const agentConfigDir = path.join(bmadDir, '_config', 'agents'); await fs.ensureDir(agentConfigDir); // Get all agents from all modules @@ -2876,7 +2938,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: // Check modules for agents (including core) const entries = await fs.readdir(bmadDir, { withFileTypes: true }); for (const entry of entries) { - if (entry.isDirectory() && entry.name !== '_cfg') { + if (entry.isDirectory() && entry.name !== '_config') { const moduleAgentsPath = path.join(bmadDir, entry.name, 'agents'); if (await fs.pathExists(moduleAgentsPath)) { const agentFiles = await fs.readdir(moduleAgentsPath); @@ -2994,7 +3056,7 @@ If AgentVibes party mode is enabled, immediately trigger TTS with agent's voice: * @param {Array} agentDetails - Array of agent details */ async generateAgentManifest(bmadDir, agentDetails) { - const manifestPath = path.join(bmadDir, '_cfg', 'agent-manifest.csv'); + const manifestPath = path.join(bmadDir, '_config', 'agent-manifest.csv'); await AgentPartyGenerator.writeAgentParty(manifestPath, agentDetails, { forWeb: false }); } diff --git a/tools/cli/installers/lib/core/manifest-generator.js b/tools/cli/installers/lib/core/manifest-generator.js index b25581cf..54349ad8 100644 --- a/tools/cli/installers/lib/core/manifest-generator.js +++ b/tools/cli/installers/lib/core/manifest-generator.js @@ -28,8 +28,8 @@ class ManifestGenerator { * @param {Array} installedFiles - All installed files (optional, for hash tracking) */ async generateManifests(bmadDir, selectedModules, installedFiles = [], options = {}) { - // Create _cfg directory if it doesn't exist - const cfgDir = path.join(bmadDir, '_cfg'); + // Create _config directory if it doesn't exist + const cfgDir = path.join(bmadDir, '_config'); await fs.ensureDir(cfgDir); // Store modules list (all modules including preserved ones) @@ -902,7 +902,7 @@ class ManifestGenerator { for (const entry of entries) { // Skip if not a directory or is a special directory - if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === '_cfg') { + if (!entry.isDirectory() || entry.name.startsWith('.') || entry.name === '_config') { continue; } diff --git a/tools/cli/installers/lib/core/manifest.js b/tools/cli/installers/lib/core/manifest.js index 743b2564..a677ed92 100644 --- a/tools/cli/installers/lib/core/manifest.js +++ b/tools/cli/installers/lib/core/manifest.js @@ -10,10 +10,10 @@ class Manifest { * @param {Array} installedFiles - List of installed files (no longer used, files tracked in files-manifest.csv) */ async create(bmadDir, data, installedFiles = []) { - const manifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml'); + const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml'); const yaml = require('yaml'); - // Ensure _cfg directory exists + // Ensure _config directory exists await fs.ensureDir(path.dirname(manifestPath)); // Structure the manifest data @@ -46,7 +46,7 @@ class Manifest { * @returns {Object|null} Manifest data or null if not found */ async read(bmadDir) { - const yamlPath = path.join(bmadDir, '_cfg', 'manifest.yaml'); + const yamlPath = path.join(bmadDir, '_config', 'manifest.yaml'); const yaml = require('yaml'); if (await fs.pathExists(yamlPath)) { @@ -97,7 +97,7 @@ class Manifest { ides: manifest.ides || [], }; - const manifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml'); + const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml'); await fs.ensureDir(path.dirname(manifestPath)); const yamlContent = yaml.stringify(manifestData, { diff --git a/tools/cli/installers/lib/custom/handler.js b/tools/cli/installers/lib/custom/handler.js index 6289aa57..1170a8c8 100644 --- a/tools/cli/installers/lib/custom/handler.js +++ b/tools/cli/installers/lib/custom/handler.js @@ -306,7 +306,7 @@ class CustomHandler { const targetMdPath = path.join(targetDir, `${agentName}.md`); // Use the actual bmadDir if available (for when installing to temp dir) const actualBmadDir = config._bmadDir || bmadDir; - const customizePath = path.join(actualBmadDir, '_cfg', 'agents', `custom-${agentName}.customize.yaml`); + const customizePath = path.join(actualBmadDir, '_config', 'agents', `custom-${agentName}.customize.yaml`); // Read and compile the YAML try { diff --git a/tools/cli/installers/lib/ide/_base-ide.js b/tools/cli/installers/lib/ide/_base-ide.js index f870194c..2d0ea38d 100644 --- a/tools/cli/installers/lib/ide/_base-ide.js +++ b/tools/cli/installers/lib/ide/_base-ide.js @@ -136,7 +136,7 @@ class BaseIdeSetup { // Get module agents const entries = await fs.readdir(bmadDir, { withFileTypes: true }); for (const entry of entries) { - if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_cfg' && entry.name !== 'agents') { + if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_config' && entry.name !== 'agents') { const moduleAgentsPath = path.join(bmadDir, entry.name, 'agents'); if (await fs.pathExists(moduleAgentsPath)) { const moduleAgents = await this.scanDirectory(moduleAgentsPath, '.md'); @@ -208,7 +208,7 @@ class BaseIdeSetup { // Get module tasks const entries = await fs.readdir(bmadDir, { withFileTypes: true }); for (const entry of entries) { - if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_cfg' && entry.name !== 'agents') { + if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_config' && entry.name !== 'agents') { const moduleTasksPath = path.join(bmadDir, entry.name, 'tasks'); if (await fs.pathExists(moduleTasksPath)) { const moduleTasks = await this.scanDirectoryWithStandalone(moduleTasksPath, ['.md', '.xml']); @@ -254,7 +254,7 @@ class BaseIdeSetup { // Get module tools const entries = await fs.readdir(bmadDir, { withFileTypes: true }); for (const entry of entries) { - if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_cfg' && entry.name !== 'agents') { + if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_config' && entry.name !== 'agents') { const moduleToolsPath = path.join(bmadDir, entry.name, 'tools'); if (await fs.pathExists(moduleToolsPath)) { const moduleTools = await this.scanDirectoryWithStandalone(moduleToolsPath, ['.md', '.xml']); @@ -300,7 +300,7 @@ class BaseIdeSetup { // Get module workflows const entries = await fs.readdir(bmadDir, { withFileTypes: true }); for (const entry of entries) { - if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_cfg' && entry.name !== 'agents') { + if (entry.isDirectory() && entry.name !== 'core' && entry.name !== '_config' && entry.name !== 'agents') { const moduleWorkflowsPath = path.join(bmadDir, entry.name, 'workflows'); if (await fs.pathExists(moduleWorkflowsPath)) { const moduleWorkflows = await this.findWorkflowYamlFiles(moduleWorkflowsPath); @@ -635,7 +635,7 @@ class BaseIdeSetup { * @param {Object} agent - Agent information */ async createAgentConfig(bmadDir, agent) { - const agentConfigDir = path.join(bmadDir, '_cfg', 'agents'); + const agentConfigDir = path.join(bmadDir, '_config', 'agents'); await this.ensureDir(agentConfigDir); // Load agent config template diff --git a/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js b/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js index 1613a582..315df80e 100644 --- a/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js +++ b/tools/cli/installers/lib/ide/shared/task-tool-command-generator.js @@ -85,7 +85,7 @@ Follow all instructions in the ${type} file exactly as written. * Load task manifest CSV */ async loadTaskManifest(bmadDir) { - const manifestPath = path.join(bmadDir, '_cfg', 'task-manifest.csv'); + const manifestPath = path.join(bmadDir, '_config', 'task-manifest.csv'); if (!(await fs.pathExists(manifestPath))) { return null; @@ -102,7 +102,7 @@ Follow all instructions in the ${type} file exactly as written. * Load tool manifest CSV */ async loadToolManifest(bmadDir) { - const manifestPath = path.join(bmadDir, '_cfg', 'tool-manifest.csv'); + const manifestPath = path.join(bmadDir, '_config', 'tool-manifest.csv'); if (!(await fs.pathExists(manifestPath))) { return null; diff --git a/tools/cli/installers/lib/ide/shared/workflow-command-generator.js b/tools/cli/installers/lib/ide/shared/workflow-command-generator.js index ec77a232..7f8385fc 100644 --- a/tools/cli/installers/lib/ide/shared/workflow-command-generator.js +++ b/tools/cli/installers/lib/ide/shared/workflow-command-generator.js @@ -224,7 +224,7 @@ When running any workflow: } async loadWorkflowManifest(bmadDir) { - const manifestPath = path.join(bmadDir, '_cfg', 'workflow-manifest.csv'); + const manifestPath = path.join(bmadDir, '_config', 'workflow-manifest.csv'); if (!(await fs.pathExists(manifestPath))) { return null; diff --git a/tools/cli/installers/lib/modules/manager.js b/tools/cli/installers/lib/modules/manager.js index 55cc6039..d54e2cf3 100644 --- a/tools/cli/installers/lib/modules/manager.js +++ b/tools/cli/installers/lib/modules/manager.js @@ -242,15 +242,15 @@ class ModuleManager { } } - // Also check for cached custom modules in _cfg/custom/ + // Also check for cached custom modules in _config/custom/ if (this.bmadDir) { - const customCacheDir = path.join(this.bmadDir, '_cfg', 'custom'); + const customCacheDir = path.join(this.bmadDir, '_config', 'custom'); if (await fs.pathExists(customCacheDir)) { const cacheEntries = await fs.readdir(customCacheDir, { withFileTypes: true }); for (const entry of cacheEntries) { if (entry.isDirectory()) { const cachePath = path.join(customCacheDir, entry.name); - const moduleInfo = await this.getModuleInfo(cachePath, entry.name, '_cfg/custom'); + const moduleInfo = await this.getModuleInfo(cachePath, entry.name, '_config/custom'); if (moduleInfo && !modules.some((m) => m.id === moduleInfo.id) && !customModules.some((m) => m.id === moduleInfo.id)) { moduleInfo.isCustom = true; moduleInfo.fromCache = true; @@ -785,7 +785,7 @@ class ModuleManager { async compileModuleAgents(sourcePath, targetPath, moduleName, bmadDir) { const sourceAgentsPath = path.join(sourcePath, 'agents'); const targetAgentsPath = path.join(targetPath, 'agents'); - const cfgAgentsDir = path.join(bmadDir, '_cfg', 'agents'); + const cfgAgentsDir = path.join(bmadDir, '_config', 'agents'); // Check if agents directory exists in source if (!(await fs.pathExists(sourceAgentsPath))) { @@ -827,7 +827,7 @@ class ModuleManager { const originalHash = crypto.createHash('sha256').update(customizeContent).digest('hex'); // Store in main manifest - const manifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml'); + const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml'); let manifestData = {}; if (await fs.pathExists(manifestPath)) { const manifestContent = await fs.readFile(manifestPath, 'utf8'); diff --git a/tools/cli/lib/agent-party-generator.js b/tools/cli/lib/agent-party-generator.js index d2b0cad6..efc783a8 100644 --- a/tools/cli/lib/agent-party-generator.js +++ b/tools/cli/lib/agent-party-generator.js @@ -29,7 +29,7 @@ const AgentPartyGenerator = { let xmlContent = ` - + Complete roster of ${forWeb ? 'bundled' : 'installed'} BMAD agents with summarized personas for efficient multi-agent orchestration. Used by party-mode and other multi-agent coordination features. diff --git a/tools/cli/lib/agent/installer.js b/tools/cli/lib/agent/installer.js index c83c8269..62b8311f 100644 --- a/tools/cli/lib/agent/installer.js +++ b/tools/cli/lib/agent/installer.js @@ -410,7 +410,7 @@ function detectBmadProject(targetPath) { const possibleNames = ['_bmad']; for (const name of possibleNames) { const bmadFolder = path.join(checkPath, name); - const cfgFolder = path.join(bmadFolder, '_cfg'); + const cfgFolder = path.join(bmadFolder, '_config'); const manifestFile = path.join(cfgFolder, 'agent-manifest.csv'); if (fs.existsSync(manifestFile)) { @@ -596,16 +596,16 @@ function addToManifest(manifestFile, agentData) { } /** - * Save agent source YAML to _cfg/custom/agents/ for reinstallation + * Save agent source YAML to _config/custom/agents/ for reinstallation * Stores user answers in a top-level saved_answers section (cleaner than overwriting defaults) * @param {Object} agentInfo - Agent info (path, type, etc.) - * @param {string} cfgFolder - Path to _cfg folder + * @param {string} cfgFolder - Path to _config folder * @param {string} agentName - Final agent name (e.g., "fred-commit-poet") * @param {Object} answers - User answers to save for reinstallation * @returns {Object} Info about saved source */ function saveAgentSource(agentInfo, cfgFolder, agentName, answers = {}) { - // Save to _cfg/custom/agents/ instead of _cfg/agents/ + // Save to _config/custom/agents/ instead of _config/agents/ const customAgentsCfgDir = path.join(cfgFolder, 'custom', 'agents'); if (!fs.existsSync(customAgentsCfgDir)) { @@ -689,7 +689,7 @@ function saveAgentSource(agentInfo, cfgFolder, agentName, answers = {}) { */ async function createIdeSlashCommands(projectRoot, agentName, agentPath, metadata) { // Read manifest.yaml to get installed IDEs - const manifestPath = path.join(projectRoot, '_bmad', '_cfg', 'manifest.yaml'); + const manifestPath = path.join(projectRoot, '_bmad', '_config', 'manifest.yaml'); let installedIdes = ['claude-code']; // Default to Claude Code if no manifest if (fs.existsSync(manifestPath)) { diff --git a/tools/cli/lib/ui.js b/tools/cli/lib/ui.js index cbbff201..ff94a6d2 100644 --- a/tools/cli/lib/ui.js +++ b/tools/cli/lib/ui.js @@ -650,11 +650,11 @@ class UI { if (stats.isDirectory()) { const files = await fs.readdir(directory); if (files.length > 0) { - // Check for any bmad installation (any folder with _cfg/manifest.yaml) + // Check for any bmad installation (any folder with _config/manifest.yaml) const { Installer } = require('../installers/lib/core/installer'); const installer = new Installer(); const bmadDir = await installer.findBmadDir(directory); - const hasBmadInstall = (await fs.pathExists(bmadDir)) && (await fs.pathExists(path.join(bmadDir, '_cfg', 'manifest.yaml'))); + const hasBmadInstall = (await fs.pathExists(bmadDir)) && (await fs.pathExists(path.join(bmadDir, '_config', 'manifest.yaml'))); console.log( chalk.gray(`Directory exists and contains ${files.length} item(s)`) + diff --git a/tools/cli/lib/yaml-xml-builder.js b/tools/cli/lib/yaml-xml-builder.js index b8b2de58..b7e81871 100644 --- a/tools/cli/lib/yaml-xml-builder.js +++ b/tools/cli/lib/yaml-xml-builder.js @@ -525,7 +525,7 @@ class YamlXmlBuilder { } else if (bmadIndex !== -1 && pathParts[bmadIndex + 1]) { // Path contains /bmad/{module}/ const potentialModule = pathParts[bmadIndex + 1]; - // Check if it's a known module, not 'agents' or '_cfg' + // Check if it's a known module, not 'agents' or '_config' if (['bmm', 'bmb', 'cis', 'core'].includes(potentialModule)) { module = potentialModule; } diff --git a/tools/migrate-custom-module-paths.js b/tools/migrate-custom-module-paths.js index 2c51b820..13aa3e71 100755 --- a/tools/migrate-custom-module-paths.js +++ b/tools/migrate-custom-module-paths.js @@ -95,7 +95,7 @@ async function migrate(directory) { console.log(chalk.dim(`Project: ${projectRoot}`)); console.log(chalk.dim(`BMAD Directory: ${bmadDir}`)); - const manifestPath = path.join(bmadDir, '_cfg', 'manifest.yaml'); + const manifestPath = path.join(bmadDir, '_config', 'manifest.yaml'); if (!fs.existsSync(manifestPath)) { console.error(chalk.red('✗ No manifest.yaml found'));