From ad4e8134703e63e83c312f51c4009969b5554d71 Mon Sep 17 00:00:00 2001 From: Alex Verkhovsky Date: Sat, 7 Mar 2026 21:53:32 -0700 Subject: [PATCH] feat(skills): add install_to_bmad flag and skill: help catalog reference Add install_to_bmad flag to skill manifests (default true) enabling skills to opt out of _bmad/ copy while retaining .claude/skills/ installation. Support skill: references in module-help.csv workflow-file column. Fix stale quick-dev-new-preview directory references in agent YAML and help catalog. Co-Authored-By: Claude Opus 4.6 --- src/bmm/agents/quick-flow-solo-dev.agent.yaml | 4 ++-- src/bmm/module-help.csv | 2 +- src/core/tasks/help.md | 6 +++++ .../installers/lib/core/manifest-generator.js | 10 +++++++- .../cli/installers/lib/ide/_config-driven.js | 12 ++++++++++ .../lib/ide/shared/skill-manifest.js | 23 ++++++++++++++++++- 6 files changed, 52 insertions(+), 5 deletions(-) diff --git a/src/bmm/agents/quick-flow-solo-dev.agent.yaml b/src/bmm/agents/quick-flow-solo-dev.agent.yaml index a999bb56d..553cc9d4d 100644 --- a/src/bmm/agents/quick-flow-solo-dev.agent.yaml +++ b/src/bmm/agents/quick-flow-solo-dev.agent.yaml @@ -27,8 +27,8 @@ agent: exec: "{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md" description: "[QD] Quick-flow Develop: Implement a story tech spec end-to-end (Core of Quick Flow)" - - trigger: QQ or fuzzy match on quick-dev-new-preview - exec: "{project-root}/_bmad/bmm/workflows/bmad-quick-flow/quick-dev-new-preview/workflow.md" + - trigger: QQ or fuzzy match on bmad-quick-dev-new-preview + exec: "{project-root}/_bmad/bmm/workflows/bmad-quick-flow/bmad-quick-dev-new-preview/workflow.md" description: "[QQ] Quick Dev New (Preview): Unified quick flow — clarify intent, plan, implement, review, present (experimental)" - trigger: CR or fuzzy match on code-review diff --git a/src/bmm/module-help.csv b/src/bmm/module-help.csv index b8378cf3c..98da248dc 100644 --- a/src/bmm/module-help.csv +++ b/src/bmm/module-help.csv @@ -3,7 +3,7 @@ bmm,anytime,Document Project,DP,,_bmad/bmm/workflows/document-project/workflow.y bmm,anytime,Generate Project Context,GPC,,_bmad/bmm/workflows/generate-project-context/workflow.md,bmad-bmm-generate-project-context,false,analyst,Create Mode,"Scan existing codebase to generate a lean LLM-optimized project-context.md containing critical implementation rules patterns and conventions for AI agents. Essential for brownfield projects and quick-flow.",output_folder,"project context", bmm,anytime,Quick Spec,QS,,_bmad/bmm/workflows/bmad-quick-flow/quick-spec/workflow.md,bmad-bmm-quick-spec,false,quick-flow-solo-dev,Create Mode,"Do not suggest for potentially very complex things unless requested or if the user complains that they do not want to follow the extensive planning of the bmad method. Quick one-off tasks small changes simple apps brownfield additions to well established patterns utilities without extensive planning",planning_artifacts,"tech spec", bmm,anytime,Quick Dev,QD,,_bmad/bmm/workflows/bmad-quick-flow/quick-dev/workflow.md,bmad-bmm-quick-dev,false,quick-flow-solo-dev,Create Mode,"Quick one-off tasks small changes simple apps utilities without extensive planning - Do not suggest for potentially very complex things unless requested or if the user complains that they do not want to follow the extensive planning of the bmad method, unless the user is already working through the implementation phase and just requests a 1 off things not already in the plan",,, -bmm,anytime,Quick Dev New Preview,QQ,,_bmad/bmm/workflows/bmad-quick-flow/quick-dev-new-preview/workflow.md,bmad-bmm-quick-dev-new-preview,false,quick-flow-solo-dev,Create Mode,"Unified quick flow (experimental): clarify intent plan implement review and present in a single workflow",implementation_artifacts,"tech spec implementation", +bmm,anytime,Quick Dev New Preview,QQ,,skill:bmad-quick-dev-new-preview,bmad-bmm-quick-dev-new-preview,false,quick-flow-solo-dev,Create Mode,"Unified quick flow (experimental): clarify intent plan implement review and present in a single workflow",implementation_artifacts,"tech spec implementation", bmm,anytime,Correct Course,CC,,_bmad/bmm/workflows/4-implementation/correct-course/workflow.yaml,bmad-bmm-correct-course,false,sm,Create Mode,"Anytime: Navigate significant changes. May recommend start over update PRD redo architecture sprint planning or correct epics and stories",planning_artifacts,"change proposal", bmm,anytime,Write Document,WD,,_bmad/bmm/agents/tech-writer/tech-writer.agent.yaml,,false,tech-writer,,"Describe in detail what you want, and the agent will follow the documentation best practices defined in agent memory. Multi-turn conversation with subprocess for research/review.",project-knowledge,"document", bmm,anytime,Update Standards,US,,_bmad/bmm/agents/tech-writer/tech-writer.agent.yaml,,false,tech-writer,,"Update agent memory documentation-standards.md with your specific preferences if you discover missing document conventions.",_bmad/_memory/tech-writer-sidecar,"standards", diff --git a/src/core/tasks/help.md b/src/core/tasks/help.md index 54a23b5f1..88f4a4d55 100644 --- a/src/core/tasks/help.md +++ b/src/core/tasks/help.md @@ -21,6 +21,12 @@ description: 'Analyzes what is done and the users query and offers advice on wha When `command` field has a value: - Show the command prefixed with `/` (e.g., `/bmad-bmm-create-prd`) +### Skill-Referenced Workflows +When `workflow-file` starts with `skill:`: +- The value is a skill reference (e.g., `skill:bmad-quick-dev-new-preview`), NOT a file path +- Do NOT attempt to resolve or load it as a file path +- Display using the `command` column value prefixed with `/` (same as command-based workflows) + ### Agent-Based Workflows When `command` field is empty: - User loads agent first via `/agent-command` diff --git a/tools/cli/installers/lib/core/manifest-generator.js b/tools/cli/installers/lib/core/manifest-generator.js index f855bcabf..fe2b5f978 100644 --- a/tools/cli/installers/lib/core/manifest-generator.js +++ b/tools/cli/installers/lib/core/manifest-generator.js @@ -9,6 +9,7 @@ const { loadSkillManifest: loadSkillManifestShared, getCanonicalId: getCanonicalIdShared, getArtifactType: getArtifactTypeShared, + getInstallToBmad: getInstallToBmadShared, } = require('../ide/shared/skill-manifest'); // Load package.json for version info @@ -44,6 +45,11 @@ class ManifestGenerator { return getArtifactTypeShared(manifest, filename); } + /** Delegate to shared skill-manifest module */ + getInstallToBmad(manifest, filename) { + return getInstallToBmadShared(manifest, filename); + } + /** * Clean text for CSV output by normalizing whitespace. * Note: Quote escaping is handled by escapeCsv() at write time. @@ -249,6 +255,7 @@ class ManifestGenerator { module: moduleName, path: installPath, canonicalId, + install_to_bmad: this.getInstallToBmad(skillManifest, entry.name), }); if (debug) { @@ -830,7 +837,7 @@ class ManifestGenerator { const csvPath = path.join(cfgDir, 'skill-manifest.csv'); const escapeCsv = (value) => `"${String(value ?? '').replaceAll('"', '""')}"`; - let csvContent = 'canonicalId,name,description,module,path\n'; + let csvContent = 'canonicalId,name,description,module,path,install_to_bmad\n'; for (const skill of this.skills) { const row = [ @@ -839,6 +846,7 @@ class ManifestGenerator { escapeCsv(skill.description), escapeCsv(skill.module), escapeCsv(skill.path), + escapeCsv(skill.install_to_bmad), ].join(','); csvContent += row + '\n'; } diff --git a/tools/cli/installers/lib/ide/_config-driven.js b/tools/cli/installers/lib/ide/_config-driven.js index 599cc0f67..791c7ec69 100644 --- a/tools/cli/installers/lib/ide/_config-driven.js +++ b/tools/cli/installers/lib/ide/_config-driven.js @@ -702,6 +702,18 @@ LOAD and execute from: {project-root}/{{bmadFolderName}}/{{path}} count++; } + // Post-install cleanup: remove _bmad/ directories for skills with install_to_bmad === "false" + for (const record of records) { + if (record.install_to_bmad === 'false') { + const relativePath = record.path.replace(new RegExp(`^${bmadFolderName}/`), ''); + const sourceFile = path.join(bmadDir, relativePath); + const sourceDir = path.dirname(sourceFile); + if (await fs.pathExists(sourceDir)) { + await fs.remove(sourceDir); + } + } + } + return count; } diff --git a/tools/cli/installers/lib/ide/shared/skill-manifest.js b/tools/cli/installers/lib/ide/shared/skill-manifest.js index 26e15b2bd..22a7cceef 100644 --- a/tools/cli/installers/lib/ide/shared/skill-manifest.js +++ b/tools/cli/installers/lib/ide/shared/skill-manifest.js @@ -66,4 +66,25 @@ function getArtifactType(manifest, filename) { return null; } -module.exports = { loadSkillManifest, getCanonicalId, getArtifactType }; +/** + * Get the install_to_bmad flag for a specific file from a loaded skill manifest. + * @param {Object|null} manifest - Loaded manifest (from loadSkillManifest) + * @param {string} filename - Source filename to look up + * @returns {boolean} install_to_bmad value (defaults to true) + */ +function getInstallToBmad(manifest, filename) { + if (!manifest) return true; + // Single-entry manifest applies to all files in the directory + if (manifest.__single) return manifest.__single.install_to_bmad !== false; + // Multi-entry: look up by filename directly + if (manifest[filename]) return manifest[filename].install_to_bmad !== false; + // Fallback: try alternate extensions for compiled files + const baseName = filename.replace(/\.(md|xml)$/i, ''); + const agentKey = `${baseName}.agent.yaml`; + if (manifest[agentKey]) return manifest[agentKey].install_to_bmad !== false; + const xmlKey = `${baseName}.xml`; + if (manifest[xmlKey]) return manifest[xmlKey].install_to_bmad !== false; + return true; +} + +module.exports = { loadSkillManifest, getCanonicalId, getArtifactType, getInstallToBmad };