Summary
claude-sonnet-5 is hardcoded to maxLevel: "high" in the bundled model catalog (packages/ai/src/models.json), so --thinking xhigh / --thinking max silently clamp to high on this model. Per Anthropic's current public docs, Sonnet 5 supports xhigh and max effort at the API level, same as Opus 5 and Fable 5.
Evidence (current official Anthropic docs, checked 2026-08-06)
docs.claude.com/en/docs/build-with-claude/effort — Compatibility section:
Supported models: claude-fable-5, claude-mythos-5, claude-mythos-preview, claude-opus-5, claude-opus-4-8, claude-opus-4-7, claude-opus-4-6, claude-sonnet-5, claude-sonnet-4-6, claude-opus-4-5-20251101
Per-level "Available on" lists in the same page:
xhigh: "Available on Claude Fable 5, Claude Mythos 5, Claude Opus 5, Claude Opus 4.8, Claude Opus 4.7, and Claude Sonnet 5."
max: "Available on Claude Fable 5, Claude Mythos 5, Claude Opus 5, Claude Opus 4.8, Claude Mythos Preview, Claude Opus 4.7, Claude Opus 4.6, Claude Sonnet 5, and Claude Sonnet 4.6."
The page also has a dedicated "Recommended effort levels for Claude Sonnet 5" section that explicitly documents xhigh ("For the hardest coding and agentic tasks") and max ("For tasks requiring the absolute highest capability with no constraints on token spending") as first-class supported levels for this model — not fallback/undocumented behavior.
docs.claude.com/en/docs/build-with-claude/thinking-troubleshooting — per-model thinking-type table confirms Sonnet 5 runs Adaptive only thinking (same family as Opus 5, not the older extended-thinking-only models), so there's no protocol-level reason it should be capped differently from Opus 5's effort ladder.
Current GJC behavior
packages/ai/src/models.json:
"claude-sonnet-5": {
...
"thinking": {
"mode": "anthropic-adaptive",
"minLevel": "minimal",
"maxLevel": "high"
}
}
vs. claude-opus-5 / claude-fable-5 which get max / xhigh respectively.
packages/ai/src/model-thinking.ts, inferAnthropicSupportedEfforts():
if (parsedModel.kind === "fable") {
return model.api === "anthropic-messages" ? DEFAULT_REASONING_EFFORTS_WITH_XHIGH : DEFAULT_REASONING_EFFORTS;
}
if (parsedModel.kind !== "opus") return DEFAULT_REASONING_EFFORTS; // <- Sonnet falls through here, capped at "high"
return anthropicModelHasRealXHighEffort(model)
? DEFAULT_REASONING_EFFORTS_WITH_XHIGH_AND_MAX
: DEFAULT_REASONING_EFFORTS_WITH_MAX;
and anthropicModelHasRealXHighEffort():
function anthropicModelHasRealXHighEffort<TApi extends Api>(model): boolean {
if (model.api !== "anthropic-messages") return false;
const parsedModel = parseKnownModel(model.id);
if (parsedModel.family !== "anthropic" || parsedModel.kind !== "opus") return false; // Sonnet excluded
return semverGte(parsedModel.version, "4.7");
}
Both the static catalog entry and the runtime inference function special-case kind === "opus" (with Fable getting a separate xhigh-only branch), leaving Sonnet on the old DEFAULT_REASONING_EFFORTS (minimal/low/medium/high) ceiling regardless of version.
Repro
gjc --model anthropic/claude-sonnet-5 --thinking xhigh -p "reply OK"
# effort silently clamps to "high" (clampThinkingLevelForModel in model-thinking.ts)
models.yml modelOverrides also can't work around this from user config — the documented overridable fields are name, reasoning, input, cost, contextWindow, maxTokens, headers, compat, contextPromotionTarget (per docs/models.md); thinking isn't in that list, so there's no user-side escape hatch either.
Expected
claude-sonnet-5 should expose xhigh and max effort, matching current Anthropic API support:
"thinking": {
"mode": "anthropic-adaptive",
"minLevel": "minimal",
"maxLevel": "max",
"levels": ["minimal", "low", "medium", "high", "xhigh", "max"]
}
and inferAnthropicSupportedEfforts() / anthropicModelHasRealXHighEffort() should stop gating xhigh/max on kind === "opus" only — Sonnet 5 (and presumably any future non-Opus model Anthropic ships with the same effort ladder) needs the same branch Opus/Fable get, ideally driven by an explicit per-model capability check rather than a kind allowlist that has to be manually extended every time Anthropic widens support.
Environment
- gjc version: 0.12.12
@gajae-code/ai version: 0.12.12
Summary
claude-sonnet-5is hardcoded tomaxLevel: "high"in the bundled model catalog (packages/ai/src/models.json), so--thinking xhigh/--thinking maxsilently clamp tohighon this model. Per Anthropic's current public docs, Sonnet 5 supportsxhighandmaxeffort at the API level, same as Opus 5 and Fable 5.Evidence (current official Anthropic docs, checked 2026-08-06)
docs.claude.com/en/docs/build-with-claude/effort— Compatibility section:Per-level "Available on" lists in the same page:
xhigh: "Available on Claude Fable 5, Claude Mythos 5, Claude Opus 5, Claude Opus 4.8, Claude Opus 4.7, and Claude Sonnet 5."max: "Available on Claude Fable 5, Claude Mythos 5, Claude Opus 5, Claude Opus 4.8, Claude Mythos Preview, Claude Opus 4.7, Claude Opus 4.6, Claude Sonnet 5, and Claude Sonnet 4.6."The page also has a dedicated "Recommended effort levels for Claude Sonnet 5" section that explicitly documents
xhigh("For the hardest coding and agentic tasks") andmax("For tasks requiring the absolute highest capability with no constraints on token spending") as first-class supported levels for this model — not fallback/undocumented behavior.docs.claude.com/en/docs/build-with-claude/thinking-troubleshooting— per-model thinking-type table confirms Sonnet 5 runsAdaptive onlythinking (same family as Opus 5, not the older extended-thinking-only models), so there's no protocol-level reason it should be capped differently from Opus 5's effort ladder.Current GJC behavior
packages/ai/src/models.json:vs.
claude-opus-5/claude-fable-5which getmax/xhighrespectively.packages/ai/src/model-thinking.ts,inferAnthropicSupportedEfforts():and
anthropicModelHasRealXHighEffort():Both the static catalog entry and the runtime inference function special-case
kind === "opus"(with Fable getting a separate xhigh-only branch), leaving Sonnet on the oldDEFAULT_REASONING_EFFORTS(minimal/low/medium/high) ceiling regardless of version.Repro
models.ymlmodelOverridesalso can't work around this from user config — the documented overridable fields arename, reasoning, input, cost, contextWindow, maxTokens, headers, compat, contextPromotionTarget(perdocs/models.md);thinkingisn't in that list, so there's no user-side escape hatch either.Expected
claude-sonnet-5should exposexhighandmaxeffort, matching current Anthropic API support:and
inferAnthropicSupportedEfforts()/anthropicModelHasRealXHighEffort()should stop gating xhigh/max onkind === "opus"only — Sonnet 5 (and presumably any future non-Opus model Anthropic ships with the same effort ladder) needs the same branch Opus/Fable get, ideally driven by an explicit per-model capability check rather than akindallowlist that has to be manually extended every time Anthropic widens support.Environment
@gajae-code/aiversion: 0.12.12