* fix(installer): remove bmad-help from Copilot Custom Agents picker
Per @BMadCode's feedback after #2324 merged: every persona agent's
activation message already advertises bmad-help, so its picker entry is
redundant AND confusing (looks like a peer agent when it's actually the
meta-help). Removes the ALWAYS_AGENT_IDS allowlist exception that put it
there.
The toml-driven filter (the mechanism BMadCode endorsed in his PR review)
remains the sole signal: a skill is a persona iff its source
customize.toml has an [agent] section. bmad-help has no customize.toml,
so under the cleaned-up filter it's correctly excluded.
Tests: replaces the inclusion assertion in Suite 17 with an exclusion
assertion. Suite still covers persona / non-conventional persona /
workflow / meta-skill-with-`-agent-`-in-name cases.
Refs #2324
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* test: clarify Suite 17 fixture comment per PR review
The fixture creates no customize.toml at all for bmad-help, so the
exclusion path being exercised is the missing-file branch — not the
file-without-[agent]-section branch. Reword the comment accordingly.
Per @augmentcode review on #2359.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(installer): generate OpenCode /<skill> slash commands
Adds .opencode/commands/<canonicalId>.md pointer files for each installed
skill so users can invoke skills directly (e.g. /bmad-quick-dev) instead
of going through the /skills menu.
- platform-codes.yaml: add commands_target_dir field for opencode
- _config-driven.js: installCommandPointers() with skip-if-exists default,
reserved-name collision guard, YAML-safe description quoting
- _config-driven.js: cleanupCommandPointers() for symmetric uninstall
- test-installation-components.js: extend OpenCode suite with assertions
covering pointer creation, content, and idempotency
OpenCode-only and opt-in via the new yaml field; other adapters unchanged.
Refs #2267
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(installer): address PR #2324 review feedback
Six fixes from CodeRabbit + Augment review on the OpenCode command
pointer generation:
- skipTarget no longer suppresses installCommandPointers in multi-IDE
shared-target_dir batches. Pointers live in a per-IDE directory and
are not deduped across peers, so OpenCode must still generate them
even when a peer (e.g. openhands) won the .agents/skills write race.
- skipTarget no longer suppresses cleanupCommandPointers either, so
partial uninstalls leave no stale pointers when a peer remains.
- canonicalId is validated as a safe basename before being interpolated
into a file path (defense in depth against a malformed manifest entry
writing outside commands_target_dir).
- yamlSafeSingleLine now quotes descriptions starting with `[` or `{`
so YAML doesn't parse them as a sequence/map.
- Per-record fs.writeFile failures are caught and counted (writeFailures)
rather than aborting the whole IDE install — pointer files are a
non-essential adjunct to the skill copy.
- Generator-shaped pointer files are refreshed when the manifest
description changes; hand-modified files (body diverges from the
generator pattern) are still preserved unless forceCommands is set.
Tests: extends Suite 8 with description-update propagation; adds new
Suite 40c covering OpenCode + openhands batches in both orderings plus
partial-IDE uninstall pointer cleanup. 308 tests pass (was 296).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(installer): address PR #2324 follow-up nitpicks
Four nitpicks from CodeRabbit's original review that were missed in the
first triage pass:
- Hand-edited pointers now survive the production install flow.
cleanupCommandPointers spares pointers for canonicalIds that are still
in the new manifest when called from the install/update flow (signal:
options.previousSkillIds is set). Uninstall and partial-IDE removal
flows still wipe pointers as before. The previous behavior wiped every
pointer in removalSet before installCommandPointers could run, so its
skip-if-exists guard never fired and hand edits were lost on every
reinstall — contradicting the docstring's preservation claim.
- RESERVED_OPENCODE_COMMANDS is now gated on this.name === 'opencode'
so future adapters opting into commands_target_dir don't silently
inherit OpenCode's reserved-name set.
- printSummary now surfaces results.commands so users see how many
pointers were created/refreshed/skipped per install, plus a warning
for any per-file write failures.
- Dropped a dead `typeof entry !== 'string'` check; fs.readdir without
withFileTypes always yields strings.
Tests: extends Suite 8 with a hand-edit-preservation regression that
calls setup with previousSkillIds (the production shape) and asserts a
sentinel byte sequence in the pointer body survives. 310 tests pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(installer): extend command-pointer generation to Copilot Custom Agents
Re-scopes #2324 to cover the second user-facing pain: GitHub Copilot's
Custom Agents picker, where installed BMAD skills currently don't show up
even though slash commands work natively.
Generalizes the per-platform pointer-file mechanism so the same
installCommandPointers / cleanupCommandPointers code path serves both
OpenCode (slash commands palette) and Copilot (Custom Agents picker), with
all platform-specific shape pushed into platform-codes.yaml as data:
- commands_target_dir — where pointer files live (existing)
- commands_extension — file extension (default '.md'; Copilot uses
'.agent.md' per VS Code Custom Agents docs)
- commands_body_template — pointer body, supports {canonicalId} and
{target_dir} placeholders. Default matches
OpenCode's `@skills/<id>` resolver. Copilot
has no such resolver, so its template uses
the {project-root}/<target_dir>/<id>/SKILL.md
LOAD pattern (consistent with PR #1769).
OpenCode behavior is unchanged. Copilot users now get a per-skill
.github/agents/<canonicalId>.agent.md file that surfaces the skill in the
Custom Agents picker — addressing the "agents being gone" complaint
flagged by enterprise users.
Tests: extends Suite 17 with assertions for Copilot agent pointer
creation, body content (LOAD pattern with {project-root}-rooted path),
and idempotency. 318 tests pass (was 310).
Refs #2267
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(installer): filter Copilot Custom Agents picker to persona agents only
Earlier commit naively wrote a `.github/agents/<id>.agent.md` for every
installed skill, which would clutter the Custom Agents picker with 90+
workflow/tool entries that don't belong there.
Adds an `agents-only` filter that gates the per-skill emission on whether
the canonical id signals a persona agent:
- Primary rule: id contains `-agent-` (e.g. `bmad-agent-pm`,
`gds-agent-game-dev`, `wds-agent-freya-ux`,
`bmad-cis-agent-storyteller`).
- Allowlist: `bmad-tea` — TEA's Murat persona uses the bare module code
rather than the `-agent-` convention. Listed explicitly so the rule
still surfaces it.
Verified against the full installed manifest (114 skills): catches all
20 description-confirmed personas across BMM, CIS, GDS, WDS, TEA;
excludes all 94 workflows/tools.
Wired through a new yaml field on github-copilot:
commands_filter: agents-only
OpenCode is unaffected — it has no `commands_filter` set, so the loop
behaves as before (every skill becomes a slash command).
Tests: extends Suite 17 with a multi-skill manifest fixture covering
persona/agent + bmad-tea + workflow cases; asserts persona agents and
bmad-tea get .agent.md files while workflows do not. 322 tests pass.
Refs #2267
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(installer): detect personas via customize.toml [agent] section
Per maintainer review on PR #2324: the `-agent-` naming convention isn't
a load-bearing contract anywhere else in the codebase, and the bmad-tea
allowlist already shows it starting to break. A future persona that
doesn't follow the convention would silently disappear from the Copilot
Custom Agents picker.
Replaces the name-based filter with a behavior-based signal: read each
skill's source `customize.toml` and check for an `[agent]` section. This
is the actual configuration source of truth — every BMAD persona is
configured under `[agent]`, every workflow under `[workflow]`, every
standalone skill has no customize.toml.
Verified on disk against the full installed manifest (114 skills):
- 20 personas detected — exactly the description-confirmed count across
BMM, CIS, GDS, WDS, TEA. bmad-tea is caught natively (no allowlist).
- 94 workflows/tools correctly excluded.
- `bmad-agent-builder` (meta-skill that builds agent skills) is now
CORRECTLY excluded — its canonical id contains `-agent-` but its
customize.toml has [workflow], not [agent], because it isn't a
persona itself. The previous naming-based filter was including it in
the agents picker, which would have been a silent UX bug.
`NON_CONVENTIONAL_AGENT_IDS` constant is removed entirely — the toml
signal subsumes it.
Tests: extends Suite 17 with a 4-skill fixture that covers persona +
non-conventional persona + workflow + meta-skill cases. 388 tests pass.
Refs #2267
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(installer): always include bmad-help in Copilot agents picker
Adds a single, deliberate exception to the toml-based agents-only filter:
`bmad-help` is the structural meta-skill across BMAD — the orientation
helper that points users at every other skill. Users invoke it
persona-style ("ask the helper") even though it has no `[agent]`
customize.toml of its own (it isn't a configurable persona).
Implemented as a one-element ALWAYS_AGENT_IDS set rather than a hardcode
in the function body so the exception is named, documented, and
discoverable. The skill is structurally unique — there is no second
meta-help skill — so this is not the start of a growing allowlist; it's
a one-off for the one orientation surface BMAD ships.
Verified on disk: agents picker now shows 21 entries (20 personas via
[agent] in customize.toml + bmad-help). bmad-agent-builder stays
correctly excluded (its customize.toml has [workflow], not [agent]).
Tests: extends Suite 17 with a `bmad-help` fixture (no customize.toml,
must still appear in agents picker). 389 tests pass.
Refs #2267
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Brian <bmadcode@gmail.com>
* fix(installer): handle deep-path URLs in custom module source parser
Rewrite parseSource() from host-specific regex to generic URL-based
parser so Azure DevOps _git paths and other multi-segment repo URLs
are preserved in cloneUrl and cacheKey.
Closes#2268
* test(installer): add Azure DevOps URL tests and wire into CI
- Add 18 assertions for dev.azure.com and visualstudio.com URLs
- Cover modern ADO, legacy ADO, .git suffix, ?path= subdir variants
- Add test:urls script to test and quality npm chains
---------
Co-authored-by: Brian <bmadcode@gmail.com>
Closes#1663.
Adds two installer flags so module config options can be set without
interactive prompts. Designed for CI scripts, Dockerfiles, and
enterprise rollouts where the user wants to bake answers into the
install command rather than answer prompts.
`--set <module>.<key>=<value>` (repeatable) sets any module config
option. `--list-options [module]` lists every key the installer can
discover locally — built-in modules (`core`, `bmm`) plus any cached
official modules. One flag scales to every module without growing the
CLI surface per option.
```bash
npx bmad-method install --yes \
--modules bmm --tools claude-code \
--set bmm.project_knowledge=research \
--set bmm.user_skill_level=expert \
--set core.user_name=Brian
```
## How it works
`--set` is a post-install patch. The installer runs its normal flow
untouched, then `applySetOverrides` upserts each value into the
relevant config files:
- `_bmad/config.toml` (team scope, default)
- `_bmad/config.user.toml` (user scope, when the key already lives
there — so user-scope keys like `core.user_name` and
`bmm.user_skill_level` keep their proper file)
- `_bmad/<module>/config.yaml` (so declared schema keys carry forward
via the existingValue path on the next install)
A module without `_bmad/<module>/config.yaml` is skipped silently —
no orphan sections in `config.toml` for uninstalled modules.
## Tradeoffs documented in install-bmad.md
- **Verbatim values.** `--set bmm.project_knowledge=research` writes
`"research"`, not `"{project-root}/research"`. The `result:`
template is not applied. Pass it explicitly if you want the
rendered form: `--set bmm.project_knowledge='{project-root}/research'`.
- **Carry-forward, declared keys.** Free — values land in the
per-module `config.yaml`, so the next install reads them as
`existingValue` and they become the prompt default (accepted under
`--yes`).
- **Carry-forward, undeclared keys.** Best-effort. The value lives in
`config.toml` for the current install but won't be re-emitted on
the next install (the manifest writer's schema-strict partition
drops unknown keys). Re-pass `--set` if needed.
- **No "key not in schema" validation.** Whatever you assert is
written.
## Security
Prototype-pollution defense: `--set __proto__.x=1` would otherwise
reach `overrides.__proto__[x] = 1` and pollute `Object.prototype`,
cascading into every plain-object lookup in the process. Defense-in-
depth via parser-level reserved-name rejection (`__proto__`,
`prototype`, `constructor`) AND `Object.create(null)` for the
override maps. Verified the attack reproduces without the guard and
is blocked with it.
## What's intentionally NOT integrated
`--set` deliberately does not touch the prompt / template / schema
collection flow. No pre-seeding answers, no question filtering, no
function-default evaluation, no schema-strict partition exemption.
That earlier integration approach was tried and scrapped: it
spread state across `Config`, `OfficialModules`,
`manifest-generator`, both collection helpers, and required parallel
plumbing for quick-update — every bug fix touched a different layer.
The post-install patch model covers the actual user need (set a
config value from CI) in ~330 lines of `set-overrides.js` without
the schema gymnastics.
## Files
- `tools/installer/set-overrides.js` (new): parser, prototype-pollution
guard, `applySetOverrides` post-install patch, `upsertTomlKey` /
`tomlString` / `tomlHasKey` line-based TOML helpers
- `tools/installer/list-options.js` (new): module.yaml discovery +
formatter for `--list-options`
- `tools/installer/commands/install.js`: register `--set` /
`--list-options` flags, early validation, `--list-options` exit-code
handling (await `stream.write` callback then `process.exitCode` to
avoid truncating piped output), thread `setOverrides` through to
quick-update
- `tools/installer/core/config.js`: carry `setOverrides` field for
the post-install patch step
- `tools/installer/core/installer.js`: invoke `applySetOverrides`
after `writeCentralConfig` (covers regular install + quick-update
via the shared install path)
- `tools/installer/ui.js`: parse `--set` for early validation, warn
about overrides targeting modules not in `--modules`, drop those
entries before threading
- `docs/how-to/install-bmad.md`, `README.md`: usage, routing rules,
carry-forward semantics, tradeoffs
## Test plan
Suite 44 (24 cases): parser, prototype-pollution guard, `tomlString`
escaping, `upsertTomlKey` across insert/replace/missing-section/
empty-file/preserved-newline cases, `applySetOverrides` happy path +
uninstalled-module skip + missing-user-toml-creation + empty-input
no-op, `discoverOfficialModuleYamls` / `formatOptionsList` sanity
(hermetic via `BMAD_EXTERNAL_MODULES_CACHE` temp dir). 355 total
passing. Lint + prettier + markdownlint clean.
E2E smoke verified across:
- [x] `--set` writes correct files (team toml / user toml / per-module
yaml) for declared and undeclared keys
- [x] Quick-update without `--set` carries forward declared keys via
`existingValue` path
- [x] Quick-update WITH `--set` applies cleanly (uniform behavior
across action types)
- [x] `--set` for unselected module: warned, no orphan section
- [x] Prototype pollution: rejected with non-zero exit
- [x] `--list-options bmm` exit 0 with full output through pipe;
`--list-options nope` exit 1
- [x] Translated docs (`docs/{cs,fr,vi-vn,zh-cn}/`) intentionally not
touched — they'll lag behind English until the translation pipeline
runs
* fix(config): promote project_name to core, fixes#2279
project_name was a bmm-specific prompt despite being a universal
project-level concept used by every module — including core skills like
bmad-brainstorming, which loads from _bmad/core/config.yaml and was
silently broken because project_name lived under bmm. Users without bmm
installed could not run brainstorming at all.
Move:
- src/core-skills/module.yaml: declare project_name with prompt
"What is your project called?" and default {directory_name}, matching
what bmm previously had.
- src/bmm-skills/module.yaml: remove the bmm definition; add project_name
to the "Variables from Core Config inserted" header comment so
contributors can see what's inherited.
Migration for existing installs:
- tools/installer/modules/official-modules.js: after loadExistingConfig
reads each per-module config.yaml, hoist any keys that are now declared
in core but appear under non-core modules. Without this, the partition
logic in writeCentralConfig (which strips core keys from non-core
buckets) would silently drop the user's prior project_name on the next
quick-update. Generic — handles project_name today and any future
module→core promotions.
- The hoist preserves precedence: an existing core value beats a stale
module-side copy.
--yes seed:
- tools/installer/ui.js: add project_name to the hardcoded core seed
(using path.basename(directory) to match the {directory_name} default)
so non-interactive fresh installs populate it. Without this the seed
silently omits project_name and core skills fall back to literals.
Tests:
- test/test-installation-components.js Suite 43 (9 assertions) covers
the schema move, the loadExistingConfig hoist, and the precedence rule.
- Suite 35 fixture updated: project_name moved from bmm bucket to core,
with a stale bmm copy left in place to verify it gets stripped.
Verified manually:
- Fresh install -y: project_name lands in [core] of config.toml.
- Existing install with project_name in bmm/config.yaml: quick-update
hoists it to [core] and strips it from [modules.bmm].
* fix(installer): harden config-load against malformed config.yaml
Per augment review on #2348: loadExistingConfig stored any truthy
yaml.parse result (including scalars like '42'), which would later crash
_hoistCoreKeysFromLegacyModuleConfigs at \`key in cfg\` with
"Cannot use 'in' operator to search for ... in 42".
- loadExistingConfig: only keep parses that are plain objects (not
scalars or arrays). A corrupt config.yaml is now treated the same as
a parse error — skipped, not crashed-on.
- _hoistCoreKeysFromLegacyModuleConfigs: belt-and-suspenders type guards
on _existingConfig.core (in case it's populated by some other path)
and on each module cfg in the loop.
- Test Suite 43 adds 2 assertions covering a scalar core/config.yaml:
loadExistingConfig must not crash, and bmm.project_name must still
hoist into a clean core bucket.
* fix(installer): require --tools for fresh --yes installs; remove --tools none (closes#2326)
Fresh non-interactive installs without --tools previously produced a
config-only install (~35 files vs ~1400 in the manifest) with no warning
and a "BMAD is ready to use" success card, leaving slash commands
unreachable. --tools none was an explicit opt-in for the same broken
state.
Now: fresh install + -y without --tools throws a helpful error pointing
at --list-tools. --tools none is rejected as an unknown ID. Empty and
typo'd tool IDs are also rejected. Existing-install paths (--action
update, quick-update, modify) are unchanged - they continue to reuse
previously-configured tools when --tools is omitted.
Adds --list-tools flag that prints all 42 supported tool IDs (id, name,
target_dir, preferred star) sourced from platform-codes.yaml.
English docs updated; localized docs (vi-vn, fr, cs, etc.) will sync via
the normal translation pass.
* fix(installer): address review for #2326 — single source of truth, drop dead code, add tests
- Refactor formatPlatformList to use IdeManager so --list-tools and --tools
validation see the same set of platforms. Eliminates the drift where suspended
platforms appeared in --list-tools but were rejected at validation.
- Drop unused getValidPlatformIds export.
- Flatten redundant block scope around the throw in the --yes-without-tools
branch (refactor leftover).
- Drop dead String() defensive cast (Commander always passes a string).
- Add Test Suite 42: 8 unit tests covering _parseToolsFlag empty/whitespace/
unknown/typo cases plus an integration check that --list-tools output and
--tools validation agree on the ID set.
* fix(installer): close --tools "" bypass and drop hardcoded tool count
- Replace truthy `if (options.tools)` guard with `!== undefined` in both
upgrade and fresh-install branches. Empty string now reaches
_parseToolsFlag and produces the specific "passed empty" error
instead of falling through to a generic message (fresh-install) or
being silently ignored (existing-install).
- Drop the hardcoded "42 supported tools" count from the prereqs in
install-bmad.md so the doc doesn't drift as platform-codes.yaml
changes.
Addresses augment / coderabbit review on #2346.
* refactor(installer): replace legacy_targets auto-cleanup with upgrade warnings
Removes the legacy_targets YAML field and its install-time auto-migration
of pre-v6.1.0 directories (.claude/commands, .opencode/agents, etc.). On
install, surface a warning instead: read manifest version and scan 24
known legacy paths, then print rm -rf commands the user can run themselves.
Also deletes orphan tools/platform-codes.yaml (never loaded by any code)
and fixes a stale URL in the cs translation.
* feat(installer): consolidate to .agents/skills and add global_target_dir for all platforms
Updates platform-codes.yaml against verified primary docs for all 24 supported
platforms. 14 platforms (auggie, codex, crush, cursor, gemini, github-copilot,
kilo, kimi-code, opencode, pi, roo, rovo-dev, windsurf) move their project
target_dir to the cross-tool .agents/skills/ standard. Junie moves from the
broken .agents/skills/ to its own .junie/skills/ per JetBrains docs.
Adds global_target_dir to every platform: 11 share ~/.agents/skills/, Crush
uses XDG ~/.config/agents/skills/, Codex global stays ~/.codex/skills/, the
rest are tool-specific. Ona and Trae omit global (no documented home path).
Note: installer logic does not yet dedupe writes for platforms sharing a
target_dir — users installing multiple .agents/skills/ tools together will
overwrite the same files (harmless on install, but uninstalling one clears
the dir for the others). Coordination logic is the next step.
* feat(installer): add 18 new platforms, dedup shared target_dir, ownership-aware cleanup
Adds 18 platforms from the verified Vercel list (adal, amp, bob, command-code,
cortex, droid, firebender, goose, kode, mistral-vibe, mux, neovate, openclaw,
openhands, pochi, replit, warp, zencoder). Marks codex and github-copilot as
preferred alongside claude-code and cursor.
Coordination for platforms sharing a target_dir:
- IdeManager.setupBatch dedups skill writes when multiple selected platforms
point at the same target_dir (e.g. .agents/skills/). The first platform
writes, peers skip the redundant wipe-and-rewrite. Result reports the same
count and target dir for every member so the install summary is consistent.
- IdeManager.cleanupByList accepts remainingIdes; when removing one platform
from a shared dir while another co-installed platform still owns it, the
target_dir wipe is skipped. Platform-specific hooks (copilot markers, kilo
modes, rovodev prompts) still run.
- _setupIdes uses setupBatch; _removeDeselectedIdes passes remainingIdes so
partial reconfigure preserves shared skills.
Skill ownership now uses skill-manifest.csv canonicalIds, not the bmad- prefix.
This unblocks custom modules that ship skills with non-bmad names (e.g.
fred-cool-skill). Affected sites:
- _config-driven.detect: reads canonicalIds from the project's bmadDir
- _config-driven.findAncestorConflict: reads canonicalIds from the ancestor's
own bmadDir, falling back to the prefix only when no manifest exists
- legacy-warnings.findStaleLegacyDirs: same canonicalId-based detection
Migration warnings: LEGACY_SKILL_PATHS adds 12 skill dirs that moved to the
.agents/skills/ standard (cursor, gemini, github-copilot, kimi, opencode, pi,
roo, rovodev, windsurf, plus their globals). Users with stale skills in those
locations get a one-line warning with the rm command per dir.
New shared helper tools/installer/ide/shared/installed-skills.js exposes
getInstalledCanonicalIds(bmadDir) and isBmadOwnedEntry(entry, canonicalIds).
Tests: 9 new assertions across two suites covering dedup, partial uninstall
preservation, and custom-module skill detection. All 286 tests pass.
* fix(installer): setupBatch must not claim a shared target_dir on failure
If the first platform's setup throws or returns success: false, the dedup map
previously still recorded the claim with skillCount: 0, causing every peer
sharing the target_dir to skip its install — leaving the dir empty/broken
behind a cascade of misleading "shares with X" rows.
Now the claim is only recorded when the install succeeded and wrote skills.
On failure, the next peer becomes the new first writer and recovers.
Adds Suite 40b regression test that monkey-patches cursor.setup to throw
and verifies gemini still populates the shared dir.
* fix(installer): address PR #2313 review findings
Three issues raised by augmentcode and coderabbit bot reviewers:
1. _removeDeselectedIdes silently swallowed cleanup failures after the
refactor to cleanupByList. The old per-IDE try/catch logged a warning;
the new path discarded the result array. Now logs a warning per failed
ide so failures stay visible.
2. The legacy-dir cleanup hint printed `rm -rf "<path>"/bmad*` which both
matched bmad-os-* utility skills the user should keep AND missed the
custom-module skills (e.g. fred-cool-skill) that the new canonical-id
detection now finds. Findings now carry the exact entry names from the
scan, and the warning prints one precise rm line per entry.
3. warnPreNativeSkillsLegacy did unguarded fs reads at install start. A
permission/IO error would have aborted the whole install. Wrapped the
call site in try/catch so legacy-scan failures only emit a warning.
* feat(installer): channel-based version resolution for external modules
Adds stable/next/pinned channel resolution so external/community modules
install at released git tags by default instead of tracking main HEAD.
Manifest now records channel, resolved version, and SHA per module for
reproducible installs.
CLI flags: --channel, --all-stable, --all-next, --next=CODE (repeatable),
--pin CODE=TAG (repeatable). Precedence: pin > next > channel > registry
default > stable. --yes accepts patch/minor upgrades but refuses majors.
Interactive "Ready to install (all stable)?" gate with a per-module
picker (stable/next/pin) when declined. Re-install prompts classify tag
diffs as patch/minor/major with semver-class-dependent defaults.
Legacy version:null manifests get a one-time migration prompt.
Custom modules gain an optional @<ref> URL suffix for pinning (https,
ssh, /tree/<ref>/subdir forms supported; local paths rejected).
Community modules honor --next/--pin overrides with a curator-bypass
warning; default path still enforces the approved SHA.
Quick-update now reads the manifest's recorded channel per module so
pinned installs don't silently roll forward.
* feat(installer): interactive channel switch, upgrade refusal, unified docs
Builds on the channel-resolution foundation. The installer now lets users
flip a module between stable, next, and pinned after install — either
interactively via a "Review channel assignments?" gate, or by flag. Quick
and modify re-installs classify stable upgrades; under non-interactive
flows, patches and minors apply automatically but majors are refused with
a pointer to --pin.
Fallback behavior for GitHub rate-limit / network failures is now cache-
aware: re-installs reuse the recorded ref silently; fresh installs abort
with actionable guidance (set GITHUB_TOKEN or use --next/--pin). Bundled
modules (core, bmm) warn when targeted by --pin or --next so users aren't
left wondering why the flag had no effect.
Install summary labels no longer mangle "main" into "vmain"; next-channel
entries render as "main @ <short-sha>" instead. Bundled modules are now
correctly skipped from all channel prompts and tag-API lookups.
Docs consolidated into a single how-to. install-bmad.md now covers the
interactive flow, the channel model (stable/next/pinned plus the npm
dist-tag axis for core/bmm), the re-install upgrade prompts, the full
flag reference, copy-paste recipes, and troubleshooting. The old
non-interactive-installation.md is reduced to a redirect stub.
* fix(installer): review fixes + unit tests for channel resolution
- ui.js: import parseGitHubRepo; fixes ReferenceError in the
interactive channel picker's stable-tag pre-resolve path.
- community-manager: pinned modules now fetch+checkout the pin tag
on cache refresh instead of resetting to origin/HEAD (was silently
drifting to main on re-install).
- channel-plan: parseChannelOptions returns acceptBypass so --yes
auto-confirms the curator-bypass prompt; headless --next/--pin
installs of community modules no longer hang.
- community-manager: simplify recordedVersion (dead ternary branch).
- custom-module-manager: drop "or sha" from the @<ref> comment
(git clone --branch rejects raw SHAs); update-path fetches
origin <ref> so /tree/<branch>/ URLs work too.
- install-bmad.md: rename "Headless / CI installs" to "Headless CI
installs" so the stub's #headless-ci-installs anchor resolves.
- test/test-installer-channels.js: 83 unit tests for channel-plan
and channel-resolver pure modules; wired into npm test as
test:channels.
* fix(installer): address CodeRabbit review findings
- ui.js: skip stable-channel upgrade classification when the user has
already declared intent via --pin/--next=/--channel or the review
gate. Prevents the decline / major-refused / fetch-error branches
from silently overwriting an explicit pin with prev.version.
- external-manager.js: short-circuit cloneExternalModule when the
requested plan matches an existing in-process resolution and the
cache is valid. Avoids redundant resolveChannel() + git fetch on
every same-plan lookup in a single install.
- installer.js: fall back to CommunityModuleManager.getResolution()
when no external resolution exists, so community module result
rows carry newChannel/newSha instead of null under --next/--pin.
- installer.js: don't label a module as "no change" when its version
string is 'main'/'HEAD' — the SHA may have moved and preVersions
doesn't track the prior SHA. Show "(refreshed)" instead.
- official-modules.js: match versionInfo.version to the manifest's
cloneRef || (hasGitClone ? 'main' : version) expression so summary
lines report the cloned ref for git-backed custom installs.
- install-bmad.md: clarify that sha is only written for git-backed
modules and that rerunning the same --modules on another machine
does not reproduce stable-channel installs — convert recorded tags
into explicit --pin flags for cross-machine reproducibility.
External official modules (bmb, cis, gds, tea, wds) are cloned to
~/.bmad/cache/external-modules/<name>/ and never copied into src/modules/,
so collectAgentsFromModuleYaml silently skipped them and their agents
never reached config.toml. Swap the hardcoded src/modules lookup for a
resolveInstalledModuleYaml() helper that also searches the external cache
(handling src/, skills/, nested, and root layouts) and warns instead of
silently skipping when a module.yaml can't be found.
* feat(agents): set team to software-development on BMM agents
All six BMM agents (analyst, tech-writer, PM, UX designer, architect,
dev) now explicitly declare `team: software-development` in the
module.yaml roster instead of falling back to the module-code default
of `bmm`.
This matches the BMad-wide team convention where agents across modules
that collaborate on software delivery share one named team. Tea's Murat
joins the same team via a parallel PR in bmad-method-test-architecture-
enterprise so party-mode, help catalog, and retrospective skills can
route the full software-delivery roster as a single unit.
* test: update team assertions for explicit software-development
* refactor: remove bmad-skill-manifest yaml; introduce four-layer central config.toml
- Agent essence moves from per-skill bmad-skill-manifest.yaml files
into each module.yaml's `agents:` block (code, name, title, icon,
description). Per-agent customize.toml remains the deep-behavior
source of truth.
- Installer emits four TOML files:
_bmad/config.toml team install answers + agent roster
_bmad/config.user.toml user install answers
_bmad/custom/config.toml team overrides stub
_bmad/custom/config.user.toml personal overrides stub
Prompts declare scope: user to route answers to config.user.toml.
- resolve_config.py merges four layers: base-team -> base-user ->
custom-team -> custom-user.
- Three consumer skills (party-mode, advanced-elicitation,
retrospective) switched from agent-manifest.csv to the resolver.
- installer.js mergeModuleHelpCatalogs now takes the in-memory
agent list from ManifestGenerator -- no CSV roundtrip.
- Deleted: 6 bmad-skill-manifest.yaml files, agent-manifest.csv
emission, collectAgents/getAgentsFromDirRecursive,
paths.agentManifest().
* fix(installer): strip core-key pollution from [modules.*]; soften config headers
- writeCentralConfig now always strips core-module keys from every
[modules.<code>] bucket, even when the module's schema is not
available in src/ (external / marketplace modules like cis, bmb).
Core values belong in [core] only; workflows read them directly.
- When the module's own schema IS available (built-in modules),
also drop any key it does not declare as a prompt — same
spread-pollution filter as before, now layered on top.
- Section-aware headers on both _bmad/config.toml and
_bmad/config.user.toml: [core] / [modules.*] values are
editable (installer reads them as defaults on next install);
[agents.*] is regenerated from module.yaml and will be wiped —
overrides for agents go in _bmad/custom/config*.toml instead.
* docs: cover central config.toml + Diataxis prose pass across three files
Document the new four-file central configuration surface (_bmad/config.toml,
config.user.toml, and custom/ overrides) alongside the existing per-skill
customize.toml. Make editing rules, scope partitioning, and when-to-use-which
guidance explicit.
- customize-bmad.md: new "Central Configuration" section with editing rules,
three worked examples (rebrand, fictional agent, module settings override),
and a "when to use which surface" table. Converted five h4 headers to
bold paragraph intros per style guide.
- expand-bmad-for-your-org.md: two-layer mental model extended to three;
new Recipe 5 with three variants (rebrand, custom crew, pinned team
settings); reinforcement table extended.
- named-agents.md: noted the dual customization surface — per-skill shapes
behavior, central config shapes roster identity.
Diataxis prose pass applied across all three files: banned vocabulary
check, em-dash cap, hypophora / metanoia / amplificatio / stakes-inflation
cleanup, rhythm and burstiness fixes. Structural conformance verified;
markdownlint and prettier clean.
* test+docs: add central config unit tests; fix stale recipe count
- test: two new suites (35 + 36) covering writeCentralConfig and
ensureCustomConfigStubs. Verifies scope partitioning (user_name
lands only in config.user.toml), core-key pollution stripping
from [modules.*], unknown-schema fallthrough (external modules
survive without schema), agent roster baked into config.toml
[agents.*] only, stub-preservation on re-install. 44 new
assertions.
- docs: fixed four stale "four recipes" references to say "five"
after Recipe 5 (Customize the Agent Roster) was added. Touches
frontmatter, opening paragraph, Combining Recipes paragraph,
and the named-agents cross-link blurb.
* fix: address PR review feedback on central config
- resolve_config.py argparse: three-layer → four-layer description
- SKILL/workflow/explanation docs: document all four layers including
_bmad/config.user.toml (was missing from merge-stack descriptions)
- customize-bmad.md + installer headers: drop the false "direct edits to
config.toml persist" claim; installer reads from per-module config.yaml,
not central TOML, so direct edits get clobbered. Route users to
_bmad/custom/config.toml for durable overrides
- writeCentralConfig: warn loudly when a module.yaml can't be parsed
(previously silent — user-scoped keys could mis-file into team config)
- writeCentralConfig: preserve [agents.*] blocks for modules that didn't
contribute fresh agents this run (e.g. quickUpdate skipping modules
whose source is unavailable) so the roster doesn't silently shrink
- add extractAgentBlocks helper + Test Suite 37 covering preservation
Addresses comments from augmentcode and coderabbitai on PR #2285.
* feat(installer): use GitHub API as primary fetch with raw CDN fallback
Corporate proxies commonly block raw.githubusercontent.com while allowing
api.github.com. Add fetchGitHubFile() to RegistryClient that tries the
GitHub Contents API first, falling back to the raw CDN transparently.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(installer): cap redirect depth and preserve dual-fallback errors
Add maxRedirects parameter to fetch() and _fetchWithHeaders() to prevent
unbounded redirect recursion. Wrap CDN fallback in try/catch and throw
AggregateError with both API and CDN errors for better diagnostics.
Extract marketplace repo coordinates into named constants in
external-manager.
* chore(installer): drop unused fetchJson and fetchGitHubJson
Neither method has any callers. Also drop the corresponding test.
* refactor(test): fold registry tests into test-installation-components
No reason for RegistryClient tests to be a separate runner — the same
file already tests the registry consumers in Suite 33. Drop test:registry
from package.json scripts and quality gate.
* fix(installer): include URL, API message, and rate-limit info in HTTP errors
Non-2xx responses previously yielded bare `HTTP 403`. Now surface the
request URL, GitHub's JSON error message (or body snippet), X-RateLimit-Reset
when quota is exhausted, and Retry-After. Turns a mystery 403 into
'rate limit exhausted; resets at 2026-04-15T18:00:00Z' — the difference
between 'try GITHUB_TOKEN' and a wild goose chase.
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fs-extra routes all operations through graceful-fs, which globally
monkey-patches node:fs with a deferred retry queue. During multi-module
installs (~500+ file ops), retried unlink operations from one module's
remove phase can fire after the next module's copy phase has written
files, silently deleting them non-deterministically.
Replace fs-extra with a thin fs-native.js wrapper over node:fs/promises
and node:fs. All 21 consumers now use native APIs with no global
monkey-patching, eliminating the retry-queue race condition entirely.
Closes#1779
* chore(installer): remove dead code across installer modules
Delete 3 entirely dead files (agent-command-generator, bmad-artifacts,
module-injections) and remove ~50 unused exports from manifest.js,
cli-utils.js, prompts.js, path-utils.js, official-modules.js,
external-manager.js, custom-module-manager.js, and registry-client.js.
Removes corresponding dead tests.
* fix(installer): restore currentProjectDir writes for placeholder expansion
The previous commit removed the three assignments to
OfficialModules.currentProjectDir as dead code, but buildQuestion()
still reads the property to resolve {directory_name} placeholders in
module config defaults during interactive collection. Without the
writes, any module default containing {directory_name} would surface
the literal placeholder to users.
* feat(installer): add community module browser and custom URL support
Three-tier module selection: official, community (category drill-down
with featured/search), and custom GitHub URL.
- Add RegistryClient shared fetch utility
- Add CommunityModuleManager with SHA-pinned cloning (refuses install
if approved SHA cannot be reached; uses HEAD when no SHA set)
- Add CustomModuleManager for arbitrary GitHub repo installation
- Extend findModuleSource chain with community and custom fallthrough
- Extend manifest to detect community and custom source types
- Add Config.customModulesMeta for custom module metadata
* fix: resolve review findings for community/custom module support
- Remove redundant CommunityModuleManager instantiation in UI display
- Remove dead customModulesMeta field from Config (never populated)
- Add 35 unit tests for CustomModuleManager and CommunityModuleManager
pure functions: URL validation, normalization, search, featured, categories
* fix: preserve installed community/custom modules in modify flow
When a user does "Modify Installation" and declines to browse community
modules, previously installed community/custom modules are now auto-kept.
If the user does browse, their selections are trusted (they can deselect).
Also fix stale docs: class doc for SHA pinning, JSDoc return type.
* fix: include community and custom modules in quick update
Quick update now checks community registry and custom cache so installed
community/custom modules are updated instead of skipped.
* fix: use defaults for new config fields during quick update
When quick update encounters new config fields (e.g., from a newly
supported community module), use schema defaults silently instead of
prompting the user. Quick update should be non-interactive.
* test: add unit tests for SHA pinning, category filtering, and URL edge cases
Cover SHA normalization (set vs null/trusted), listByCategory,
getModuleByCode, and URL validation edge cases (HTTP, trailing slash,
SSH without .git). Total: 243 tests.
* refactor(installer): remove custom content installation feature
Remove the entire local filesystem custom content feature from the
installer to make way for marketplace-based plugin installation.
Deleted: custom-handler.js, custom-module-cache.js, custom-modules.js
Removed: --custom-content CLI flag, interactive custom content prompts,
custom module caching, manifest tracking, missing-source resolution,
and related test suites. Updated docs across all translations.
* fix: address review findings from Augment
Fix admonition syntax (remove accidental space in :::note) across 4
translated docs files, and update stale JSDoc on listAvailable().
* chore(install): stop copying skill prompts to _bmad by default
Flip install_to_bmad default from true to false so skill directories
are cleaned from _bmad/ after IDE install. Skills are self-contained
in their IDE directories (.claude/skills/, etc.) and no longer need
duplicate copies in _bmad/.
Two skills (bmad-create-prd, bmad-validate-prd) opt back in via
explicit manifests because bmad-edit-prd cross-references their data
files. Also fixes broken bmm-skills/ path references and corrects
the file-ref validator module-to-source mapping.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(install): make edit-prd self-contained and remove install_to_bmad
Give bmad-edit-prd its own copy of prd-purpose.md and replace the
cross-skill validation workflow reference with a skill invocation, so
all three PRD skills are fully self-contained. With no remaining
consumers, remove the install_to_bmad flag from manifests, CSV output,
the post-install cleanup loop, and the dedicated test file.
* feat(install): clean up skill directories from _bmad after IDE install
Skills are self-contained in IDE directories, so _bmad/ only needs
module-level files (config.yaml, _config/). After all IDE setups
complete, remove skill directories from _bmad/ via skill-manifest.csv.
Also cleans up skill dirs left by older installer versions.
* test(install): drop stale install_to_bmad column from suite 27 CSV row
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(installer): overhaul branding, versioning, and skill cleanup
Logo and branding:
- Responsive logo: full "BMAD METHOD" at >=95 cols, "BMAD" for narrower terminals
- Color scheme updated from yellow to blue (matching bmadcode.com brand)
- Added copyright notice and tagline in white for contrast
- Removed version number from logo (individual module versions shown in summary)
- Added ™ to both wide and narrow logo variants
Installer start message:
- Replaced outdated V6 launch announcement with clean welcome
- Consolidated redundant module/platform messaging into single intro
- Tightened open source manifesto (same spirit, fewer words)
- Merged speaking/media into support section with contact email
- Added full social links: Website, Discord, YouTube, X, Facebook
- Replaced docs.bmad-method.org and changelog links with bmadcode.com hub
Install summary improvements:
- Module names now show full display names from module.yaml (not abbreviations)
- All module versions sourced from .claude-plugin/marketplace.json exclusively
- Summary shows version transitions: "v6.2.2 -> v6.3.0", "v6.3.0, no change",
or "v6.3.0, installed" for fresh installs
- Switched summary from clack note() to box() for full-brightness text
- Removed dim/gray styling that was hard to read on dark terminals
- Links styled with color.blue instead of color.dim
- Get started section leads with actionable steps (launch agent, run bmad-help)
- Removed redundant social links (already shown in start message)
Version source unification:
- All module versions now come from .claude-plugin/marketplace.json only
- Removed package.json as version source for core/bmm modules
- Updated manifest.js getModuleVersionInfo() to use marketplace.json
- Updated installer.js _getMarketplaceVersion() helper
- Updated ui.js getMarketplaceVersion() for module selection display
- Quick Update menu no longer shows misleading version (was using package.json)
- Module selection list now shows versions next to each module name
Skill cleanup overhaul:
- Replaced blunt-force bmad-* prefix deletion with surgical removal system
- Added removals.txt support: optional per-project file listing skills to remove
- Created initial removals.txt with all skills removed since v6.2.0
- Install/update: captures previously installed skill IDs from skill-manifest.csv
before manifest regeneration, then removes those + removals.txt entries
- Uninstall: removes all installed skills via skill-manifest.csv + removals.txt
- Deselecting modules now correctly removes their skills from IDE directories
- User-created bmad-* skills in IDE directories are no longer destroyed
- Legacy directory cleanup retains prefix matching (those dirs are abandoned)
Bug fixes:
- Fixed duplicate "CORE module already up to date" during quick update
- Fixed version display showing package.json version instead of actual module version
- Updated test fixture for bmad-os-* preservation test to use skill-manifest.csv
* fix(installer): address Augment review findings
- Fix plugins[0] fragility: extract highest version across all plugins
in marketplace.json instead of assuming first entry (ui.js, installer.js,
manifest.js)
- Fix _readMarketplaceVersion ignoring moduleSourcePath: custom modules
can now source their own marketplace.json by walking up from source path
- Hard-exclude bmad-os-* utility skills in both surgical and legacy cleanup
modes, preventing accidental deletion if tracked in manifests
- Distinguish missing file vs parse error in skill-manifest.csv reading:
warn on corrupt CSV instead of silently skipping cleanup
* fix(installer): resolve module source before reading marketplace version
Move _readMarketplaceVersion call after source type resolution so custom
modules use their own source path instead of falling back to the external
module cache, which could match a different module with the same code.
* fix: preserve local custom module sources during quick update
Keep customModules in the generated main manifest so local custom
module source paths survive update runs. Load those preserved source
paths during stock quick update before falling back to the custom
cache directory.
This fixes the case where BMAD would drop customModules, lose the
original source path for a local module, and then skip the module or
try to re-cache from _bmad/_config/custom/<module>, which could fail
with ENOENT after the cache directory was removed.
Also adds an installation component regression test to verify
customModules and sourcePath are preserved in manifest generation.
Fixes#1582
* fix: ensure consistent formatting
* refactor: extract quick update custom source assembly
Move quick-update custom module source collection out of Installer and into
CustomModules as assembleQuickUpdateSources(). This keeps discoverPaths() focused on consuming prepared install inputs while
making the quick-update source assembly step explicit and easier to evolve.
Also:
- preserve customModules metadata in manifest regeneration for installed modules
- drop stale customModules entries when modules are no longer installed
- cover manifest preservation and manifest-backed quick-update sources in tests
Kilo Code now supports Agent Skills. Remove the suspended flag,
restore it in the IDE picker, and replace the suspended test suite
with a full native-skills installation test.
- Remove suspended message from platform-codes.yaml
- Rewrite test suite 22: config, IDE picker, install, skill output,
legacy cleanup, and reinstall assertions
- Update migration checklist to reflect active status
Co-authored-by: Junie <junie@jetbrains.com>
Co-authored-by: Brian <bmadcode@gmail.com>
The ancestor directory walk was based on the false premise that IDEs
like Claude Code inherit skills from parent directories — they do not.
The check blocked legitimate installations when unrelated BMAD skills
existed anywhere up the directory tree.
* refactor(installer): restructure installer with clean separation of concerns
Move tools/cli/ to tools/installer/ with major structural cleanup:
- InstallPaths async factory for path resolution and directory creation
- Config value object (frozen) replaces mutable config bag
- ExistingInstall value object replaces stateful Detector class
- OfficialModules + CustomModules + ExternalModuleManager replace monolithic ModuleManager
- install() is prompt-free; all user interaction in ui.js
- Update state returned explicitly instead of mutating customConfig
- Delete dead code: dependency-resolver, _base-ide, IdeConfigManager,
platform-codes helpers, npx wrapper, xml-utils
- Flatten directory structure: custom/handler → custom-handler,
tools/cli/ → tools/installer/, lib/ directories removed
- Update all path references in package.json, tests, CI, and docs
* fix(installer): guard ExistingInstall.version and surface module.yaml errors
Guard ExistingInstall.version access with .installed check in
uninstall.js, ui.js, and installer.js to prevent throwing on
empty/partial _bmad dirs. Surface invalid module.yaml parse errors
as warnings instead of silently returning empty results.
Two bugs combined to produce an empty agent-manifest.csv:
1. collectAgents() only scanned {module}/agents/ directories, but agents
live at various paths (bmm/1-analysis/bmad-agent-analyst/,
cis/skills/bmad-cis-agent-*, etc.). Now walks the full module tree.
2. All 9 BMM agent manifests declared type: skill instead of type: agent.
The manifest generator requires type: agent to include a directory in
agent-manifest.csv. CIS, GDS, TEA, and WDS already had the correct type.
Changes:
- Fix 9 BMM bmad-skill-manifest.yaml files: type: skill → type: agent
- Replace collectAgents/getAgentsFromDir with full-tree recursive scan
- Module field from manifest file always takes precedence over directory
- Remove dead skillManifest load (legacy .md agent support removed)
- Add TODO in bmad-artifacts.js documenting legacy agent pipeline as dead code
- Add 10 regression tests covering BMM, CIS, and GDS directory layouts
* refactor(installer): discover skills by SKILL.md instead of manifest YAML
Switch skill discovery gate from requiring bmad-skill-manifest.yaml with
type: skill to detecting any directory with a valid SKILL.md (frontmatter
name + description, name matches directory name). Delete 34 stub manifests
that carried no data beyond type: skill. Agent manifests (9) are retained
for persona metadata consumed by agent-manifest.csv.
* refactor(installer): remove dead task/tool/workflow manifest code
The remove-skill-manifest-yaml branch deleted the scanners that
discover tasks, tools, and workflows but left behind the code that
writes their manifest CSVs. Remove collectTasks/Tools/Workflows,
writeTaskManifest/ToolManifest/WorkflowManifest, their helpers, and
the now-unreachable getPreservedCsvRows/upgradeRowToSchema methods.
Update installer pre-registration and test assertions accordingly.
Switch skill discovery gate from requiring bmad-skill-manifest.yaml with
type: skill to detecting any directory with a valid SKILL.md (frontmatter
name + description, name matches directory name). Delete 34 stub manifests
that carried no data beyond type: skill. Agent manifests (9) are retained
for persona metadata consumed by agent-manifest.csv.
* refactor(installer): remove dead agent compilation pipeline
Delete 9 files (~2,600 lines) that compiled .agent.yaml to .md.
No .agent.yaml files exist in the source tree — agents now ship
as pre-built SKILL.md. Clean up all references in installer,
module manager, custom handler, base IDE, UI, and tests.
* refactor(custom-handler): remove dead install/copy/find methods
CustomHandler.install(), copyDirectory(), and findFilesRecursively()
are never called — custom modules are installed via moduleManager.install()
since Dec 2025. Also removes unused FileOps import and constructor.
Verified with before/after clean-installer comparison (codex + custom
modules with custom.yaml): output is identical.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(installer): remove dead compilation refs from docs and module manager
Address review findings from PR #2080 triage:
- Remove compile-agents from CLI action docs (en, fr, zh-cn)
- Remove dead vendorCrossModuleWorkflows() and .agent.yaml skip logic
- Clean stale compilation-era comments in manifest-generator
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor(installer): remove legacy workflow, task, and agent IDE generators
All platforms now use skill_format exclusively. The old
WorkflowCommandGenerator, TaskToolCommandGenerator, and
AgentCommandGenerator code paths in _config-driven.js were
no-ops — collectSkills claims every directory before the
legacy collectors run, making their manifests empty.
Removed:
- workflow-command-generator.js (deleted)
- task-tool-command-generator.js (deleted)
- writeAgentArtifacts, writeWorkflowArtifacts, writeTaskToolArtifacts
- AgentCommandGenerator import from _config-driven.js
- Legacy artifact_types/agents/workflows/tasks result fields
Simplified installToTarget, installToMultipleTargets, printSummary,
and IDE manager detail builder to skills-only.
Updated test fixture to use SKILL.md format instead of old agent format.
* fix(installer): address PR review findings from #2078
- Fix temp dir leak in test fixture cleanup (use path.dirname)
- Fail loudly when skill_format missing instead of silent success
- Add workflow.md to test fixture for verbatim-copy coverage
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
The *.agent.yaml format was replaced by SKILL.md-based agents.
Zero agent YAML files remain in src/, so remove the Zod schema,
validator CLI, fixture-based test suite (52 fixtures), unit tests,
CLI integration tests, and the CI steps that invoked them.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(agents): convert all BMM agents to conformant skill structure
Replace legacy XML-based .agent.yaml files with new SKILL.md + bmad-manifest.json
format for all 9 BMM agents (analyst, architect, dev, pm, qa, sm,
quick-flow-solo-dev, ux-designer, tech-writer). Each agent now has:
- SKILL.md with persona, activation flow (bmad-init, project context, dynamic menu)
- bmad-manifest.json with capabilities referencing external skills
- bmad-skill-manifest.yaml for party-mode agent-manifest.csv generation
Tech-writer includes internal prompt files for write-document, mermaid-gen,
validate-doc, and explain-concept capabilities.
Also includes core bmad-init skill and removes legacy agent compilation tests
that referenced the old .agent.yaml format.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(installer): support new SKILL.md agent format in manifest generation
Update getAgentsFromDir to detect directories with bmad-skill-manifest.yaml
where type=agent and extract metadata directly from the YAML fields. This
allows the agent-manifest.csv to be populated from both old-format compiled
.md agents (XML parsing) and new-format SKILL.md agents (YAML manifest).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(installer): install type:agent skills to IDE native skills directory
The collectSkills scanner only recognized type:skill manifests, causing
new-format agents (type:agent in bmad-skill-manifest.yaml) to be added
to agent-manifest.csv but not installed to .claude/skills/. Now both
type:skill and type:agent are recognized as installable skills, while
collectAgents still processes type:agent dirs for the agent manifest
even when claimed by the skill scanner.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(installer): suppress canonicalId warning for type:agent skills
Agent-type skill manifests legitimately use canonicalId for agent-manifest
mapping (e.g., bmad-analyst). Only warn for regular type:skill manifests.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(skills): update analyst manifest and simplify bmad-init instructions
Switch analyst's create-brief menu entry to the new product-brief-preview
skill. Simplify bmad-init SKILL.md by removing hardcoded code fences and
making the script path relative to the skill directory.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(bmm): update tech-writer CSV refs to new skill path
The module-help.csv still referenced the old agent YAML path for
tech-writer entries. Update to skill:bmad-agent-tech-writer to match
the conformant skill structure.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Ona (ona.com) to the BMAD installer so users can select it during
`npx bmad-method install` or via `--tools ona`. Skills are installed to
`.ona/skills/<name>/SKILL.md` using the default templates.
Fixes#1967
Co-authored-by: Ona <no-reply@ona.com>
Subtract agents from total skill directories so the summary shows
non-agent skills and agents as distinct counts (e.g. 34 skills, 10
agents) instead of double-counting agents in the skill total.
* fix(installer): simplify install summary
* style: fix prettier formatting in test file
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(installer): clean up temp dir leak and conditional IDE footer
- Return fixture root from createSkillCollisionFixture so cleanup
removes the parent temp directory, not just the _bmad child
- Only show bmad-help next-step line when IDEs are configured
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
- Rename party-mode → bmad-party-mode (canonical ID convention)
- Change bmad-skill-manifest.yaml from type:workflow to type:skill
- Add SKILL.md with frontmatter for installer discovery
- Remove installed_path, use relative ./steps/ refs internally
- Update module-help.csv to skill:bmad-party-mode
- Update compiler.js hardcoded PM menu path
- Update 43 cross-references to IDE-agnostic _bmad/ path
- Update test fixtures for renamed directory
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* refactor(skills): add SKILL.md entrypoint to skill directories
Align skill source format with Open Skills standard: each skill
directory now contains a SKILL.md with name/description frontmatter
where name must match the directory name exactly. The installer
copies skill directories verbatim instead of generating SKILL.md.
- Add SKILL.md to both tracer bullet skill directories
- Strip name/description from workflow.md frontmatter (SKILL.md owns it)
- Installer reads metadata from SKILL.md, validates name matches dirname
- Install path in manifest CSV now points to SKILL.md
- Copy filter excludes OS/editor artifacts (.DS_Store, backups, dotfiles)
- Debug-guard validation messages, keep name-mismatch as hard error
- Add typeof guard for malformed YAML frontmatter
- Add negative test cases for parseSkillMd validation (Suite 30)
* fix(skills): improve quick-dev-new-preview description for LLM discovery
Add trigger context so LLMs know when to invoke the skill,
matching the "Use when..." pattern used by other skills.
* fix(cli): validate frontmatter name/description are strings in parseSkillMd
Prevents cleanForCSV() crash when YAML parses name or description as
a non-string type (number, object, boolean).
* fix(cli): address PR review findings (mkdtemp, regex escape, recursive filter)
- Replace Date.now() temp dir with fs.mkdtemp() in Suite 30 tests (F5)
- Replace unescaped RegExp with startsWith/slice for path prefix stripping (F7)
- Apply artifact filter recursively via fs.copy filter option (F8)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* refactor(augment): remove legacy YAML/XML workflow rules from code review guidelines
All workflows have been converted to markdown. Remove workflow.yaml,
workflow.xml, and config_source references from Augment review rules.
Drop the entire xml_workflows section (5 rules) and the YAML-specific
standard_workflow_instructions rule.
* refactor: extract discover_inputs protocol from workflow.xml into co-located markdown
Convert the discover_inputs XML protocol (FULL_LOAD, SELECTIVE_LOAD,
INDEX_GUIDED strategies) into standalone markdown files placed alongside
the two workflows that use it (create-story, code-review). Replace
<invoke-protocol> tags with explicit file references. This decouples
the workflows from workflow.xml, enabling its deletion in a follow-up.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: delete dead YAML/XML workflow engine files
Remove 5 files made obsolete by the workflow.yaml → workflow.md migration:
- workflow.xml (the YAML workflow interpreter engine)
- dev-story/instructions.xml (superseded by workflow.md)
- 3 installer templates for YAML workflow command generation
References in CLI code will be cleaned up in follow-up commits.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: delete obsolete workflow handler fragments
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: remove YAML workflow code paths from CLI installer pipeline
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: remove workflow.xml references from manifests and checklists
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: remove workflow.xml references from English command docs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: update fixtures to remove workflow.yaml references
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: update workflow.yaml example path to workflow.md in handler-multi
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: stop tracking workflow/validate-workflow as handler attributes
These handler fragments were deleted — the exec handler already covers
loading .md workflow files directly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: rename workflow attribute to exec in agent menu items
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: address PR review findings from triage
- Fix regex capture group index in module manager workflow path parsing
- Remove stale workflow handler references from handler-multi.txt
- Replace workflow with multi in activation-steps dispatch contract
- Remove dead validate-workflow emission from compiler and xml-builder
- Align commands.md wording to remove engine references
- Fix relativePath anchoring in _base-ide.js recursive directory scans
- Remove dead code from workflow-command-generator (unused template,
generateCommandContent, writeColonArtifacts, writeDashArtifacts)
- Delete unused workflow-commander.md template
- Add regression test for workflow path regex
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(manifest): unified skill scanner decoupled from legacy collectors
Add collectSkills() that recursively walks module trees to discover
type:skill directories anywhere, replacing the band-aid detection
inside collectWorkflows(). Legacy collectors now skip claimed dirs.
scanInstalledModules recognizes skill-only modules.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(manifest): address PR review findings from triage
- Add missing skillClaimedDirs guard to getAgentsFromDir (F1)
- Add skills to this.files[] in collectSkills (F2)
- Add test for type:skill inside workflows/ dir (F5)
- Warn on malformed workflow.md parse in skill dirs (F6)
- Add skills count to generateManifests return value (F9)
- Remove redundant \r? from regex after line normalization (F10)
- Normalize path.relative to forward slashes for cross-platform (F12)
- Enforce directory name as skill canonicalId, warn if manifest overrides (F13)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(tasks): convert review-adversarial-general from XML task to native skill
Convert the simplest core task (review-adversarial-general.xml) from
type:task XML format to type:skill markdown format. This establishes
the pattern for converting remaining XML tasks to self-contained skills.
- Convert XML task to workflow.md with frontmatter, role, execution steps
- Add type:skill manifest for verbatim directory copying
- Extend manifest-generator getTasksFromDir to recurse into subdirectories
and detect type:skill entries (mirrors existing workflow skill detection)
- Update cross-references in quick-dev-new-preview, quick-dev, quick-spec
- Update module-help.csv to use skill: prefix
* refactor: replace file path references with skill name invocations
Consumers of review-adversarial-general now invoke by skill name
instead of loading via _bmad/ file path. Removes the indirection
variable from frontmatter and inlines the skill name directly.
* refactor(installer): scan tasks/ for type:skill entries
Teach collectWorkflows to also scan the tasks/ subdirectory for
type:skill entries. Skills can live anywhere in the source tree —
the workflow scanner just needs to look in more places.
* fix: update stale task terminology to skill after format conversion
Address review findings from PR #1857: replace remaining "task"
references with "skill" in workflow steps and test documentation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(skills): add type:skill manifest for verbatim skill directory copying
Introduce `type: skill` in bmad-skill-manifest.yaml to signal the
installer to copy entire skill directories verbatim into IDE skill
directories, replacing the launcher-based approach.
Changes:
- skill-manifest.js: fix single-entry detection for type-only manifests,
add getArtifactType export
- manifest-generator.js: collect type:skill entries separately, write
skill-manifest.csv, derive canonicalId from directory name
- _config-driven.js: add installVerbatimSkills with YAML-safe SKILL.md
generation, stale file cleanup, and warning on parse failures
- Rename quick-dev-new-preview to bmad-quick-dev-new-preview so
directory name is the canonical ID
- Update workflow.md installed_path to reference IDE skill base directory
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor: replace {installed_path} with relative paths in quick-dev skill
Skills resolve paths relative to the skill root directory per the
open agent standard, so the installed_path variable is unnecessary.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* 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:<canonicalId> 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 <noreply@anthropic.com>
* test: add install_to_bmad design contract tests
Unit tests against getInstallToBmad and loadSkillManifest that nail
down the 4 core design decisions for the install_to_bmad flag.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: reset skills array between runs and allow skill-only targets
- Reset this.skills and this.files in ManifestGenerator to prevent stale
data when instance is reused across multiple manifest runs
- Allow targets with empty artifact_types to still install verbatim
skills by checking skill_format before short-circuiting
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: resolve broken file references in quick-dev-new-preview workflow
- Fix step-02-plan.md templateFile path (./tech-spec-template.md → ../tech-spec-template.md)
- Teach validate-file-refs.js to skip skill: prefixed references in CSV
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add pi coding agent as supported platform
Add pi (provider-agnostic terminal-native AI coding agent) to
platform-codes.yaml with native skills format output to .pi/skills/.
Pi follows the open Agent Skills specification and uses the same
subdirectory/SKILL.md structure that BMAD already generates for
other platforms.
Fixes#1853
* fix: address PR review comments for Pi test suite
- Assert template_type === 'default' to pin config contract
- Verify Pi appears in getAvailableIdes() list
- Test detect() returns false before install, true after
- Parse frontmatter between --- delimiters instead of regex on full file
- Assert description is present and non-empty
- Assert frontmatter contains only name and description keys
- Validate body content is non-empty with expected activation instructions
- Add reinstall/upgrade coverage (rerun setup over existing output)
- Move temp directory cleanup to finally block
* feat(skills): migrate Roo Code installer to native skills format
Move Roo Code from legacy `.roo/commands/` flat files to native
`.roo/skills/{skill-name}/SKILL.md` directory output. Verified
skill discovery in Roo Code v3.51 with 43 skills installed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test(skills): add native skills tests for Claude Code, Codex, and Cursor
Add dedicated test suites covering config validation, fresh install,
legacy cleanup, and ancestor conflict detection for Claude Code, Codex
CLI, and Cursor. Updates migration checklist to reflect verified status.
84 assertions now pass (up from 50).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test(skills): add Roo Code reinstall/upgrade test
Verify that running Roo setup over existing skills output succeeds
and preserves SKILL.md output. Checks off the last Roo checklist item.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(skills): migrate GitHub Copilot to config-driven native skills
Replace 699-line custom installer with config-driven skill_format.
Output moves from .github/agents/ + .github/prompts/ to
.github/skills/{skill-name}/SKILL.md. Legacy cleanup strips BMAD
markers from copilot-instructions.md and removes old directories.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: update migration checklist with Copilot and Roo verified results
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(skills): migrate Cline to config-driven native skills
Move Cline installer from .clinerules/workflows to .cline/skills with
SKILL.md directory output. Add legacy cleanup and 9 test assertions.
* feat(skills): migrate CodeBuddy to config-driven native skills
Move CodeBuddy installer from .codebuddy/commands to .codebuddy/skills
with SKILL.md directory output. Add legacy cleanup and 9 test assertions.
* feat(skills): migrate Crush to config-driven native skills
Move Crush installer from .crush/commands to .crush/skills with
SKILL.md directory output. Add legacy cleanup and 9 test assertions.
* feat(skills): migrate Trae to config-driven native skills
Move Trae installer from .trae/rules to .trae/skills with SKILL.md
directory output. Add legacy cleanup and 9 test assertions.
* feat(skills): migrate KiloCoder to config-driven native skills
Replace 269-line custom kilo.js installer with config-driven entry in
platform-codes.yaml targeting .kilocode/skills/ with skill_format: true.
- Add installer config: target_dir, skill_format, template_type, legacy_targets
- Add cleanupKiloModes() to strip BMAD modes from .kilocodemodes on cleanup
- Remove kilo.js from manager.js customFiles and Kilo-specific result handling
- Delete tools/cli/installers/lib/ide/kilo.js
- Add test Suite 22: 11 assertions (config, install, legacy cleanup, modes, reinstall)
- Update migration checklist with verified results
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(skills): migrate Gemini CLI to config-driven native skills
Replace TOML-based .gemini/commands output with native SKILL.md output
in .gemini/skills/. Gemini CLI confirms native skills support per
geminicli.com/docs/cli/skills/.
- Update platform-codes.yaml: target_dir, skill_format, legacy_targets
- Add test Suite 23: 9 assertions (config, install, legacy, reinstall)
- Add Gemini CLI section to migration checklist
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(skills): migrate iFlow, QwenCoder, and Rovo Dev to native skills
Complete the native skills migration for all remaining platforms:
- iFlow: .iflow/commands → .iflow/skills (config change)
- QwenCoder: .qwen/commands → .qwen/skills (config change)
- Rovo Dev: replace 257-line custom rovodev.js with config-driven
.rovodev/skills, add cleanupRovoDevPrompts() for prompts.yml cleanup
All platforms now use config-driven native skills. No custom installer
files remain. Manager.js customFiles array is now empty.
- Add test suites 24-26: 20 new assertions (173 total)
- Update migration checklist: all summary gates passed
- Delete tools/cli/installers/lib/ide/rovodev.js
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(installer): preserve bmad-os-* skills during cleanup
The cleanupTarget method removed all entries starting with "bmad" from
IDE skills directories, which would also wipe version-controlled
bmad-os-* skills from the BMAD-METHOD repo. Add exclusion for the
bmad-os- prefix so those skills survive reinstalls.
* docs: flag all unverified platforms for manual IDE testing
Add NEEDS MANUAL IDE VERIFICATION to KiloCoder, Gemini CLI, iFlow,
QwenCoder, and Rovo Dev checklists. CodeBuddy, Crush, and Trae already
had the flag.
* fix(installer): suspend Kilo Code and add verified Gemini/Crush results
Kilo Code does not support the Agent Skills standard — the migration
from modes+workflows to skills was based on a false fork assumption.
- Add suspended field to platform-codes.yaml, hiding Kilo from the IDE
picker and blocking setup with a clear message
- Fail the installer early (before writing _bmad/) if all selected IDEs
are suspended, protecting existing installations from being corrupted
- Still clean up legacy Kilo artifacts (.kilocodemodes, .kilocode/workflows)
when users switch to a different IDE
- Mark Crush and Gemini CLI as manually verified (both work end-to-end)
- Replace Suite 22 install tests with suspended-behavior tests (7 assertions)
* docs: update KiloCoder checklist to reflect suspended status
* fix(skills): add canonicalIds for BMM research and PRD workflows
Drop the bmm module prefix from 6 workflow skill names so they
install as bmad-create-prd, bmad-domain-research, etc. instead of
bmad-bmm-create-prd, bmad-bmm-domain-research, etc.
* fix(installer): address PR review findings from automated reviewers
Triage of 18 findings from Augment and CodeRabbit reviews on PR #1841:
Source code fixes:
- Exclude bmad-os-* from findAncestorConflict to match cleanupTarget
- Wrap cleanupCopilotInstructions in try/catch (best-effort, not fatal)
- Wrap suspended-platform cleanup in try/catch (failure boundary)
- Clean up temp backup dirs in catch block when install aborts
- Normalize IDE keys to lowercase before suspended lookup
- Delete dead loadCustomInstallerFiles method and stale references
- Rename "Roo Cline" to "Roo Code" in both platform-codes.yaml files
- Fix Gemini CLI package name (@google/gemini-cli, not @anthropic-ai)
Test improvements:
- Add name/frontmatter invariant check to 6 missing platform suites
- Assert stale bmad-architect skill is removed after cleanup
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat(skills): add canonical bmad- naming via skill manifests
Add bmad-skill-manifest.yaml sidecars to all 38 capabilities (tasks,
agents, workflows) declaring canonicalId as the single source of truth
for skill names. Update Claude Code and Codex installers to prefer
canonicalId over path-derived names, with graceful fallback.
- 24 manifest files covering 38 capabilities
- New shared skill-manifest.js utility for manifest loading
- resolveSkillName() in path-utils.js bridges manifest → installer
- All command generators propagate canonicalId through CSV manifests
- Drops bmm module prefix from all user-facing skill names
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat(skills): claude-code installer outputs .claude/skills/<name>/SKILL.md
Refactor the config-driven installer to emit Agent Skills Open Standard
format for Claude Code: directory-per-skill with SKILL.md entrypoint,
unquoted YAML frontmatter, and full canonical names.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* refactor(installer): migrate codex to config-driven pipeline
Delete the custom codex.js installer (441 lines) and route Codex
through the config-driven pipeline via platform-codes.yaml. This
fixes 7 task/tool descriptions that were generic due to bypassing
manifests, and eliminates duplicate transformToSkillFormat code.
Key changes:
- Add codex entry to platform-codes.yaml with skill_format + legacy_targets
- Remove codex from custom installer list in manager.js
- Add installCustomAgentLauncher() to config-driven for custom agent support
- Add detect() override for skill_format platforms (bmad-prefix check)
- Set configDir from target_dir for base-class detect() compatibility
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(installer): guard codex skill installs in nested directories
* fix(installer): warn on stale global legacy skill dirs
* feat(installer): migrate cursor to native skills
* Migrate Windsurf installer to native skills
* Clarify Windsurf skill invocation in checklist
* feat(installer): migrate kiro to native skills
* docs: record kiro skill visibility verification
* Migrate Antigravity installer to native skills
* Document Antigravity ancestor skill verification
* Synchronize native skills migration checklist
* Migrate Auggie installer to native skills
* Migrate OpenCode installer to native skills
* Document live skill verification for Auggie and OpenCode
* fix(test): replace _bmad filesystem dependency with self-contained fixture
The installation component tests walked up the filesystem looking for a
pre-installed _bmad directory, which exists locally but not in CI. Replace
findInstalledBmadDir() with createTestBmadFixture() that creates a minimal
temp directory with fake compiled agents, making tests fully self-contained.
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Brian <bmadcode@gmail.com>
* fix(workflows): remove ambiguous with-argument from help task chaining
The "with argument" clause in 7 workflow completion steps caused LLMs
to interpret "Read fully and follow: help.md with argument X" as a
skill/function invocation rather than a file-read instruction. Drop the
clause entirely — help.md already infers the completed workflow from
the preceding "[Workflow] complete." text in conversation context.
Closes#1637
* fix(workflows): correct broken qa/automate file references
The QA workflow was renamed to qa-generate-e2e-tests but three files
still referenced the old qa/automate path, breaking CI file-ref
validation.
* fix(test): update QA agent test to match renamed workflow path
The workflow path changed from qa/automate to qa-generate-e2e-tests
but the installation component test was not updated to match.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Brian <bmadcode@gmail.com>
* fix(docs): comprehensive documentation site review fixes
Rehype plugins:
- Rewrite rehype-markdown-links for correct relative .md resolution
- Handle raw HTML base paths and bare .md links in rehype-base-paths
- Guard protocol-relative URLs (//...) in all link processors
- Use file.path instead of file.history[0] for vfile compatibility
- Fail build when content directory cannot be detected
- Export helpers for testability; add 107 unit tests
Build & CI:
- Revert cancel-in-progress to false to avoid mid-deploy cancellation
- Remove redundant link-validation CI step (build validates internally)
- Remove unnecessary fetch-depth:0 from docs deploy workflow
- Refuse docs build on Windows (platform guard)
- Remove dead build scripts and stale references
Tooling:
- Add DOCS_ROOT boundary check in validate-doc-links.js
- Handle directory paths and prefix stripping in link validator
- Remove dead regex and add // guard in fix-doc-links.js
Accessibility & CSS:
- Darken caution/danger aside title colors for WCAG AA 4.5:1 contrast
- Fix 100vw scrollbar overflow (banner width:100%, html overflow-x:clip)
- Add :focus-visible ring to banner link for keyboard navigation
- Remove dead CSS declaration and add missing code block lang
Documentation content:
- Convert /docs/ absolute links to relative paths and fix llms.txt URLs
- Correct command file paths and naming in commands reference
- Update stale shard-doc command to current /bmad-shard-doc format
- Fix incomplete sentence in install-bmad.md
- Add Quick Flow next steps and fix 404 link path
- Expand thin content pages with substantive detail
- Add sidebar ordering frontmatter to all content pages
- Remove BMGD docs (moved to dedicated repo)
- Remove unused assets and misleading diagram caption
- Add non-iframe fallback link to workflow map diagram
- Remove dead noscript block from workflow-map
- Standardize BMAD to BMad, fix spelling/grammar, normalize headings
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(docs): add non-interactive installation to sidebar, rewrite and reorder how-to guides
- Move non-interactive-installation.md into how-to/ directory so it appears
in the sidebar navigation (was orphaned at docs root)
- Rewrite the page based on editorial review: consolidate redundant sections,
add missing how-to structure (prerequisites, "What You Get"), condense
installation modes from 5 subsections to a table, cut speculative examples
- Reorder how-to sidebar: Install (1), Non-Interactive (2), Upgrade to v6 (3),
then the rest following user journey order
- Fix README link to point to docs site instead of repo-internal markdown path
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(docs): address documentation review findings
Fix broken directory tree, grammar errors, inconsistent naming,
missing admonition/headings, enable lastUpdated timestamps in CI,
and remove footer CSS that misapplied to the content footer.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(docs): move bleeding-edge install command out of Verify Installation
The alternative npx command for installing from main was misplaced
inside the "Verify Installation" section. Move it to a tip admonition
under Step 1 where users look for install options.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: extend validate-file-refs.js to scan CSV workflow-file references
Add CSV file reference extraction to the Layer 1 validation pipeline,
preventing broken _bmad/ workflow-file paths in module-help.csv files.
Closes the gap identified after PR #1529 where CSV references were
unvalidated despite being a source of repeat community issues.
Refs: #1519
* fix: include test:refs in aggregate test script
Add CSV file-ref extraction tests to the aggregate `npm test` pipeline,
matching the existing pattern for test:schemas and test:install.
Thanks to CodeRabbit for catching the omission.
* fix: address review feedback on CSV validator extension
- Surface CSV parse errors visibly instead of silently swallowing
(no Layer 2c schema validator exists yet to catch these)
- Add explanatory comments for the !VERBOSE logging pattern
(non-verbose prints file headers only when issues found)
- Add verbose-mode diagnostics for extensionless path handling
([SKIP] when nothing exists, [OK-DIR] for valid directories)
* refactor: collect-then-print to eliminate confusing !VERBOSE pattern
Replace the split header-printing logic (print early in verbose mode,
print late in non-verbose mode with a !VERBOSE guard) with a simpler
collect-then-print approach. Refs are now classified into ok[] and
broken[] arrays first, then printed in a single location with one
straightforward if/else if decision.
Addresses alexeyv's review feedback about the counterintuitive
"if not verbose, log" pattern.
* feat: promote extensionless unresolved paths from silent skip to [UNRESOLVED]
Paths without file extensions that don't exist as files or directories
are now flagged as [UNRESOLVED] — a distinct tag from [BROKEN] (which
means a file with a known extension wasn't found). Both count toward
the broken reference total and appear in CI annotations.
This catches real bugs like wrong directory names in installed_path
metadata and dead invoke-workflow references to removed workflows.
Extensionless paths that DO exist as directories are still [OK-DIR].
---------
Co-authored-by: Alex Verkhovsky <alexey.verkhovsky@gmail.com>
Co-authored-by: Brian <bmadcode@gmail.com>