Finding
Claude Code decides "is this a first-party endpoint?" like this — verified in 2.1.216:
function Wd(){ if(Z._CLAUDE_CODE_ASSUME_FIRST_PARTY_BASE_URL) return !0; return K9n() }
function K9n(){ let e=process.env.ANTHROPIC_BASE_URL; if(!e) return !0; return jPe(e) }
function jPe(e){ try{ let t=new URL(e).host; return ["api.anthropic.com"].includes(t) }catch{ return !1 } }
Two things stand out:
- The allowlist is exactly one host. Any gateway, proxy, or third-party endpoint fails it — that's the root of #46416.
_CLAUDE_CODE_ASSUME_FIRST_PARTY_BASE_URL force-passes the gate. Leading underscore, undocumented, and the only underscore-prefixed variable in the entire binary — a strong signal it's internal/testing, not a supported knob.
Wd() gates a lot: native 1M context (eM), gateway model discovery, default and small-fast model selection, model-picker rows, CLAUDE_CODE_PROPAGATE_TRACEPARENT, and PBr() which returns "third_party_provider".
Also verified — provider identity is env-driven and independent of the URL gate:
function Tn(){ if(dy())return"gateway"; return Z.CLAUDE_CODE_USE_BEDROCK?"bedrock": … :"firstParty" }
Setting ANTHROPIC_BASE_URL alone leaves Tn() === "firstParty" while Wd() returns false. Two independent switches, and we should reason about them separately rather than assuming one implies the other.
Why this is not an obvious win
Flipping this makes Claude Code believe a third-party endpoint is Anthropic's. That plausibly unlocks 1M context and model discovery — but it also means first-party-only behaviour gets applied to a backend that may not support it: beta headers, experimental fields, adaptive thinking. That is precisely the class of 400 we are fixing in #3 (Extra inputs are not permitted, Input tag 'adaptive' found).
So this could trade one silent breakage for a louder one. It may also cause Claude Code to skip compatibility fallbacks it would otherwise apply.
An undocumented underscore-prefixed internal flag can also change or vanish in any release, with no deprecation path.
Task — investigate before adopting
Recommendation
Do not ship this by default. If it proves useful, put it behind an explicit opt-in (e.g. assumeFirstParty: true) with the tradeoff documented. [1m] (#14) is the supported, documented mechanism and should remain our primary lever.
Finding
Claude Code decides "is this a first-party endpoint?" like this — verified in 2.1.216:
Two things stand out:
_CLAUDE_CODE_ASSUME_FIRST_PARTY_BASE_URLforce-passes the gate. Leading underscore, undocumented, and the only underscore-prefixed variable in the entire binary — a strong signal it's internal/testing, not a supported knob.Wd()gates a lot: native 1M context (eM), gateway model discovery, default and small-fast model selection, model-picker rows,CLAUDE_CODE_PROPAGATE_TRACEPARENT, andPBr()which returns"third_party_provider".Also verified — provider identity is env-driven and independent of the URL gate:
Setting
ANTHROPIC_BASE_URLalone leavesTn() === "firstParty"whileWd()returns false. Two independent switches, and we should reason about them separately rather than assuming one implies the other.Why this is not an obvious win
Flipping this makes Claude Code believe a third-party endpoint is Anthropic's. That plausibly unlocks 1M context and model discovery — but it also means first-party-only behaviour gets applied to a backend that may not support it: beta headers, experimental fields, adaptive thinking. That is precisely the class of
400we are fixing in #3 (Extra inputs are not permitted,Input tag 'adaptive' found).So this could trade one silent breakage for a louder one. It may also cause Claude Code to skip compatibility fallbacks it would otherwise apply.
An undocumented underscore-prefixed internal flag can also change or vanish in any release, with no deprecation path.
Task — investigate before adopting
/statusreport the true context window?400s that don't occur with it off?[1m]suffix (BUG: z.ai preset silently runs at 200K context instead of 1M #14) — if that alone gets us the context window, this is unnecessary riskRecommendation
Do not ship this by default. If it proves useful, put it behind an explicit opt-in (e.g.
assumeFirstParty: true) with the tradeoff documented.[1m](#14) is the supported, documented mechanism and should remain our primary lever.