What is a hook, and what category of hook is PreModelSwitch?
A hook is Claude Code's mechanism for automatically running an action at a specific point in time — you can write a shell command, call an HTTP endpoint, call an MCP tool, feed an LLM prompt, or invoke a Subagent, and have it run automatically the moment a particular event fires. The two most common hooks are PreToolUse (before a tool runs) and PostToolUse (after a tool runs), corresponding to two different timings: "the tool hasn't run yet, so it can be intercepted" versus "the tool has already finished, so all you can do is handle it afterward."
PreModelSwitch applies that same logic to the action of switching models — it fires before the switch happens, so in principle it can be intercepted or denied. Its counterpart, PostModelSwitch, corresponds to the timing of "the switch has already happened," logically the same category as PostToolUse: you can log it, but you can't stop it.
Why does model switching deserve its own set of hooks, rather than just being covered by the general PreToolUse/PostToolUse?
The most direct reason is that a model switch isn't a "tool call" — it's a change to the session's own state, affecting which model handles every subsequent request, not the result of a single tool execution. Using a generic mechanism like PreToolUse/PostToolUse to intercept a model switch wouldn't give you the key information specific to a model switch — whether the current prompt cache is still warm, what the estimated cache-rebuild cost is — information that only makes sense in the context of knowing "this is specifically a model switch."
The deeper reason involves how Prompt Caching works: each model has its own independent cache, so once you switch models, the next request reads through the entire conversation with zero cache hits. Without a dedicated interception point letting you evaluate that cost before the switch happens, the cache-rebuild cost from a model switch becomes something you "discover after the fact" rather than something you could weigh beforehand — which is exactly the core reason PreModelSwitch exists.
How do you actually start using these two hooks? Is there a minimum viable setup?
Step one is to observe first, without rushing to intercept anything — before writing any interception rules, run a representative long task without deliberately switching models, and simply watch the new prompt-cache line in /usage, and, if you have a custom status line, what fields like prompt_cache.warm and prompt_cache.hit_ratio look like. Establishing a baseline for "what cache behavior normally looks like" first makes the rules you write afterward more accurate.
Step two is starting with three simple outcome categories, rather than a single hard-coded rule like "Opus is expensive": deny if the target model isn't on your approved list; ask if the current cache is still warm and the estimated cache-rebuild cost exceeds a threshold you set; allow if the cache is already cold, the context is small, or this switch is an expected part of the task flow. Log the source model, target model, source of the request (manual or automatic), context size, whether the cache was warm, and the estimated cost every time it fires — but never log credentials or the transcript content itself.
Step three is adding the after-the-fact logging logic for PostModelSwitch, paying particular attention to automatic fallback and session resume — the two scenarios that never go through PreModelSwitch — to make sure those switches get recorded too, rather than leaving zero trace at all.
If I'm just an individual developer with usually short conversations, is it worth spending time setting up these two hooks?
If your typical usage pattern is short, one-off conversations, rarely switching between models and rarely resuming old sessions from long ago, honestly the practical benefit of these two hooks is limited — you probably won't notice meaningful latency or cost differences from cache rebuilds, and the time spent writing interception rules may not be worth the return.
But if any of the following applies to you, it's worth spending some time on this even as an individual developer: you regularly run very long sessions (a single task lasting several hours or even spanning days) and switch models mid-task, either manually or via a fast mode; you're in the habit of resuming an old session from days ago to keep working rather than starting fresh each time; or you're using an SDK or Remote Control client that automatically picks a model for you, and you're not entirely sure when it switches. In these situations, even just adding PostModelSwitch logging logic first (no interception at all, purely observational) can help you clearly see how often model switching actually happens in your real usage and how costly it is. With that visibility in hand, deciding whether to add interception rules afterward is a much more grounded call than writing rules from the start.
Claude Code 2.1.251 (August 28, 2026) added two new hook events, PreModelSwitch and PostModelSwitch — meaning an action that used to happen silently inside a session (switching models) can now be intercepted, logged, and even blocked. If you've never heard of hooks at all, or only know PreToolUse and PostToolUse, this piece explains what these two new events actually do, from the ground up.
Claude Code lets you switch models mid-session — from Sonnet to Opus, say, or by enabling a fast mode that automatically changes the model. Previously, there was no interception point for this at all: a switch just happened, the system didn't ask you or log any detail, and you had no way to write a rule saying "don't casually switch models if the current conversation cache is still warm." For personal use, this might not feel like a real difference. But for anyone running long sessions, or a team sharing one gateway across multiple people, a model switch is actually a decision point that directly affects cost and result consistency — it's just that this decision point used to be completely invisible and uncontrollable.
PreModelSwitch fires at the moment a switch is about to happen. What it can see includes the requested source and target models, current context size, whether the cache is still warm, the cache's time-to-live, an estimated cache-rebuild cost, and the pricing source — with that information, the hook can decide allow, deny, or ask. PostModelSwitch fires after a switch has already completed. What it can see is the full result of that switch, including switches caused by automatic fallback or session resume — but this hook can only log the event or attach context to it; it can't stop something that's already happened.
Official documentation specifically flags a detail that's easy to overlook: an explicit switch request through /model, a picker, or /config triggers both PreModelSwitch and PostModelSwitch. But automatic fallback (say, a model is temporarily unavailable and the system switches to a backup) and restoring a previously-used model on session resume only trigger PostModelSwitch — they never go through PreModelSwitch for you to intercept. In other words, if you only write interception rules for PreModelSwitch and assume that covers every model switch, you'll still miss automatic fallback and session resume — those two scenarios can only be recorded after the fact through PostModelSwitch, never blocked in advance.
If you typically run short, one-off conversations, the impact of a model switch is usually limited, and you probably don't need to bother writing these two hooks. But if any of the following applies to you, it's worth the time to set them up: sessions that regularly run long, frequently switching between Sonnet and Opus, using a fast mode that auto-switches models, resuming old sessions, or an SDK or Remote Control client behind the scenes that selects models automatically. In these situations, a model switch often means the next request reads through the entire conversation with zero cache hits — and if the timing of that switch isn't consciously controlled, it can cause unexpected latency and cost.