Move an installed project to a newer BMAD+ version with a plan, backups and a receipt you can restore from: flags, what is preserved, refusals, recovery and every message.
update takes a project that already has BMAD+ and brings its files to the version of the package you run. It never works blindly: it first computes a plan from the ownership inventory recorded at install, shows how many files change and which ones it will leave alone because you edited them, asks for confirmation, backs everything up, writes, verifies, and leaves a receipt. If anything fails halfway it rolls back, and a finished update can be undone later with --restore.
Confirm without prompting. Required when there is no terminal.
-l, --lang <code>
language code
Language of the confirmation texts. Defaults to the language recorded at install.
--latest
-
Do not use the package you are running: look up the latest compatible release on npm and run exactly that version. Without --yes or --auto it only reports what it would run.
--expected-version <version>
exact version
Refuse unless the running package is exactly this version. Used by the updater itself as a safety check.
--auto
-
Apply only if the project’s update policy allows it, the ownership inventory is complete and nothing is in conflict. Needs --expected-version.
--restore <receipt-id>
receipt id
Put back the files saved by an earlier update. Cannot be combined with --latest, --expected-version or --auto.
Plain update uses the package you are running. npx bmad-plus@0.23.0 update moves the project to 0.23.0. When the installed and running versions are equal, it prints “Nothing to update.” and stops.
update --latest asks npm (update-check does the same lookup) for the newest release of your update channel, checks that it is a newer, eligible, Node-compatible version allowed by your policy, then runs npm exec on exactly that version in a temporary folder with update --yes --expected-version <version>. Without --yes (or --auto) it stops after naming the target: the report is the approval request.
After --latest the manifest is read again. If it does not show the target version, the command fails and asks you to inspect the project.
Agents, skills, data, module files that you did not touch
Replaced by the new version after a backup.
Managed files you edited (modified-managed-file)
Left as they are and listed as a preserved conflict.
A file in the way that BMAD+ never recorded (unowned-file)
Left as it is, listed as a conflict.
Files the new version no longer ships
Removed with a backup when unchanged; kept and listed (modified-orphaned-file) when you edited them. Empty folders are cleaned up.
AGENTS.md and tool files carrying the BMAD+ marker and unchanged
Regenerated.
Instruction files you wrote, or edited after install (local-instructions, repository-adopted)
Left as they are, listed as a conflict.
_bmad/config.yaml, memory, _bmad-output/
Not touched.
Legacy installations without a complete ownership inventory
Original pack files are backed up before replacement, with a warning; older instruction files are saved as <file>.bak. --auto refuses.
A backup of every file the update changes is stored under .bmad/updates/<receipt-id>/backups/, next to receipt.json. The receipt records the status of the update: prepared, committed, rolled-back, recovery-required or restored. Only one install or update can run at a time (.bmad/update.lock).
No update run was recorded in the 0.23.0 acceptance runs, so the two transcripts below are composed from the message templates in the code (version numbers and counts are placeholders) and are marked as simulated.
A plain update with one preserved conflictSimulated
$ npx bmad-plus@<new> updateInstalled: v<old> -> Executing package: v<new>Planned changes: <N> files (<R> no longer shipped, removed with backup); preserved conflicts: 1.CLAUDE.md: preserved (local-instructions).? Apply this update from v<old> to v<new>? Yes<N> files updated; 1 local conflicts preserved.Receipt and backups: <project>/.bmad/updates/<receipt-id>/receipt.jsonBMAD+ v<new> applied partially. Reload your agent instructions or start a new session.
npx bmad-plus@<new> update
Illustrative transcript, not captured from a real run. Source: tools/cli/commands/update.js lines 120-190
Latest release, approval requested then givenSimulated
$ npx bmad-plus update --latestConfirm this exact update with --yes.Target: v<new># Nothing was changed; exit code 0.$ npx bmad-plus update --latest --yesupdated# The updater that this command starts prints its own lines here (the plan, the receipt and the “applied” line, as in the previous transcript); they are omitted.Target: v<new>Reload your agent instructions or start a new session.
Illustrative transcript, not captured from a real run. Source: tools/cli/lib/update-dispatch.js lines 110-180 and tools/cli/commands/update.js lines 62-74
If an update fails after it started writing, it rolls itself back and ends with a line such as ; rolled-back. Recovery: bmad-plus update --restore <id> --directory "<dir>" --yes. The receipt id is also the folder name under .bmad/updates/. --restore checks that every saved file still matches its recorded hash, that the current manifest is the one from before or after that update, and that no live update holds the lock; then it puts the old files back and marks the receipt restored. Nothing is restored if a file changed since the update: the command refuses and names it.
No BMAD+ installation found in <dir> (missing _bmad/.bmad-plus-install.json).
You are in the wrong folder, or BMAD+ is not installed.
Run from the project folder, pass --directory, or install first.
--restore cannot be combined with --latest or --expected-version.
Incompatible flags.
Run the restore alone.
Automatic update requires --expected-version.
--auto without a target version.
Add --expected-version <v>, or let --latest --auto do it.
Executing package version X does not match expected version Y.
The running package is not the one you named.
Run npx bmad-plus@Y update ....
Downgrade refused: A -> B
The running package is older than the installed version.
Run a newer package.
Automatic update refused: <reason>
Policy does not allow it (approval-required, updates-disabled, outside-allowed-range, prerelease-not-allowed), or the project is legacy or has conflicts.
Use update-policy to inspect it, or approve manually with update --latest --yes.
Update refused: <reason>.
A --latest safety check failed: updates-disabled, automatic-updates-not-authorized (--auto while the policy mode is not auto), fresh-metadata-required, policy-channel-changed, downgrade-not-allowed, ownership-preflight-failed, incompatible-or-invalid-node-engine, and similar.
Read the reason, fix its cause, retry. fresh-metadata-required usually means npm was unreachable.
Updater finished without the expected manifest version X. Inspect the project before retrying.
The nested updater ended but the manifest does not show the target.
Run doctor; do not retry blindly.
Another update is in progress: <path>.
The project lock is held.
Wait; if it was interrupted, doctor says when it is stale and which file to delete.
Every generated instruction file tells the assistant to check once per session and to follow the project policy. You can ask it explicitly.
In your AI assistant
Is there a newer BMAD+ for this project? If an update is allowed by our policy, apply it, then tell me what was preserved.
What you should get The assistant runs npx bmad-plus update-check --json. If updateAvailable and canAutoApply are both true it runs update --latest --auto; if an update exists but cannot be applied automatically it explains the version and the reason, and applies it with update --latest --yes only because you asked. It does not change the policy, overwrite customised files or resolve conflicts on its own. Afterwards it rereads the project instructions, and reports the preserved conflicts the command listed.