fix(installer): Multiple installer fixes#1492
Conversation
📝 WalkthroughWalkthroughUpdates YAML frontmatter regexes to accept LF or CRLF line endings; centralizes BMAD folder name into shared path-utils and propagates it across IDE components; adds artifact collection and template-based rendering/writing for tasks/tools; introduces new Markdown and TOML templates; fixes a path variable bug in an agent installer. Changes
Sequence DiagramsequenceDiagram
participant ConfigDriven as ConfigDrivenIdeSetup
participant TaskToolGen as TaskToolCommandGenerator
participant Templates as TemplateEngine
participant FileSystem as FileSystem
ConfigDriven->>TaskToolGen: new(bmadFolderName)
ConfigDriven->>TaskToolGen: collectTaskToolArtifacts(bmadDir)
TaskToolGen->>FileSystem: read task/tool manifests
TaskToolGen-->>ConfigDriven: return artifacts + counts
ConfigDriven->>Templates: preload templates (task/tool)
Templates-->>ConfigDriven: template content
loop per artifact
ConfigDriven->>Templates: renderTemplate(artifact, templateType)
Templates-->>ConfigDriven: rendered content
ConfigDriven->>FileSystem: write file to targetPath
end
ConfigDriven-->>ConfigDriven: return { tasks, tools } counts
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@tools/cli/installers/lib/ide/_config-driven.js`:
- Around line 213-218: The wrapper filename generation creates double extensions
when source paths with non-.md extensions (e.g., .xml from
scanDirectoryWithStandalone) are passed through toDashPath(), because
toDashPath() currently only strips .md and generateFilename() only cleans
.yaml.md/.yml.md; update toDashPath() to strip a broader set of common
extensions (at least .md, .yaml, .yml, .json, .xml, .toml) so it returns a clean
base name, or alternatively extend the cleanup regex in generateFilename() to
remove any trailing .(md|yaml|yml|json|xml|toml)\.(md|yaml|yml|json|xml|toml)
patterns; locate and modify the toDashPath() function and/or generateFilename()
to apply this broader extension-stripping logic so filenames like
bmad-core-create-story.xml.md become bmad-core-create-story.md (and ultimately
bmad-core-create-story.toml when template extension is .toml).
|
@CodeRabbit review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
tools/cli/installers/lib/modules/manager.js (1)
74-78:⚠️ Potential issue | 🟡 MinorGuard
setBmadFolderNamefor non-BaseIde handlers.
If a dynamically loaded handler doesn’t implementsetBmadFolderName, this will throw and prevent handler registration. Consider checkingtypeof instance.setBmadFolderName === 'function'before calling it (Line 77).tools/cli/installers/lib/ide/_base-ide.js (1)
56-63:⚠️ Potential issue | 🟠 MajorCleanup should use the instance’s folder name.
Line 61 usesBMAD_FOLDER_NAMEdirectly, which ignores any override set viasetBmadFolderName. This can leave custom-named BMAD config behind. Usethis.bmadFolderNameinstead.
🤖 Fix all issues with AI agents
In `@tools/cli/installers/lib/ide/manager.js`:
- Around line 74-78: The code assumes every HandlerClass instance implements
setBmadFolderName which can throw if missing; update the instantiation flow in
manager.js to check typeof instance.setBmadFolderName === 'function' before
calling it (i.e., only call setBmadFolderName when available) while still
populating this.handlers with instance.name; reference HandlerClass, instance,
setBmadFolderName and this.handlers.set to locate and update the guard.
In `@tools/cli/installers/lib/ide/shared/task-tool-command-generator.js`:
- Around line 27-76: collectTaskToolArtifacts currently only strips a leading
_bmad/ but doesn't convert absolute manifest paths to relative ones, letting
absolutes leak into templates; update the task and tool normalization in
collectTaskToolArtifacts to first replace backslashes, then if
path.isAbsolute(taskPath) / path.isAbsolute(toolPath) convert to a relative path
using path.relative(bmadDir, taskPath/toolPath) (and replace backslashes again),
and only then remove the bmadPrefix so artifact.path contains the normalized
relative path; apply the exact same logic to the toolPath handling in the tools
loop and keep using bmadPrefix, task.module/tool.module and relativePath
construction unchanged.
|
This need some checking and testing... |
…ath handling in command generator
BMAD Installation QA ReportExecutive Summary
All IDE counts match expected values, no unexpanded variables detected, correct path formats verified, and cross-platform parity confirmed. 1. Manifest Verification
Modules Installed
2. IDE Command BreakdownStandard IDEs (Expected: 41 = 10 agents + 25 workflows + 6 tasks)
Special IDEs
3. Variable AuditInstall-Time Variables (
|
| Directory | Unexpanded {{ found |
Status |
|---|---|---|
.claude/commands/ |
0 | PASS |
.gemini/commands/ |
0 | PASS |
Runtime Variables ({...}) - Should be preserved
| Variable | Present | Status |
|---|---|---|
{project-root} |
Yes | PASS |
{user_name} |
Yes | PASS |
Config File Values (win)
# core/config.yaml
user_name: myself
communication_language: English
document_output_language: English
output_folder: "{project-root}/_bmad-output"
# bmm/config.yaml
project_name: win
user_skill_level: intermediate
planning_artifacts: "{project-root}/_bmad-output/planning-artifacts"
implementation_artifacts: "{project-root}/_bmad-output/implementation-artifacts"
project_knowledge: "{project-root}/docs"4. Path Format Audit
| Check | Pattern | Matches Found | Status |
|---|---|---|---|
| Backslashes in paths | \\ |
0 | PASS |
| Absolute Windows paths | [A-Z]:\ |
0 | PASS |
| Leaked source paths | BMAD-METHOD |
0 | PASS |
Correct {project-root}/ usage |
{project-root}/ |
Present | PASS |
Sample verified paths:
{project-root}/_bmad/core/agents/bmad-master.md
{project-root}/_bmad/bmm/agents/analyst.md
{project-root}/_bmad/core/config.yaml
5. Cross-Platform Comparison
| Metric | Windows | Linux | Status |
|---|---|---|---|
| Claude commands | 41 | 41 | MATCH |
| Gemini commands | 41 | 41 | MATCH |
| Codex prompts | 41 | 41 | MATCH |
Config user_name |
myself | myself | MATCH |
Config output_folder |
{project-root}/_bmad-output |
{project-root}/_bmad-output |
MATCH |
6. Format Validation Samples
Gemini TOML (.gemini/commands/bmad-agent-bmad-master.toml)
description = "Activates the bmad-master agent from the BMad Method."
prompt = """
CRITICAL: You are now the BMad 'bmad-master' agent.
PRE-FLIGHT CHECKLIST:
1. [ ] IMMEDIATE ACTION: Load and parse {project-root}/_bmad/core/config.yaml...
...
"""Status: Valid TOML structure
Claude Markdown (.claude/commands/bmad-agent-bmad-master.md)
---
name: 'bmad-master'
description: 'bmad-master agent'
disable-model-invocation: true
---
<agent-activation CRITICAL="TRUE">
1. LOAD the FULL agent file from {project-root}/_bmad/core/agents/bmad-master.md
...
</agent-activation>Status: Valid YAML frontmatter + Markdown
Kilo YAML (.kilocodemodes)
customModes:
- slug: bmad-core-bmad-master
name: 'Bmad Master'
roleDefinition: You are a Bmad Master...
whenToUse: Use for Bmad Master tasks
customInstructions: |
You must fully embody this agent's persona...
groups:
- read
- edit
- browser
- command
- mcp
- slug: bmad-bmm-analyst
...Status: Valid YAML with 10 customModes
7. Agents Verified (10)
| Slug | Display Name | Module | File Verified |
|---|---|---|---|
| bmad-master | BMad Master | core | PASS |
| analyst | Mary | bmm | PASS |
| architect | Winston | bmm | PASS |
| dev | Amelia | bmm | PASS |
| pm | John | bmm | PASS |
| quick-flow-solo-dev | Barry | bmm | PASS |
| quinn | Quinn | bmm | PASS |
| sm | Bob | bmm | PASS |
| tech-writer | Paige | bmm | PASS |
| ux-designer | Sally | bmm | PASS |
8. Workflows Verified (25)
Core (2)
- brainstorming
- party-mode
BMM (23)
- Phase 1 - Analysis: create-product-brief, research
- Phase 2 - Plan: create-prd, create-ux-design
- Phase 3 - Solutioning: check-implementation-readiness, create-architecture, create-epics-and-stories
- Phase 4 - Implementation: code-review, correct-course, create-story, dev-story, retrospective, sprint-planning, sprint-status
- Quick Flow: quick-dev, quick-spec
- Documentation: document-project, generate-project-context
- Diagrams: create-excalidraw-diagram, create-excalidraw-dataflow, create-excalidraw-flowchart, create-excalidraw-wireframe
- QA: qa-automate
9. Standalone Tasks Verified (6)
| Task | Display Name | Status |
|---|---|---|
| editorial-review-prose | Editorial Review - Prose | PASS |
| editorial-review-structure | Editorial Review - Structure | PASS |
| help | help | PASS |
| index-docs | Index Docs | PASS |
| review-adversarial-general | Adversarial Review (General) | PASS |
| shard-doc | Shard Document | PASS |
Final Classification
SUCCESS (Hopefully, would be nice if someone does similar check)
All verification checks passed:
- All 18 IDEs have correct file counts
- No unexpanded
{{}}install-time variables in IDE files - Runtime variables
{...}correctly preserved - All paths use forward slashes
- No absolute or leaked paths detected
- Windows and Linux installations are identical
- All format validations passed
- Codex has 41 files (
.xmltask bug is fixed)
Summary
This PR fixes bugs affecting task/tool installation across IDEs:
\r\n) line endings.mdfiles instead of.tomlfor Gemini CLI.xmltask/tool files had incorrect paths (hardcoded.md)'_bmad'strings to use centralized constant.mdfiles, missing.xmltask filesworkflow.xmlwere incorrectly exposed to users.vscode/directory due to useless config entryinternal="true"were not being skipped like tasks wereC:/_bmad/...split('","')which breaks on fields containing commas or quotesProblem
Issue 1: Tasks not installed on Windows
The manifest generator's regex
^---\nexpected LF-only line endings, but Windows files have CRLF. This caused:.mdtasks defaulting tostandalone: falsebmad-helpnot being installed despite havingstandalone: truein their frontmatterIssue 2: Gemini CLI incompatibility
The
TaskToolCommandGeneratorhardcoded markdown format for all IDEs, but Gemini CLI requires TOML format. Agents and workflows already used the template system correctly, but tasks/tools did not.Issue 3: Incorrect file extensions in paths
The
relativePathproperty was hardcoded to.md, so tasks/tools with.xmlextension got incorrect paths like{project-root}/_bmad/core/tasks/index-docs.mdinstead of{project-root}/_bmad/core/tasks/index-docs.xml.Issue 4: Codex task generation broken
The
codex.jsinstaller failed to generate task commands due to multiple bugs:name,displayName,path)TaskToolCommandGeneratorwas instantiated withoutbmadFolderNameparameteragent/installer.js:context_bmadFolderinstead ofcontext.bmadFolderIssue 5: Scattered BMAD_FOLDER_NAME constant
The
'_bmad'folder name was hardcoded in multiple files (installer.js,_base-ide.js,ide/manager.js,modules/manager.js, and command generators). This made it error-prone to change and inconsistent.Issue 6: XML task files not discovered
The
bmad-artifacts.jstask discovery function only looked for.mdfiles, ignoring.xmltask files entirely. This caused XML-based tasks to be missing from IDE command generation.Issue 7: Internal engine tasks exposed to users
Internal engine tasks like
workflow.xml(used by the workflow execution engine) were incorrectly exposed to users as installable tasks. These internal tasks should be hidden since they are not meant to be invoked directly by users.Issue 8: GitHub Copilot creates empty .vscode directory
The GitHub Copilot platform config in
platform-codes.yamlhad a useless.vscodetarget with:artifact_types: [](empty array - no artifacts to install)template_type: vscode_settings(non-existent template)The
_config-driven.jsinstaller calledensureDir()before checking if any artifacts would be written, resulting in an empty.vscode/directory being created during installation.Issue 9: Internal tools not filtered
The
manifest-generator.jscorrectly skipped tasks withinternal="true"ingetTasksFromDir(), butgetToolsFromDir()had no such check. This meant internal tools (if any exist) would be incorrectly included in the tool manifest.Issue 10: Windows path regex fails on absolute paths
The
task-tool-command-generator.jsused a regex/_bmad/to extract relative paths from absolute paths. This pattern requires a leading/before_bmad, which works for Unix paths (/home/user/project/_bmad/...) but fails for Windows absolute paths (C:/_bmad/...) where there's no leading separator before the folder name.Issue 11: Fragile CSV parsing breaks on special characters
The
manifest-generator.jsfunctionswriteAgentManifest(),writeTaskManifest(), andwriteToolManifest()usedline.split('","')to parse existing CSV entries. This naive approach breaks when CSV fields contain:"A tool for X, Y, and Z")"Contains ""quoted"" text")Example:
This caused data corruption when re-running the installer, as entries with special characters would be incorrectly parsed and the wrong module/name would be extracted for the Map key.
Issue 12: Agent ID uses platform-specific path separators
The
compileModuleAgents()function inmodules/manager.jsandcompileAndCopyAgents()incustom/handler.jsusedpath.relative()to generate the agent ID. On Windows, this produces backslashes (e.g.,tech-writer\tech-writer.agent.yaml) while on Linux/macOS it produces forward slashes. This caused:Design Note: Intentional Hardcoded
'_bmad'StringsThe following
replaceAll('_bmad', ...)patterns are intentionally hardcoded and should NOT use the constant:_base-ide.js_bmadin template content_config-driven.js_bmadin rendered contentagent-command-generator.js_bmadin templatesworkflow-command-generator.js_bmadin templatesmodules/manager.js_bmadin YAML contentReason: These search for the literal string
_bmadthat exists in source template files, then replace it with the configured folder name (this.bmadFolderName). If we used the constant here, and someone configured a different folder name, the search pattern would fail to match the templates.Changes
Codex Fix (f334f66)
codex.js- Added missingname,displayName,pathproperties to task artifacts; passbmadFolderNametoTaskToolCommandGeneratortask-tool-command-generator.js- Added robust path handling with fallback for missing paths, absolute-to-relative conversionagent/installer.js- Fixed typocontext_bmadFolder→context.bmadFolderBMAD_FOLDER_NAME Centralization
path-utils.js- Added centralizedBMAD_FOLDER_NAMEconstantinstaller.js- Now importsBMAD_FOLDER_NAMEfrom path-utils_base-ide.js- Now importsBMAD_FOLDER_NAMEfrom path-utilside/manager.js- Now importsBMAD_FOLDER_NAMEfrom path-utilsmodules/manager.js- Now importsBMAD_FOLDER_NAMEfrom path-utilsagent-command-generator.js- UsesBMAD_FOLDER_NAMEfor default parametertask-tool-command-generator.js- UsesBMAD_FOLDER_NAMEfor default parameter and prefix matchingworkflow-command-generator.js- UsesBMAD_FOLDER_NAMEfor default parameterXML Task Discovery (ba00d43)
bmad-artifacts.js- ExtendedgetTasksFromDir()to include both.mdand.xmltask files; fixed extension removal for correct task namesInternal Task Filtering (12d4e1f)
workflow.xml- Addedinternal="true"attribute to mark as engine-internalmanifest-generator.js- Skip files containinginternal="true"during manifest generation_base-ide.js- Skip internal files during IDE command discoverybmad-artifacts.js- Skip internal files during task discoveryGitHub Copilot Empty Directory Fix
platform-codes.yaml- Removed useless.vscodetarget entry with emptyartifact_typesarray_config-driven.js- Added defensive guard to skip targets with explicitly emptyartifact_typesbefore callingensureDir()Internal Tools Filtering
manifest-generator.js- Addedinternal="true"check togetToolsFromDir()to match existing task behaviorWindows Path Regex Fix
task-tool-command-generator.js- Changed regex from/\/_bmad\//to/[/\\]_bmad[/\\]/to handle both Unix and Windows path separatorsFragile CSV Parsing Fix
manifest-generator.js- Addedcsv-parse/syncimport (already a project dependency)manifest-generator.js- Replacedline.split('","')withcsv.parse(content, { columns: true, skip_empty_lines: true })inwriteAgentManifest(),writeTaskManifest(), andwriteToolManifest()manifest-generator.js- AddedescapeCsvhelper function to properly escape quotes ("→"") per RFC 4180manifest-generator.js- Changed from storing raw CSV lines in Map to storing parsed record objects for cleaner mergingAgent ID Path Separator Fix
modules/manager.js- Changedpath.relative(sourceAgentsPath, agentFile)to normalize separators:.split(path.sep).join('/')custom/handler.js- Same fix applied tocompileAndCopyAgents()functionTest Plan
.tomlfiles for tasks/tools.mdfiles for tasks/tools.mdfilesbmad-helptask now correctly hasstandalone: truein manifest.xmltasks/tools get correct extension inrelativePathC:\...or Unix/...) produce correct relative paths in artifacts.xmltask files are discovered and included in IDE commandsworkflow.xml) are NOT exposed in manifests or IDE commandsinternal="true"attribute are filtered out at all discovery points.github/agents/with agent files.vscode/directoryinternal="true"attribute are filtered out (same as tasks)C:/_bmad/core/tasks/...) correctly resolve to relative pathstech-writer/tech-writer.agent.yaml)Breaking Changes
None - this is purely a bug fix. Existing installations will work correctly after reinstall.