[Bug] Auto-compact window not updated after mid-session model switch
Bug: /context's "Auto-compact window" doesn't update mid-session on /model switch
Environment
- Claude Code:
2.1.211 - Platform: Linux (WSL2),
6.6.114.1-microsoft-standard-WSL2, x86_64 - Node:
v22.21.0 - Reproduced in both the terminal and the VS Code extension
Summary
After switching the active model with /model mid-session, /context's "Auto-compact window" line keeps showing the previous model's window — indefinitely, even across real message turns. The model name/id shown in the same /context view updates correctly; only the auto-compact window value is stale. Only a full session restart/resume fixes it.
Reproduction (pure native, no plugins/hooks involved)
- Start a session on any model. Run
/context, note the "Auto-compact window" value. - Run
/autocompact auto(clears any explicit override, so the window is computed purely from Claude Code's own per-model default). - Switch models with
/modelto a model with a meaningfully different context size (e.g. Sonnet ↔ Opus, or any model ↔ Fable). - Send a real message (e.g. "hi") and get a real response.
- Run
/contextagain.
Expected: "Auto-compact window" reflects the value tuned for the currently active model (the doc text for auto itself says "picks a window tuned for your model").
Actual: it still shows the previous model's window. Confirmed this persists:
- across a real message/response turn (not just immediately after
/model), - after opening and closing
/hooks(which we hypothesized might force a config reload — it doesn't), - with zero third-party plugins/hooks involved — pure native
/autocompact auto, no override ever set.
Only exiting and reattaching to the same session (claude --continue / claude --resume, or VS Code "Reload Window") picks up the correct value — i.e., a fresh process re-reads settings.json/re-resolves the model correctly at boot, but the already-running process never does.
Why this matters
Any workflow that relies on /context (or the actual auto-compact trigger point, if it shares the same stale resolution — untested directly, but plausible given the symptom) to reflect the current model mid-session is silently wrong. This also blocks any hook-based tooling (via SessionStart/UserPromptSubmit) from keeping a per-model autoCompactWindow override in sync without asking the user to restart every time they switch models — there is no hook event for "model changed" or "settings.json changed externally," and no hook output field to trigger a native command or force a settings reload (checked the full hook output schema: systemMessage, continue, stopReason, suppressOutput, decision, reason, hookSpecificOutput.{additionalContext,permissionDecision,permissionDecisionReason,updatedInput} — nothing applicable).
Hypothesis (from reading the minified bundle — not source-confirmed, just a lead)
The running process appears to cache the effective settings object in memory at session start and only invalidates that cache on its own internal writes (e.g. the native /autocompact <value> command, which explicitly clears/updates the cache as part of its own write path). External writes to settings.json (by any other process) are never picked up by a live file-watch during the session. For the auto resolution path specifically, the function that computes /context's auto-compact window line appears to receive a "current model" reference that isn't the same live-updated one used to render the model name elsewhere in the same view — so even with no override set at all, switching models doesn't reflect in that one computed value until the process restarts.
Ask
- Either make
/context's auto-compact resolution re-derive from the live current model on each render (matching how the model name itself already does), or - Expose a supported way (hook output field, or a lightweight native command) to force a live settings/model re-resolution without a full session restart — this would unblock accurate per-model auto-compact tooling entirely.
---
Separate UX feedback: friction points for less-technical users
Found while building a plugin (per-model auto-compact windows) and troubleshooting the bug above. None of these are the main bug — they're smaller things that compound into "you need to be fairly technical (or have an AI assistant reverse-engineer the binary, which is how we found the bug above) to understand what's going on."
1. Slash-command argument hints are inconsistent, silently
A command's argument-hint frontmatter only renders in the command picker/UI when the command file is .md. The same frontmatter in a .toml command file is silently ignored — no warning, no error, nothing in docs surfacing this distinction that we found. A plugin author using .toml (a perfectly valid, documented format) ends up with a command that looks broken/unfinished to end users (no hint, no discoverability of what arguments it takes), with no signal telling the author why.
2. No GUI surface for plugin/hook configuration
/context has a genuinely good, discoverable visual panel (grid, categories, percentages). Plugin and hook configuration has nothing comparable in the VS Code extension — it's CLI commands and hand-edited JSON files (settings.json, a plugin's own config file) end to end. For a non-technical user, "go edit this JSON file in ~/.claude/" or "run this CLI binary from a terminal" is a much higher bar than a settings toggle, and the terminal-only path doesn't exist at all inside the VS Code extension's UI unless the user already has a terminal open.
3. No in-app signal that a setting needs a restart to take effect
This compounds directly with the bug above: nothing in the UI ever says "this won't apply until you restart." claude plugin update prints "Restart to apply changes" in the CLI — good, that one's covered — but plain settings.json changes (like autoCompactWindow, or anything else written outside the app's own commands) give zero indication, in /context, in the statusline, anywhere, that what's displayed might not reflect a pending external change or a stale session-start snapshot. A technical user can reason about "oh, this is probably cached"; a non-technical user just sees a wrong number with no explanation and no path to figuring out why.
4. Restart requirements are inconsistent and undocumented across surfaces
Some things apply instantly (statusline commands re-run every render), some need a restart to register at all (hook registration changes, plugin code updates — confirmed while building this: a freshly-installed/updated plugin's hooks don't run until the next session), and some are cached for the entire session regardless of how many times the underlying file changes (the bug above). There's no single place that documents which category a given setting/change falls into — we had to discover each one by testing.