Uh oh!
There was an error while loading. Please reload this page.
fix: make Claude 200k context window selection take effect - #8409
Conversation
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
ApprovabilityVerdict: Not approved Macroscope's review found this PR not approvable — The PR changes effective Claude context-window defaults and overrides existing user/project settings across live sessions and CLI text-generation workflows. An unresolved medium-severity concern also remains around stale usage reporting during mid-thread window switches. Not approved because:
Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more. |
87eba2d to
5da0e5bCompareMaxHTu
commented
Sep 3, 2026
Rebased onto current |
| // rather than the process env: a user or project settings file's | ||
| // `env` block overrides the spawned process env, while flag settings | ||
| // outrank both (live-test finding; managed policy settings still win). | ||
| ...(contextWindowEnv ? { env: contextWindowEnv } : {}), |
There was a problem hiding this comment.
🟡 MediumLayers/ClaudeAdapter.ts:4353
A fresh session selecting a non-200k context window can still start at 200k: when contextWindowEnv is undefined, settings omits env, so a user/project CLAUDE_CODE_DISABLE_1M_CONTEXT: "1" setting remains effective. The model-switch path already clears this with { env: null }; initial session creation must pass the same clear value so the selected context window is deterministic.
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/Layers/ClaudeAdapter.ts around line 4353:
A fresh session selecting a non-200k context window can still start at 200k: when `contextWindowEnv` is `undefined`, `settings` omits `env`, so a user/project `CLAUDE_CODE_DISABLE_1M_CONTEXT: "1"` setting remains effective. The model-switch path already clears this with `{ env: null }`; initial session creation must pass the same clear value so the selected context window is deterministic.
There was a problem hiding this comment.
Good catch — reproduced: with a project .claude/settings.json setting CLAUDE_CODE_DISABLE_1M_CONTEXT: "1", a 1M selection ran at 200,000. Fixed in a135cad: the catalog helper now states the resolved window in both directions ("1" for 200k, "0" for any other known window) at session start and on mid-thread switches, so the window is decided by the selection alone. env: null isn't usable at startup (only applyFlagSettings accepts null), hence the explicit "0". Verified: flag-settings "0" beats the project-level "1" → 1,000,000.
There was a problem hiding this comment.
Sorry, I'm unable to act on this request because you do not have permissions within this repository.
Claude Code auto-enables the 1M-token context window for models that
support it (claude-opus-5, claude-fable-5, claude-sonnet-5), so passing
a bare model slug does not mean 200k — the session silently runs at 1M
regardless of the selection. State the selection explicitly through
CLAUDE_CODE_DISABLE_1M_CONTEXT ("1" when the catalog resolves the window
to 200k tokens, "0" otherwise), so the session runs the window T3
displays regardless of what a user or project settings file sets.
The rule lives in the model catalog (resolveClaudeCatalogContextWindowEnv),
keyed off the manifest's contextWindowTokens rather than a literal option
id, so remote manifest updates keep working. Models without catalog token
data are left to the user's configuration.
The value goes through the SDK settings option (the flag-settings layer)
instead of the spawned process env, because an `env` block in a user or
project settings file overrides the process env and would silently
defeat the fix. Managed policy settings still outrank it.
Because the flag-settings value also outranks an explicit `[1m]` model
suffix (verified empirically), sendTurn restates it via applyFlagSettings
whenever the resolved value changes, ahead of setModel. A failure there
is logged rather than failing the turn, so an older CLI that does not
know the control request loses only the window, not the turn.
ClaudeTextGeneration spawns the same CLI with the same bare slug, so it
gets the same treatment.
Fixespingdotgg#8405
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>5da0e5b to
a135cadCompare| }).pipe(Effect.as(false)), | ||
| ), | ||
| ); | ||
| if (applied) { |
There was a problem hiding this comment.
🟡 MediumLayers/ClaudeAdapter.ts:4627
Switching from a 200k to a 1M context window leaves context.lastKnownContextWindow at 200k, so streaming usage caps usedTokens at 200k until the terminal result arrives. Update the cached context window when applyFlagSettings succeeds so the new turn's usage is reported against the selected window.
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/Layers/ClaudeAdapter.ts around line 4627:
Switching from a 200k to a 1M context window leaves `context.lastKnownContextWindow` at 200k, so streaming usage caps `usedTokens` at 200k until the terminal result arrives. Update the cached context window when `applyFlagSettings` succeeds so the new turn's usage is reported against the selected window.
What Changed
Selecting the 200k context window for Claude models now actually runs the session at 200k. A new catalog helper,
resolveClaudeCatalogContextWindowEnv, states the resolved window to the CLI asCLAUDE_CODE_DISABLE_1M_CONTEXT—"1"when the manifest resolves the selection to 200k tokens,"0"for any other known window, nothing for models without catalog token data. The adapter injects it into the SDK's flag-settings layer at session start and restates it viaapplyFlagSettingswhenever the resolved value changes mid-thread;ClaudeTextGeneration(commit-message / PR-content / thread-title generation, which spawns the same CLI) applies the same value.Why
Fixes#8405. Claude Code auto-enables the 1M window for
claude-opus-5/claude-fable-5/claude-sonnet-5unless the process opts out, so the bare model slug does not mean 200k — the 200k selection was a silent no-op and every such session ran at 1M (verified empirically viamodelUsage[].contextWindow; details in the issue).Design points, each verified against SDK 0.3.170 + CLI 2.1.247:
contextWindowTokensrather than the literal"200k"option id, so remote manifest updates keep working and the synthetic test catalog covers it.settingSources: ["user", "project", "local"], and anenvblock in a user/project settings file overrides the spawned process env — aqueryOptions.env-based fix is silently defeated by e.g."env": {"CLAUDE_CODE_DISABLE_1M_CONTEXT": "0"}in~/.claude/settings.json. Flag settings (the SDKsettingsoption) outrank those files. Managed policy settings still win; the CLI's own usage report then corrects T3's meter."1"would clamp a 1M selection to 200k while T3's meter claims 1M. Since T3's meter, warnings andmaxTokensall derive from the same catalog data, any divergence makes T3 lie to the user — so the value is stated in both directions. Note for maintainers: this means T3 overrides a user's globalCLAUDE_CODE_DISABLE_1M_CONTEXT=1for every 1M-capable model, includingclaude-opus-4-7/4-8where T3 offers no selector. The per-selection control in T3's UI is the intended replacement.[1m]model suffix, so without restating it a session started at 200k (any default Sonnet session) would silently clamp a later 1M selection.sendTurnrestates it whenever the resolved value changes, ahead ofsetModel. A failure is logged rather than failing the turn, so an older CLI that doesn't know the control request loses only the window, not the turn.ClaudeTextGenerationspawns the same CLI with the same bare slug and already builds a--settingsobject, so it gets the same conditional spread.This also makes the context meter agree with reality (#5286):
selectedClaudeContextWindowseeds 200k and the CLI now confirms it instead of reporting 1M.Testing: new/updated unit tests in
ClaudeModelCatalog.test.ts(200k / 1m / fixed-window / no-data cases),ClaudeAdapter.test.ts, andClaudeTextGeneration.test.ts(all on synthetic catalog fixtures); typecheck clean. Behavior verified end-to-end through the real SDK: bare slug → 1,000,000; flag-settings"1"→ 200,000 even against a conflicting user-settingsenvblock; flag-settings"0"→ 1,000,000 against a project-settings"1"; mid-sessionapplyFlagSettingsflip verified in both directions.Checklist
I included before/after screenshots for any UI changes(no UI changes)I included a video for animation/interaction changes(no animation changes)🤖 Generated with Claude Code
Note
Fix Claude 200k context window selection to take effect via SDK flag settings
resolveClaudeCatalogContextWindowEnvin ClaudeModelCatalog.ts to map catalog-resolved token counts to Claude SDK environment settings: ≤200k tokens maps to the 1M-context opt-out state, larger windows map to enabled, and missing token data produces no mappingClaudeAdapter.startSessionin ClaudeAdapter.ts now merges the resolved context-window setting into initial SDK settings;ClaudeAdapter.sendTurncompares the current model's resolved window against tracked session state and applies an SDK flag-settings update before model switching when it changes, clearing with a null payload when catalog data disappearsClaudeAdapter.sendTurnnow issues an SDK flag-settings call on every turn where the context window differs from tracked state; flag-settings failures are logged but do not fail the turn, leaving the prior tracked value so a later turn retriesMacroscope summarized a135cad.