Effort & Context
Reasoning effort
Section titled “Reasoning effort”Claude Code’s effort level (/effort, the /model slider, --effort, or CLAUDE_CODE_EFFORT_LEVEL) is sent as the output_config.effort request field, and shunt maps it to the Responses reasoning.effort for mapped models:
| Claude Code effort | → reasoning.effort |
|---|---|
low / medium / high / xhigh |
passthrough |
max |
passthrough on models that accept it (the gpt-5.6 family), else folded to xhigh |
Which reasoning levels a Codex slug accepts is listed per-model in openai/codex’s models.json (supported_reasoning_levels).
Precedence in shunt: a config route.effort / [providers.*].effort override wins first; otherwise the request’s output_config.effort is honored; otherwise thinking.enabled → high, then a model-name suffix (-xhigh/-high/-medium/-low, with -spark treated as -low), else medium.
Token counting (count_tokens)
Section titled “Token counting (count_tokens)”For an Anthropic-routed model shunt passes POST /v1/messages/count_tokens through to the upstream (exact counts). For a responses-routed model there is no equivalent upstream endpoint, so the provider’s count_tokens setting decides:
count_tokens = "tiktoken"(default) — shunt computes the count locally with tiktoken’so200k_baseencoder and returns{"input_tokens": N}. Near-exact for text on GPT-family models, and answered in-process (~ms) — which matters because Claude Code’s/contextissues onecount_tokenscall per displayed item (30–50 calls per invocation).count_tokens = "estimate"(opt-in) — shunt returns 404, which the gateway protocol explicitly allows. The main-loop context bar then estimates locally, but/contextre-runs every category count against Haiku over the network — slow, and silently reported as 0 tokens when no Anthropic credential is available.
Either way the request never reaches the responses adapter, so a count request is never turned into (and billed as) a full inference call.
Context / usage display for mapped models
Section titled “Context / usage display for mapped models”Claude Code computes the context indicator locally from the assistant message’s token usage divided by the model’s context-window size. For models routed to a responses provider:
- Token count (the numerator) is accurate. shunt reads
input_tokens(and cached tokens) from the Responsesusageand forwards them in the Anthropicmessage_delta, peeling the cached part intocache_read_input_tokens. - The window (the denominator) defaults to a fixed 200k for unrecognized ids. A model with a larger real window (e.g.
gpt-5.6-solat 372k) shows a conservative, over-reported percentage — this only makes auto-compact trigger a little early.
The 200k default can be overridden client-side with CLAUDE_CODE_MAX_CONTEXT_TOKENS (Claude Code 2.1.205+); it applies to any model id that does not start with claude-:
# e.g. gpt-5.6-sol's real windowexport CLAUDE_CODE_MAX_CONTEXT_TOKENS=372000The other client-side lever is the [1m] model-id suffix, which forces a 1M window — only use it when the upstream really has that window.
| Field | Mapped (responses) model |
Claude passthrough |
|---|---|---|
| Context tokens used | ✅ accurate (forwarded by shunt) | ✅ accurate |
| Context window (denominator) | ⚠️ 200k default; set CLAUDE_CODE_MAX_CONTEXT_TOKENS |
✅ exact |
count_tokens (pre-flight) |
⚠️ local tiktoken count (default) | ✅ exact (upstream) |
rate_limits (5h / weekly) |
❌ needs Anthropic headers | ✅ shown |
Context overflow recovery
Section titled “Context overflow recovery”When a conversation outgrows the upstream model’s real window, the provider rejects the request with its own wording — OpenAI’s context_length_exceeded, "This model's maximum context length is N tokens…", or a proxy’s "prompt token count of N exceeds the limit of M". Claude Code’s automatic compact-and-retry only fires on Anthropic’s phrasing, so unrewritten these errors would strand the session until a manual /compact (documented gateway pitfall).
shunt detects context-overflow errors on responses-routed models and rewrites them into the Anthropic shape Claude Code matches:
{"type": "error", "error": {"type": "invalid_request_error", "message": "prompt is too long: 372982 tokens > 272000 maximum"}}When the upstream message carries both token counts, shunt preserves them (whatever order the upstream states them in) — Claude Code parses the N tokens > M maximum gap and compacts past the whole overshoot in a single retry. When the upstream gives no counts (e.g. the Responses API’s plain “Your input exceeds the context window of this model”), shunt emits prompt is too long alone, which still triggers compaction. Non-overflow errors are passed through with their original message.
Attribution block
Section titled “Attribution block”Claude Code prepends an attribution line to the system prompt. Anthropic strips it before processing, but shunt forwards it unchanged, so a mapped provider receives it as the first line of instructions. It’s harmless but meaningless noise for a non-Anthropic model. To drop it:
export CLAUDE_CODE_ATTRIBUTION_HEADER=0This is global, so it also removes attribution from Anthropic-passthrough traffic (used for cost tracking) — fine when you’re routing to another provider.