# update-policy

> Show or set the project policy that decides whether BMAD+ looks for updates and whether any may apply without you: modes off, notify and auto, channel, range, prereleases, the file and the errors.

Canonical: https://bmad-plus.rochetta.fr/docs/reference/cli-update-policy/
Language: en
BMAD+ version: 0.23.1
Documentation reviewed: 2026-10-19
Author: Laurent Rochetta
License: MIT

BMAD+ documentation › [Reference](https://bmad-plus.rochetta.fr/docs/reference/) › update-policy

The update policy is a small file in your project that says how much BMAD+ may do about new releases. The default is to tell you and wait. You can switch the lookups off, or allow automatic updates inside a version range you choose, which is how a team lets a trusted patch line roll forward while still keeping a human in charge of anything bigger. `update-policy` shows the policy and, with options, rewrites it. It never checks or installs anything itself.

<a id="synopsis"></a>
## Synopsis

**In your project terminal**

```sh
npx bmad-plus update-policy [-d <path>] [--mode <off|notify|auto>] [--range <semver-range>] [--channel <tag>] [--allow-prerelease | --stable-only] [--json]
```

**Options of update-policy**

| Flag | Argument | What it does |
| --- | --- | --- |
| `-d, --directory <path>` | folder | Project (default: current folder). |
| `--mode <mode>` | `off`, `notify`, `auto` | `off`: never contact npm. `notify`: check and report, a human applies. `auto`: allow automatic updates inside `--range`. `auto` requires `--range`. |
| `--range <range>` | semver range | The versions automatic updates may reach, for example `^0.23.0`. Must be a valid semver range. |
| `--channel <tag>` | npm tag | The npm release tag to follow. Default `latest`. Lowercase letters, digits, `-` and `_`, starting with a letter, 32 characters at most. |
| `--allow-prerelease` | - | Allow prerelease versions as targets. |
| `--stable-only` | - | Disallow prereleases (the default). Cannot be combined with `--allow-prerelease`. |
| `--json` | - | Print `{"policy": {...}, "changed": true\|false}`; errors print `{"error": "..."}`. |

<a id="policy-file"></a>
## The policy file

The policy lives in `_bmad/update-policy.json`. Without the file, the default applies: mode `notify`, channel `latest`, no range, no prereleases, registry `https://registry.npmjs.org/`. The registry is not configurable: any other value makes the policy invalid, so updates cannot be redirected to another source. Unknown keys are refused. The file is written atomically and never through a link.

**A policy allowing automatic patch updates in 0.23.x**

```json
{
  "schemaVersion": 1,
  "mode": "auto",
  "channel": "latest",
  "allowedRange": "~0.23.0",
  "allowPrerelease": false,
  "registry": "https://registry.npmjs.org/"
}
```

**What each mode does**

| Mode | `update-check` | `update --latest` |
| --- | --- | --- |
| `off` | Does not contact npm: status `off`. | Refused: `updates-disabled`. |
| `notify` (default) | Checks and reports; the reason is `approval-required`. | Only with `--yes`. `--auto` is refused. |
| `auto` | Reports `ready-for-authorized-update` when the target is inside the range and the files are unchanged. | With `--yes`, or with `--auto` for an in-range target; `--auto` also needs a complete ownership inventory and no conflicts. |

<a id="exit-codes"></a>
## Exit codes

**Exit codes of update-policy**

| Code | Meaning |
| --- | --- |
| 0 | Policy shown or saved. |
| 1 | Invalid option combination, invalid policy, or unreadable policy file. The message goes to the error stream (or to the JSON `error` field). |

<a id="real-output"></a>
## Output

The output is one line: `Update policy saved: ...` when you changed something, `Update policy: ...` when you only looked. The transcripts are composed from the code’s template and marked as simulated.

**Look, then allow patch updates** (Simulated)

```text
$ npx bmad-plus update-policy
Update policy: notify; channel=latest; range=none; prereleases=false
$ npx bmad-plus update-policy --mode auto --range "~0.23.0"
Update policy saved: auto; channel=latest; range=~0.23.0; prereleases=false
```

Illustrative transcript, not captured from a real run. Source: tools/cli/commands/update-policy.js line 40 and tools/cli/lib/update-policy.js DEFAULT_POLICY

<a id="errors"></a>
## Errors and what to do

**Messages of update-policy**

| Message | Cause | What to do |
| --- | --- | --- |
| `Choose --allow-prerelease or --stable-only.` | Both flags given. | Keep one. |
| `--mode auto requires an explicit --range.` | `auto` without a range. | Add `--range "<semver range>"`. |
| `Invalid update policy: check mode, channel, range, prerelease flag and official registry.` | A value is out of bounds: mode, channel name, range syntax, or a registry other than npm’s. | Correct the value. The registry cannot be changed. |
| `Automatic updates require an explicit allowedRange.` | The file says `auto` with no `allowedRange`. | Set a range, or change the mode. |
| `Update policy is unreadable or invalid: ...` | The existing file is not valid JSON or fails validation. | Fix or delete `_bmad/update-policy.json`, then set the policy again. |

<a id="examples"></a>
## Examples

**Never look for updates in this project**

```sh
npx bmad-plus update-policy --mode off
```

**Back to the default (tell me, I decide)**

```sh
npx bmad-plus update-policy --mode notify
```

**See also**

- [update-check](https://bmad-plus.rochetta.fr/docs/reference/cli-update-check/)
- [update](https://bmad-plus.rochetta.fr/docs/reference/cli-update/)
- [The whole lifecycle](https://bmad-plus.rochetta.fr/docs/guides/install-lifecycle/)

[BMAD+ documentation](https://bmad-plus.rochetta.fr/docs/) · [Reference](https://bmad-plus.rochetta.fr/docs/reference/)

[Source on GitHub](https://github.com/lrochetta/BMAD-PLUS)
