What model does Claude Code use? On the machine this was written on — CLI 2.1.232, no model set in any configuration file — a single five-word prompt was billed to two different models, and nothing in the repository decided which. The session model was claude-opus-5[1m]; claude-haiku-4-5 ran alongside it. This article shows the resolution chain that produces that answer, the committed script that reads it, and the one-line change that moves the decision into git.
Key takeaways
- One turn used two models.
modelUsageon a single headless run namedclaude-haiku-4-5-20251001andclaude-opus-5[1m]— the question has a plural answer. - There is no shipped default to look up. Part of the model list is fetched from the account and cached in
~/.claude.json, which is why two developers on the same CLI version see different menus. - Model ids carry a context suffix.
claude-opus-5[1m]reports a 1,000,000-token window withcanonicalModel: claude-opus-5. The bracketed form appears in no public model list. - On this repository the resolution chain falls all the way through to the account, so the model can change without a commit. That is a one-line fix.
- The prompt was 2 tokens of the 32,005 that reached the model — 0.006%. Which model you pick matters less than most comparisons assume.
The short answer
Claude Code uses whichever model your account resolves to, unless a settings file or an environment variable pins one — and it uses a cheaper model alongside it on the same turn regardless. If you want a stable answer, put model in .claude/settings.json and commit it; if you want a cheaper bill, the effort setting is the larger lever.
For everything around the model — the permission system, subagents, the instruction file — the complete Claude Code guide is the pillar this sits under.
Two models ran, not one
The measurement is one headless invocation with JSON output, which reports per-model usage for the turn. That is the whole method: no instrumentation, no proxy, one documented flag.
claude -p "Reply with exactly: ok" --output-format json --effort low
MODEL ID CANONICAL CONTEXT MAX OUT IN OUT COST claude-haiku-4-5-20251001 claude-haiku-4-5 200,000 32,000 521 12 $0.000581 claude-opus-5[1m] claude-opus-5 1,000,000 64,000 2 4 $0.092567
Four things in that table are worth more than the model names.
Haiku is not incidental. It read 521 input tokens and wrote 12 — real work, on a prompt that asked for one word. Whatever it is doing, it does it on turns you did not ask it to.
The session model read 2 input tokens. Not two thousand. The prompt was almost the entire uncached input, because the other 32,003 tokens arrived as cache reads and cache writes. That is the harness, and it is the reason the model choice moves the bill less than people expect.
The context windows differ by 5x between the two models on the same turn, and both are reported, so you can see which ceiling applies to what. How much of either ceiling a real repository consumes is a separate measurement — one lockfile came to 139,640 tokens, which is most of the smaller window on its own.
The output ceiling is not the published one. Anthropic's model overview lists 128k max output for Claude Opus 5 on the Messages API; the CLI reported maxOutputTokens: 64000 for the same model on this turn, and 32,000 for Haiku 4.5 against a published 64k. Claude Code is setting its own cap, roughly half the API maximum in both cases. Worth knowing before you plan a task around a single long generation.
The cheap model cost 0.6% of the turn. $0.000581 against $0.092567. Worth knowing about, not worth optimising.
What model does Claude Code use here: the resolution chain
The reason there is no single documented answer is that the model is the output of a precedence chain, and the last step is not a file.
--model flag → .claude/settings.local.json ← repo, not committed → .claude/settings.json ← repo, committed → ~/.claude/settings.json ← machine → ANTHROPIC_MODEL ← environment → whatever the account resolves to ← not visible from the repository
Every step but the last is something you can read, diff and hand to a teammate. The last one is not. The committed check reports where a given repository lands:
npm run check:model
CLI 2.1.232 (Claude Code)
Where a model could be pinned, highest precedence first
SOURCE FILE PRESENT MODEL EFFORT
project (local) .claude/settings.local.json yes — —
project (shared) .claude/settings.json no — —
user ~/.claude/settings.json yes — —
Account state cached on this machine (~/.claude.json)
Org default none cached
Model access empty — no per-model grants cached
Additional options 1 fetched from the account, not shipped in the CLI
claude-fable-5[1m] Fable
FAIL: nothing in this repository pins a model.
That Additional options line is the finding. ~/.claude.json carries additionalModelOptionsCache, orgModelDefaultCache and modelAccessCache — the set of models the CLI will offer you is partly server state cached on disk. It is not a list compiled into the binary, which is why "what model does Claude Code use" cannot be answered by reading the release notes, and why two developers on identical CLI versions can genuinely see different pickers.
The suffix on the model id
claude-opus-5[1m] is not a typo and not a version. The usage payload reports it as the model id while giving canonicalModel separately as claude-opus-5, with contextWindow: 1000000. The same bracketed form shows up in the cached account options, where claude-fable-5[1m] is listed with the label Fable.
This matters in exactly one place, and it is a place people hit: string matching. Cost dashboards, log parsers, allowlists and analytics that compare a model id against a published list will miss the bracketed variant, because the bracketed variant is not on the published list. Match on the canonical field where one is available, or match on a prefix.
Sonnet vs Opus, and the setting that matters more
The Sonnet-versus-Opus question is real, and it is smaller than the question next to it. We since measured it properly — two probes, one per tier — and the premium turns out to be exactly 2.5x on identical work, invariant across every token shape, while the figure this CLI reports for the pair is 1.3x. Claude Code exposes both:
claude --model sonnet --effort medium
# --model accepts an alias ('opus', 'sonnet') or a full id ('claude-opus-5')
# --effort accepts low, medium, high, xhigh, max
Aliases track the latest model in a family, which is convenient and is also a moving target — an alias pinned in a committed settings file will silently start meaning something else when the family advances. A full id does not move. Neither is wrong; they are different promises, and the choice deserves a sentence in your project's setup notes rather than a shrug.
On effort: the environment on this machine reported CLAUDE_EFFORT=high for a running session, and the flag documents five levels. Effort changes how much thinking a turn does, which on agentic work moves the bill and the wall-clock more than swapping model families does. If a session feels expensive, measure before you downgrade — why Claude Code gets slow covers the other half of that, and what AI coding assistants actually cost covers the pricing side.
Pin the model in the repository
If the answer to "which model built this" should live in git rather than in a menu, it is one file:
{
"model": "claude-opus-5"
}
Commit it. Two consequences, both worth accepting deliberately:
- A pinned full id stops tracking the family. You will get the model you asked for after the next release, which is the point, and you now own the upgrade.
- A pinned model overrides the account default for everyone on the repository, including people whose account would have offered something else. That is usually what a team wants and occasionally is not.
The check exits non-zero until one of those files names a model, so it works as a build step or a pre-commit hook rather than as something you remember to run.
What we are not claiming
This article does not rank the models against each other, and the omission is deliberate.
Everything above is a measurement of resolution and accounting — which model was selected, what it reported about itself, what it cost. None of it is evidence about output quality, which would need a controlled task set and a grader, and which the harness dominates anyway: 32,003 of the 32,005 input tokens on the measured turn were not the prompt.
Two further limits, stated plainly. The probe is one account on one day; the resolution chain means yours can differ legitimately. And the cached account state was read from ~/.claude.json, which also holds identifiers — the committed script touches four keys by name for that reason, and prints none of the rest.
Common mistakes reading the model picker
- Assuming the picker is the whole list. Part of it is fetched and cached per account. An option a colleague has and you do not is not necessarily a version difference.
- Reading one model per turn. Two were billed on the smallest prompt we could write.
- Matching model ids as exact strings.
claude-opus-5[1m]will not equalclaude-opus-5, and the bracketed form is the one in the usage payload. - Pinning an alias and calling it pinned.
opustracks the family; the family moves. - Optimising the model before the harness. On the measured turn, the prompt was 0.006% of what reached the model, and emptying the tool list is enough to make the same model answer a repository question wrong.
Conclusion
Put model in .claude/settings.json and commit it, so the answer stops depending on an account setting nobody can see from the repository. Then run npm run check:model on your own project and read the modelUsage block from one headless turn before you plan anything around cost — on this machine that took one command and returned two models, a bracketed id that is on no public list, and a prompt that was two tokens of thirty-two thousand.
Frequently asked questions
What model does Claude Code use by default?
Does Claude Code use more than one model in a single request?
What does the 1m in claude-opus-5[1m] mean?
How do I pin Claude Code to a specific model?
Should I use Sonnet or Opus in Claude Code?
Muhammad Kashif
Founder and editor of Devventa, covering AI coding assistants, Next.js and the modern AI development stack.




