feat!: distribute BMAD as a flat skills tree via npx skills and plugin marketplaces - #2768
Merged
Conversation
3 tasks
alexeyv
force-pushed
the
feat/npx-skills-distribution
branch
from
August 21, 2026 02:54
69481ae to
9254832
Compare
This was referenced Aug 24, 2026
alexeyv
marked this pull request as ready for review
August 24, 2026 17:14
Contributor
|
Too many files changed for review (434 files, 100 file limit). Bypass the limit by tagging |
Contributor
|
@coderabbitai review |
alexeyv
force-pushed
the
feat/npx-skills-distribution
branch
from
August 28, 2026 15:47
9e77de7 to
63e4d3d
Compare
alexeyv
force-pushed
the
feat/npx-skills-distribution
branch
from
August 30, 2026 22:29
63e4d3d to
518c239
Compare
alexeyv
force-pushed
the
feat/npx-skills-distribution
branch
2 times, most recently
from
September 3, 2026 18:34
9f77c1b to
987bd13
Compare
Walk core+bmm skill sources into a skills/<canonical-id>/ tree and fatten only dest bmad-help with the shared Python, module.yaml defaults, and a baked core+bmm help catalog.
Read top-down from main, drop PackagerError, and stop catching failures so a missing source or payload surfaces as a stack.
Read package steps top-down, assemble bmad-help.csv through the stdlib csv module so quoted descriptions stay intact, and assert bad, empty, or short catalogs fail without touching dest.
Materialize _bmad from dest help: scripts symlink or copy, shipped module.yaml defaults, empty custom/, baked catalog.
First-run setup copies authored team and user templates instead of walking module.yaml, and reads the three user answers from a sidecar so the skill route does not put them on the shell.
Setup is the only place that knows the template filenames; the packager copies help assets as-is.
Invoke setup from {skill-root}/scripts/setup.py so dest scripts
includes the pump and an npx update is seen. Require
resolve_config.py in the payload.
Move the setup interview and pump into references/setup.md so ordinary bmad-help loads do not pay that context.
A second bmad-help setup now fills new team-config and module-yaml keys, replaces the baked catalog, and repairs a wrong or stale scripts path. Existing custom/ and *.user.toml stay untouched.
Document shipped skill relationships, conditional routes, completion criteria, and artifact destinations for independently packaged skills. Refs: sc-1
Add the canonical bmad entrypoint, exclude bmad-help from flattened output, and retain transitional CSV packaging. Move the setup tests, allow the canonical root ID in validation, and normalize the existing install-only custom path for strict reference checks.
Validate module manifests and package versions before replacing output. Copy identical manifests and declared scripts into every owning skill.
Replace catalog-driven ordinary help with fresh host skill discovery and read-only manifest reasoning for partial and conflicting installations.
…oved README section
setup and doctor rewrite _bmad wholesale via replace_dir, so running them through a symlinked _bmad crashed mid-flight with a raw IsADirectoryError from the backup rename. Reads through the symlink are the point of symlinking and stay untouched; only the write paths now fail fast, naming the link target and the --project-root to use against the real installation. The doctor flow rejects in its missing-_bmad pre-flight so --list-config-questions --doctor fails before interrogating the user.
help.md now names https://docs.bmad-method.org/llms.txt as the place to look when it and the installed skills cannot answer a BMad question; the index also names the source repository as the final authority. The hub skill's constraints direct that fetch before conceding a limitation, restoring the remote-docs grounding the CSV-era bmad-help had via its _meta row.
parse_packaged_manifest required `knowledge` to equal one hardcoded literal naming the bmad skill's own help document, so no second module could ship a manifest that parses. The value is then discarded — it is not a field on ParsedManifest and nothing reads it — so the check bought nothing. The cost was disproportionate. discover_installed_copies parses every sibling manifest before doing any work, so one unacceptable value aborted `bmad update`, `setup`, and `doctor` for the whole project, including modules whose own manifests were fine. This is also what the format spec asks for: the packager rejects unknown or malformed keys, while `bmad` ignores what it does not recognize, so a manifest from a newer format cannot break an older hub. stamp_release.py keeps its equality check — it is the packager, and it only ever runs against this repo's manifests. `knowledge` stays required and non-empty. CIS points it at its published llms.txt, the same remote-docs grounding help.md already names for BMM.
The knowledge value named `reference/help.md`, but the bmad skill has no reference/ directory — the file is references/help.md. Nothing ever resolved the value, so the dangling pointer reached 30 manifests and the release stamper's constant unnoticed.
The hub bound every route to references/help.md and was told to treat no manifest key but `module` as routing, so a module shipped from another repository was visible and unroutable. Discovery now reads each sound manifest's free-form `knowledge` text and follows it, for the module the question concerns, to the document it names. help.md stops being privileged: it opens with the discovery model and carries its method/toolbox content as a labelled section — which is simply what those two modules' manifests point at.
setup.py drops build metadata when ordering versions, so 6.12.0+hotfix compares equal to 6.12.0 and a release stamped that way is invisible to every installed copy. The runbook warned against it; the stamper accepted it. Reject it before anything is written. The version rule is now "orderable and distinguishable", one notch stricter than setup.py's orderability - the contract test pins that gap and pins the premise it rests on.
`load_central_config` read `_bmad/config.user.toml` as layer 2 while setup.py listed the same file in LEGACY_LEFTOVERS — debris from the classic installer that doctor reports read-only and never writes. The mechanism that populated it (the removed JS installer's `module.yaml` `scope:` partition) is gone, so nothing creates the file and the resolver read a layer that could only ever be hand-written into a directory documented as installer-owned. Central config is now three layers, matching load_customization: config.toml -> custom/config.toml -> custom/config.user.toml. Tests keep writing config.user.toml and assert a key unique to it never reaches the merge, pinning the removal.
Sixteen skills read `_bmad/bmm/config.yaml` directly — a flattened legacy YAML projection that setup.py writes only for `core` and `bmm`. It coerces every value to a string, lets `[core]` silently win key collisions with `[modules.bmm]`, and is generated once at setup, so the `_bmad/custom/` override layers never reach it. Each now calls resolve_config.py with the exact keys it needs, matching the eight skills that already did. Nothing reads either YAML projection after this; setup.py still writes them. Values stay under `modules.bmm`, which is where config.template.toml writes them, though these skills declare `module = "method"`. Drops the fallbacks with them: the `config.user.yaml` hedge (nothing writes that file), the missing-key defaults, and "never block". The config step always follows a resolve_customization.py call, so a missing scripts directory has already surfaced by then.
Setup resolved config through the script already, but still wrote core/config.yaml and bmm/config.yaml on every run. Nothing reads them. Drop the writes and the code that existed only to build them: the legacy_config projection threaded through materialize_bmad/stage_bmad, without_manifest_answers, delete_path, stringify, and the whole YAML parse/render/fill path. ensure_file now merges TOML only. Existing files are left in place, like the other classic-installer traces, and both paths join LEGACY_LEFTOVERS so doctor reports them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Sn1de7Zc9yWcJnJkE6QNis
Main renamed bmad-checkpoint-preview to bmad-walkthrough; apply the same rename under skills/, repoint the hub help doc, and drop the v6 shim main added since this branch removes the shim tree.
The Python rewrite of the file-ref checker ported the JS pattern verbatim, including the `\\\\` that only matched the escaped `C:\\Users` form. Main fixed the JS copy in #2794 before this branch deleted it; apply the same pattern here so the rebase does not revert the fix.
alexeyv
force-pushed
the
feat/npx-skills-distribution
branch
from
September 5, 2026 07:44
987bd13 to
0258223
Compare
Main has released 6.12.0, so the module manifests and the package version now carry the next placeholder above it.
Checks that ran when a PR was opened against main are stale once the retarget workflow moves it to dev. Trigger on the edited event and skip title and body edits, so a retargeted PR gets fresh checks without the contributor closing and reopening it.
|
Retested on opencode CLI after the flat skills tree landed — working end-to-end. ✅ Environment: opencode 1.18.27 (CLI, non-interactive Verification (marker-injection repro from #2692, adapted to the new layout):
Raw evidenceThanks for the rework — the new distribution model is a big improvement for opencode users. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
BMAD's skills depended on its npm installer to turn nested source files into an
installation. This PR makes the repository itself installable: 29 skills live
under
skills/<canonical-id>/, and thebmadhub handles project setup,update checks, and repair.
Users can install with
npx skills add bmad-code-org/BMAD-METHOD, or use theClaude Code and Codex marketplaces supplied by
bmad-code-org/bmad-plugins.What changes
module-manifest.tomldeclaring its module, version, update source, andknowledge location. The tree contains 21
methodskills and eighttoolboxskills, including thebmadhub. No packaging step is needed forthe Skills CLI.
bmad setupcreates scripts, configuration, and outputdirectories, preserving existing answers and customizations on subsequent
runs.
bmad updatechecks installed versions without installing updates;plugin copies report
plugin-managed.bmad doctorrepairs an existingruntime. Deterministic work runs through Python.
github:bmad-code-org/BMAD-METHOD/skills. GitHub update checks explicitlyread
main. Plugin packaging lives in the separate plugin repository.dev, merge adev→mainPR with a merge commit, tag that merge commit, then stamp the next patch
placeholder on
dev. There are no release branches or back-merges.The stamper synchronizes all manifests,
package.json, and both rootversion fields in
package-lock.json, preserving dependency versions.It rejects invalid SemVer,
-dev, and build metadata.mainanddev, and on PRs to any branch. A metadata-onlypull_request_targetworkflow retargets newly opened PRs from
maintodev, except when thehead branch is
dev. Contributor guidance directs 6.12 npm maintenanceto
V6.12.publishing pipeline, and legacy shim skills. Skill and file-reference
validation and renderer snapshot tests use Python.
CLAUDE.mdimportsAGENTS.md; the site tooling directory isdocs-site/.hub commands. The release runbook replaces the temporary rehearsal process.
Site documentation intentionally continues to describe npm until the first
official release under the new distribution scheme.
All version declarations remain
6.12.0-next; this PR does not cut a release.Validation
npm ci && npm run qualitypasses on committed HEAD in the checkout beingpushed, including formatting, lint, documentation build and link checks,
JavaScript tests, Python tests, and skill/reference validation.
mainURL, package-versionsynchronization, dependency preservation, and no writes on invalid or
missing package metadata.
versioned files byte-for-byte.
npm cireports 11 dependency advisories (two moderate, nine high);dependency remediation is outside this change.
Rollout outside this PR
V6.12fromv6.12.0, adapt its npm publish workflow, and movemaintenance PRs there.
devfrommainand retarget this PR todevbefore merging.Apply the planned protection to
mainand retarget other development PRs.to BMAD-METHOD, rebuild plugins, and verify all three install routes.
Replaces #2736.