The gap ANTHROPIC_DEFAULT_MODEL fills
Before Claude Code v2.1.236, released 19 August 2026, there was no clean way to say "sessions on this machine should start on Sonnet" without writing to a settings file. ANTHROPIC_MODEL was the closest tool available, but it's a blunt instrument: exported in a shell, it overrides the model key in every settings file for as long as it stays set, including a choice you'd already saved with /model. That makes it wrong for the common case of just wanting a sensible starting point that a person can still change and have their choice stick.
ANTHROPIC_DEFAULT_MODEL is Claude Code's answer to that gap. It's documented directly in Claude Code's model configuration reference, and the short version is: it sets what a brand new session starts on, but only when nothing more specific already decided that.
export ANTHROPIC_DEFAULT_MODEL=sonnet
Put that in a shell profile, a Dockerfile, a self-hosted runner's environment, or a CI job's config, and every fresh Claude Code session launched in that environment opens on Sonnet, unless something else in the precedence chain below already made the choice.
What actually sets a session's starting model
Claude Code checks several places, in order, before it ever looks at ANTHROPIC_DEFAULT_MODEL. Per the model configuration reference, a new session starts on the variable's model only when none of these already selects one:
- The
--modelflag passed at launch ANTHROPIC_MODEL, if it's exported- A
modelvalue in any settings file, including a choice you've saved with/model - An organisation default model, on Claude Enterprise plans where an admin has configured one
That ordering is the whole point of the variable. It's a fallback, not an override. Once you save a model with /model, that choice persists in your settings and takes precedence over ANTHROPIC_DEFAULT_MODEL on every later launch, even though the variable is still exported. Compare that to ANTHROPIC_MODEL: with that one set instead, Claude Code returns to the variable's model on the next launch regardless of what you saved with /model, because ANTHROPIC_MODEL outranks the settings file every time, not just at first run.
ANTHROPIC_MODEL vs ANTHROPIC_DEFAULT_MODEL
ANTHROPIC_MODEL | ANTHROPIC_DEFAULT_MODEL | |
|---|---|---|
| What it sets | The model for this session, full stop | A fallback if nothing else picks one |
Beats a saved /model choice | Yes, every launch | No, once you save with /model |
Beats model in a settings file | Yes | No |
Beats the --model flag | No, --model wins | No |
| Minimum version | Any | Claude Code v2.1.236 or later |
| Good for | Pinning one model for a single session or script | A sensible default a person can still change |
If you want to force a specific model for one script or one CI job regardless of anything else, ANTHROPIC_MODEL (or --model) is still the right tool. If you want new sessions on a shared machine or a fresh onboarding to start somewhere reasonable without locking anyone in, ANTHROPIC_DEFAULT_MODEL is the one built for that.
The Default row and its label
The /model picker always includes a Default option. Once ANTHROPIC_DEFAULT_MODEL applies, Claude Code resolves that option to the variable's model too, unless an organisation default model also applies, in which case the org default wins. When the Default row is resolving to your variable, the picker labels it Set by ANTHROPIC_DEFAULT_MODEL so it's visible at a glance which source is actually in control, rather than you having to guess from behaviour alone.
Values Claude Code ignores
Not every string is valid here, and getting this wrong means the variable silently does nothing rather than erroring. Claude Code ignores ANTHROPIC_DEFAULT_MODEL entirely, and the Default option resolves as though you'd never set it, in four situations:
- You set it to
default,inherit,opusplan, orhaiku. These aren't valid targets for this variable; use a real model alias such assonnetoropus, or a full model name. enforceAvailableModelsis on. An administrator has turned on strict enforcement of the model allowlist for the Default option specifically.availableModelsor organisation model restrictions exclude the model. The variable can't redirect the Default option to a model your organisation has blocked.- The model isn't available to your account. Naming a model your plan or provider doesn't grant you access to does nothing.
None of these produce an error message at startup; the session just falls through to whatever the next rule in the precedence chain resolves to. If you set the variable and a session doesn't seem to be respecting it, check this list before assuming something else is wrong.
Setting it in practice
Personal shell, so every terminal you open defaults sensibly:
# ~/.zshrc or ~/.bashrc
export ANTHROPIC_DEFAULT_MODEL=sonnet
A Dockerfile, for a container image used across a team:
ENV ANTHROPIC_DEFAULT_MODEL=sonnet
A CI job, where you want a specific, cheaper model as the starting point for non-interactive runs but still want --model to win when a specific job needs something stronger:
env:
ANTHROPIC_DEFAULT_MODEL: haiku
A self-hosted runner, alongside the other environment configuration a fleet of machines shares. If you're already managing per-machine defaults this way, see how to self-host Claude Code runners and deploying a self-hosted runner to production for the surrounding setup.
Model aliases and the Opus/Sonnet/Haiku family variables
ANTHROPIC_DEFAULT_MODEL sits alongside a separate family of variables that control what a model alias resolves to, rather than which model a session starts on:
ANTHROPIC_DEFAULT_OPUS_MODELANTHROPIC_DEFAULT_SONNET_MODELANTHROPIC_DEFAULT_HAIKU_MODELANTHROPIC_DEFAULT_FABLE_MODEL
These pin exactly which dated model ID opus, sonnet, haiku, or fable resolves to, useful on Amazon Bedrock, Google Cloud's Agent Platform, or Microsoft Foundry, where you want to pin a version before a wider rollout. ANTHROPIC_DEFAULT_MODEL is different in kind: it doesn't redefine what an alias means, it picks which model (alias or full name) a new session opens on by default. The reference documentation is explicit that this table of alias-pinning variables omits ANTHROPIC_DEFAULT_MODEL, because it solves a different problem.
How it interacts with an organisation default model
On Claude Enterprise plans, an admin can set an organisation default model from the claude.ai admin console, for the whole org or per custom role, requiring Claude Code v2.1.196 or later. When one is configured, the Default option in /model resolves to that org default rather than to whatever ANTHROPIC_DEFAULT_MODEL names, and the picker labels that row Org default instead of Set by ANTHROPIC_DEFAULT_MODEL. A role-specific default takes precedence over an organisation-wide one, and when a person's several roles set different defaults, the most capable model applies.
The org default is described as a starting point rather than a hard restriction: a --model flag, ANTHROPIC_MODEL, or a model value saved anywhere, including through /model, still overrides it. Some organisations configure the default to override user selection instead, in which case it takes precedence even over a value saved in user, project, or local settings, and /model shows a note that your organisation's default applies again on restart. Either way, this is a separate mechanism from ANTHROPIC_DEFAULT_MODEL: the two can coexist, but the org default, when set, wins the Default row over your personal environment variable.
How it differs from fallbackModel
It's easy to conflate ANTHROPIC_DEFAULT_MODEL with fallbackModel, since both involve a secondary model choice, but they solve different problems entirely. ANTHROPIC_DEFAULT_MODEL decides what a brand new session starts on. fallbackModel decides what Claude Code switches to mid-turn, when the primary model is overloaded, unavailable, or returns a non-retryable server error:
{
"fallbackModel": ["claude-sonnet-5", "claude-haiku-4-5"]
}
A fallback switch lasts only for the current turn; the next message tries the primary model again. Claude Code caps a fallback chain at three models after removing duplicates, and drops any entry that availableModels doesn't permit. Setting ANTHROPIC_DEFAULT_MODEL doesn't configure any fallback behaviour, and setting fallbackModel doesn't change what a session starts on. If you want both, a sensible default for new sessions and resilience against a single model being temporarily unavailable, you set them independently.
How resuming a session interacts with it
Resuming usually restores the model a session was already using, independent of any environment variable. ANTHROPIC_DEFAULT_MODEL has one narrow exception: when a brand new session in that same environment would have started on the variable's model, resuming that session with claude --resume, --continue, or the /resume picker also opens it on that model. Claude Code doesn't restore the model saved in that session's transcript in this one case. Outside of that specific situation, the variable plays no role in what a resumed session runs on; the model saved in the transcript is what's restored, per the ordinary session resume behaviour.
Enterprise: keeping the variable inside an allowlist
Administrators managing availableModels in managed settings don't need to worry about ANTHROPIC_DEFAULT_MODEL becoming a bypass. The allowlist applies to every surface a user can pick a model from, and ANTHROPIC_DEFAULT_MODEL is explicitly named as one of them, alongside /model, the --model flag, ANTHROPIC_MODEL, the model setting, and the model restored on resume. If a developer sets the variable to a model outside the organisation's list, Claude Code ignores it rather than granting quiet access to a model policy excludes. When enforceAvailableModels is turned on specifically, the same exclusion applies even to what the Default option resolves to.
On platforms that embed Claude Code and set CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST, the host's own model configuration takes precedence over managed model settings generally, including the ANTHROPIC_DEFAULT_*_MODEL family, though a managed availableModels allowlist stays in force unless the host supplies its own.
Troubleshooting
The variable doesn't seem to change anything. Confirm you're on Claude Code v2.1.236 or later with claude --version; the variable is silently unrecognised on earlier releases. Then check whether a model value already exists in one of your settings files, including one saved by an earlier /model pick, since any of those take precedence.
A /model choice stopped tracking the variable after I changed it. That's expected. Once you save a model with /model, that saved choice wins over ANTHROPIC_DEFAULT_MODEL on every future launch. To go back to letting the variable decide, you'd need to change the saved model value in your settings file directly, not just the environment variable.
The Default row doesn't show the "Set by ANTHROPIC_DEFAULT_MODEL" label. Either the variable is set to one of the ignored values (default, inherit, opusplan, haiku), an organisation default model is overriding it, or an availableModels allowlist excludes the model you named. Work through those in order.
It works locally but not in CI. Confirm the variable is actually exported into the job's environment and not just set in a step that runs after Claude Code starts, and check whether the job also passes a --model flag or sets ANTHROPIC_MODEL, either of which takes precedence regardless of what ANTHROPIC_DEFAULT_MODEL says.
Where to go next
For the full picture of how Claude Code layers settings, environment variables, and command-line flags against each other, see Claude Code's own settings precedence documentation. For running Claude Code across a fleet of machines where a variable like this genuinely earns its keep, see how to self-host Claude Code runners and deploying a self-hosted runner to production. Browse the current Claude Code catalogue at getclaudeskills.com/platforms/claude-code.
Verified 22 August 2026 directly against Claude Code's own model configuration, settings, settings reference, and environment variables documentation at code.claude.com. Precedence rules and version numbers reflect what those pages document as of that date.
