16 KiB
| title | description | sidebar | ||
|---|---|---|---|---|
| How to Install BMad | Install, update, and pin BMad for local development, teams, and CI |
|
Use npx bmad-method install to set up BMad in your project. One command handles first installs, upgrades, channel switching, and scripted CI runs. This page covers all of it.
When to Use This
- Starting a new project with BMad
- Adding or removing modules on an existing install
- Switching a module to main-HEAD or pinning to a specific release
- Scripting installs for CI pipelines, Dockerfiles, or enterprise rollouts
:::note[Prerequisites]
- Node.js 20+ (the installer requires it)
- Git (for cloning external modules)
- An AI tool such as Claude Code or Cursor (run
npx bmad-method install --list-toolsto see all supported tools)
:::
First-time install (the fast path)
npx bmad-method install
The interactive flow asks you five things:
- Installation directory (defaults to the current working directory)
- Which modules to install (checkboxes for core, bmm, bmb, cis, gds, tea)
- "Ready to install (all stable)?" — Yes accepts the latest released tag for every external module
- Which AI tools/IDEs to integrate with (claude-code, cursor, and others)
- Per-module config (name, language, output folder)
Accept the defaults and you land on the latest stable release of every module, configured for your chosen tool.
:::tip[Just want the newest prerelease?]
npx bmad-method@next install
Runs the prerelease installer, which ships a newer snapshot of core and bmm. More churn, fewer delays between development and release. :::
Picking a specific version
Two independent axes control what ends up on disk.
Axis 1: external module channels
Every external module — bmb, cis, gds, tea, and any community module — installs on one of three channels:
| Channel | What gets installed | Who picks this |
|---|---|---|
stable (default) |
Highest released semver tag. Prereleases like v2.0.0-alpha.1 are excluded. |
Most users |
next |
Main branch HEAD at install time | Contributors, early adopters |
pinned |
A specific tag you name | Enterprise installs, CI reproducibility |
Channels are per-module. You can run bmb on next while leaving cis on stable — the flags below let you mix freely.
Axis 2: installer binary version
The bmad-method npm package itself has two dist-tags:
| Command | What you get |
|---|---|
npx bmad-method install (@latest) |
Latest stable installer release |
npx bmad-method@next install |
Latest prerelease installer, auto-published on every push to main |
The installer binary determines your core and bmm versions. Those two modules ship bundled inside the installer package rather than being cloned from separate repos.
Why core and bmm don't have their own channel
They're stapled to the installer binary you ran:
npx bmad-method install→ latest stable core and bmmnpx bmad-method@next install→ prerelease core and bmmnode /path/to/local-checkout/tools/installer/bmad-cli.js install→ whatever your local checkout has
--pin bmm=v6.3.0 and --next=bmm are silently ineffective against bundled modules, and the installer warns you when you try. A future release extracts bmm from the installer package; once that ships, bmm gets a proper channel selector like bmb has today.
Updating an existing install
Running npx bmad-method install in a directory that already contains _bmad/ gives you a menu:
| Choice | What it does |
|---|---|
| Quick Update | Re-runs the install with your existing settings. Refreshes files, applies patches and minor stable upgrades, refuses major upgrades. Fast, non-interactive. |
| Modify Install | Full interactive flow. Add or remove modules, reconfigure settings, optionally review and switch channels for existing modules. |
Upgrade prompts
When Modify detects a newer stable tag for a module you've installed on stable, it classifies the diff and prompts accordingly:
| Upgrade type | Example | Default |
|---|---|---|
| Patch | v1.7.0 → v1.7.1 | Y |
| Minor | v1.7.0 → v1.8.0 | Y |
| Major | v1.7.0 → v2.0.0 | N |
Major defaults to N because breaking changes frequently surface as "instability" when they weren't expected. The prompt includes a GitHub release-notes URL so you can read what changed before accepting.
Under --yes, patch and minor upgrades apply automatically. Majors stay frozen — pass --pin <code>=<new-tag> to accept non-interactively.
Switching a module's channel
Interactively: choose Modify → answer Yes to "Review channel assignments?" → each external module offers Keep, Switch to stable, Switch to next, or Pin to a tag.
Via flags: the recipes in the next section cover the common cases.
Headless CI installs
Flag reference
| Flag | Purpose |
|---|---|
--yes, -y |
Skip all prompts; accept flag values + defaults |
--directory <path> |
Install into this directory (default: current working dir) |
--modules <a,b,c> |
Exact module set. Core is auto-added. Not a delta — list everything you want kept. |
--tools <a,b> |
IDE/tool selection. Required for fresh --yes installs. Run --list-tools for valid IDs. |
--list-tools |
Print all supported tool/IDE IDs (with target directories) and exit. |
--action <type> |
install, update, or quick-update. Defaults based on existing install state. |
--custom-source <urls> |
Install custom modules from Git URLs or local paths |
--channel <stable|next> |
Apply to all externals (aliased as --all-stable / --all-next) |
--all-stable |
Alias for --channel=stable |
--all-next |
Alias for --channel=next |
--next=<code> |
Put one module on next. Repeatable. |
--pin <code>=<tag> |
Pin one module to a specific tag. Repeatable. |
--set <module>.<key>=<value> |
Set any module config option non-interactively (preferred — see Module config overrides). Repeatable. |
--list-options [module] |
Print every --set key for built-in and locally-cached official modules, then exit. Pass a module code to scope to one module. |
--user-name, --communication-language, --document-output-language, --output-folder |
Legacy shortcuts equivalent to --set core.<key>=<value> (still supported) |
Precedence when flags overlap: --pin beats --next= beats --channel / --all-* beats the registry default (stable).
:::note[Example resolution]
--all-next --pin cis=v0.2.0 puts bmb, gds, and tea on next while pinning cis to v0.2.0.
:::
Recipes
Default install — latest stable for everything:
npx bmad-method install --yes --modules bmm,bmb,cis --tools claude-code
Enterprise pin — reproducible byte-for-byte:
npx bmad-method install --yes \
--modules bmm,bmb,cis \
--pin bmb=v1.7.0 --pin cis=v0.2.0 \
--tools claude-code
Bleeding edge — externals on main HEAD:
npx bmad-method install --yes --modules bmm,bmb --all-next --tools claude-code
Add a module to an existing install (keep everything else):
npx bmad-method install --yes --action update \
--modules bmm,bmb,gds
--tools is omitted intentionally — --action update reuses the tools configured during the first install.
Mix channels — bmb on next, gds on stable:
npx bmad-method install --yes --action update \
--modules bmm,bmb,cis,gds \
--next=bmb
Module config overrides
--set <module>.<key>=<value> lets you set any module config option non-interactively. It's repeatable and scales to every module — present and future. The flag is applied as a post-install patch: the installer runs its normal flow first, then --set upserts each value into _bmad/config.toml (team scope) or _bmad/config.user.toml (user scope), and into _bmad/<module>/config.yaml so declared values carry forward to the next install.
Example — install bmm with explicit project knowledge and skill level:
npx bmad-method install --yes \
--modules bmm \
--tools claude-code \
--set bmm.project_knowledge=research \
--set bmm.user_skill_level=expert
Discover available keys for a module:
npx bmad-method install --list-options bmm
--list-options (no argument) lists every key the installer can find locally — built-in modules (core, bmm) plus any currently cached official modules. The cache is per-machine and can be cleared, so previously installed officials won't appear on a fresh checkout or an ephemeral CI worker until they're installed again. Community and custom modules aren't enumerated here; read the module's module.yaml directly to see what keys it declares.
How it works:
- Routing. The patch step looks for
[modules.<module>] <key>(or[core] <key>) inconfig.user.tomlfirst; if found there, it updates that file. Otherwise it writes to the team-scopeconfig.toml. So user-scope keys (e.g.core.user_name,bmm.user_skill_level) end up inconfig.user.tomland team-scope keys end up inconfig.toml, matching the partition the installer uses. - Verbatim values. The value is written exactly as you provided it — no
result:template rendering. To get the rendered form (e.g.{project-root}/research), pass it explicitly:--set bmm.project_knowledge='{project-root}/research'. - Carry-forward, declared keys. Values for keys declared in
module.yamlsurvive subsequent installs because they're also written to_bmad/<module>/config.yaml, which the installer reads as the prompt default on the next run. - Carry-forward, undeclared keys. A value for a key the module's schema doesn't declare lands in
config.tomlfor 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--setif you need it sticky, or edit_bmad/config.tomldirectly. - No validation.
single-selectvalues aren't checked against the allowed choices, and unknown keys aren't rejected — whatever you assert is written. - Modules not in
--modules. Setting a value for a module you didn't include prints a warning and the value is dropped (no file gets created for an uninstalled module).
The legacy core shortcuts (--user-name, --output-folder, etc.) still work and remain documented for backward compatibility, but --set core.user_name=... is equivalent.
:::note[Works with quick-update]
--set is a post-install patch, so it applies the same way regardless of action type. Under bmad install --action quick-update (or --yes against an existing install, where quick-update is the default), --set patches the central config files at the end just like a regular install.
:::
:::caution[Rate limit on shared IPs] Anonymous GitHub API calls are capped at 60/hour per IP. A single install hits the API once per external module to resolve the stable tag. Offices behind NAT, CI runner pools, and VPNs can collectively exhaust this.
Set GITHUB_TOKEN=<personal access token> in the environment to raise the limit to 5000/hour per account. Any public-repo-read PAT works; no scopes are required.
:::
What got installed
After any install, _bmad/_config/manifest.yaml records exactly what's on disk:
modules:
- name: bmb
version: v1.7.0 # the tag, or "main" for next
channel: stable # stable | next | pinned
sha: 86033fc9aeae2ca6d52c7cdb675c1f4bf17fc1c1
source: external
repoUrl: https://github.com/bmad-code-org/bmad-builder
The sha field is written for git-backed modules (external, community, and URL-based custom). Bundled modules (core, bmm) and local-path custom modules don't have one — their code travels with the installer binary or your filesystem, not a cloneable ref.
For cross-machine reproducibility, don't rely on rerunning the same --modules command. Stable-channel installs resolve to the highest released tag at install time, so a later rerun lands on whatever has been released since. Convert the recorded tags from manifest.yaml into explicit --pin flags on the target machine, e.g.:
npx bmad-method install --yes --modules bmb,cis \
--pin bmb=v1.7.0 --pin cis=v0.4.2 --tools claude-code
Troubleshooting
"Could not resolve stable tag" or "API rate limit exceeded"
You've hit GitHub's 60/hr anonymous limit. Set GITHUB_TOKEN and retry. If you already have a token set, it may be expired or rate-limited on its own budget — try a different token or wait for the hourly reset.
"Tag 'vX.Y.Z' not found"
The tag you passed to --pin doesn't exist in the module's repo. Check the repo's releases page on GitHub for valid tags.
A pinned install keeps upgrading
Pinned installs don't upgrade. Quick-update applies patches and minors on stable channel only; it won't touch pinned or next. If a pinned install changed, open _bmad/_config/manifest.yaml — channel: pinned plus a fixed version and sha should hold across runs unless you explicitly override via flags.
--pin bmm=X didn't do anything
bmm is a bundled module — --pin and --next= don't apply. Use npx bmad-method@next install for a prerelease core/bmm, or check out the bmad-bmm repo and run the installer locally to get unreleased changes.