Claude Code 2.1.251: The PreModelSwitch Hook Is Now Your Model Governance Control Plane
Claude Code 2.1.251 adds PreModelSwitch and PostModelSwitch hooks that let operators block, confirm, or annotate model switches in real time. Combined with new spend-limit visibility and per-session cache metrics, this release makes the client itself a usable governance surface.
Archive item produced with AI assistance from the cited source and published without individual review. Editor of record: Joe Werner.

Until now, Claude Code's hook system gave operators fine control over tool calls — block a bash command, intercept a file write, log MCP activity — but the model selection itself was opaque. A user or a sub-agent could request a model switch and the request simply went through. 2.1.251 closes that gap.
What changed in 2.1.251
Two new hook events ship in this release, along with cost visibility features that make the client a more useful piece of the operator governance stack.
PreModelSwitch fires before Claude Code applies any model switch requested by the user or a client. It is sequential — Claude Code waits for the hook to resolve before proceeding. The default behavior when a hook is registered but does not return a decision is block: the switch is cancelled. To allow the switch, the hook must return an explicit allow. To cancel with a message, it returns deny with a permissionDecisionReason. The hook receives from_model and to_model in the input, so a policy script can compare against an allowlist without parsing session context.
PostModelSwitch fires after the model has changed, including restores that happen when a session resumes. It is asynchronous — useful for logging the switch, adjusting downstream configuration, or notifying an audit trail.
SessionStart resume context now includes session staleness and estimated re-cache cost. Teams that pre-warm context windows on session start can factor in whether the previous cache is still warm before deciding to run a full warmup cycle.
Spend limit visibility arrives for teams running Claude Code behind a Claude apps gateway that enforces monthly spend caps. A spend limit progress bar appears in /usage, and a rate_limits.spend_limit field appears in the status line — available to shell scripts that parse Claude Code's machine-readable status output. Previously, the cap was only visible on the gateway's billing dashboard. Now it surfaces inside the client session.
Per-session prompt-cache metrics appear in /cost: hit ratio, cache misses, tokens re-cached, and a warm/cold indicator. For teams doing long agent runs, this turns cache utilisation from a guess into a per-session measurement.
What operators were missing before
The model switch gap matters most in two operational situations.
The first is enterprise license scoping. Many teams deploy Claude Code with an enterprise contract that covers Sonnet but not Opus. Prior to 2.1.251, a user who manually switched to Opus mid-session — or a sub-agent that was configured to use Opus — would make the request and it would succeed or fail depending on whether the gateway blocked it at the API layer. That API-layer block produces an opaque error; the session fails without a clear message about why. A PreModelSwitch hook can return a deny with a readable explanation instead.
The second is cost policy enforcement. Some gateway configurations route requests to different providers depending on model name. A switch from a cheaper model to a more expensive one mid-session can bypass the routing logic that would have applied at session start. A hook that checks to_model against a cost threshold and blocks or requires confirmation closes this.
The hook vs enforceAvailableModels
Claude Code has had enforceAvailableModels in managed settings since 2.1.176. The two controls are not redundant — they operate at different layers.
enforceAvailableModels is a static lock applied through managed settings, typically deployed by an organisation-wide managed settings file. It rejects any model ID that is not in the configured list, at the managed-settings check step. An operator can only update it by pushing a new managed-settings file.
PreModelSwitch is a runtime hook. It fires at the moment the switch is requested and can make dynamic decisions: check a user's cost budget from an external API, compare against the project's current quota, or log the switch and allow it with an annotation. It can also be deployed at the project level by any operator with access to the project's .claude/settings.json, without requiring an organisation-wide managed-settings push.
For strict allowlist enforcement, enforceAvailableModels is the right tool. For dynamic cost-aware or context-aware policy, PreModelSwitch is the layer that can respond to runtime state.
Security fixes that close operator assumptions
Three of the security fixes in 2.1.251 are worth auditing against operator deployments:
Symlink traversal in file tools: Read, Write, and Edit would follow a symlink swapped inside the working directory after the permission check. An attacker with write access to the working directory could create a symlink targeting a path outside the approved directory, then trigger a file read or write. Fixed — the permission check now covers the resolved path.
Plugin path traversal: Plugin commands declared in a marketplace entry could reference paths outside the plugin directory. Those paths are now rejected with a path-traversal error at load time.
OTEL bypass via project settings: Project settings could enable raw API body logging or detailed beta tracing in ways that bypassed an OTLP collector pinned by managed settings or a host app. This is fixed. Teams that use managed settings to pin an OTLP endpoint should verify the endpoint is receiving all traces, not just those from sessions where project settings didn't override the trace level.
The practical implication for gateway operators: if your organisation uses managed settings to control trace destinations and data retention, the 2.1.251 fix closes a leak path. Upgrading is not optional if OTLP pinning is part of your compliance configuration.
What to configure or audit
For the PreModelSwitch hook, the minimal governance policy — block any switch to a model not in the approved list — looks like this in .claude/settings.json:
{
"hooks": {
"PreModelSwitch": [
{
"hooks": [
{
"type": "command",
"command": "/usr/local/bin/check-model-policy.sh"
}
]
}
]
}
}
The shell script reads from_model and to_model from stdin as JSON and returns either no output (block) or an explicit allow. Because PreModelSwitch is sequential, the response blocks the switch until the script exits.
For the spend limit field, if your deployment uses status line scripts to feed cost data to a dashboard, add rate_limits.spend_limit to the fields you parse. Its presence signals that the session is behind a gateway with an active cap; its value shows remaining budget.
For the OTEL fix, run claude --version to confirm 2.1.251 and check your trace collector to confirm logs are arriving with no gaps.
What TheRouter users should watch or try
For teams routing Claude Code through TheRouter's developer gateway, the PreModelSwitch hook is the cleanest way to enforce model routing policy on the client side before the request reaches the API layer. A hook that matches to_model against your configured provider's available models prevents the session from requesting a model the gateway would reject, producing a clearer failure mode than a downstream 404.
The per-session cache metrics in /cost are also worth monitoring: a session with a consistently low cache hit ratio is spending more on re-encoding context than necessary, which shows up as inflated costs at the routing layer even when model prices have not changed.

Claude Fable 5.1 Arrives: Containment Escape Blocks Cloud Credential Fetches by Default
Claude Code ships Fable 5.1 with 1M context and a hard auto-mode gate on cloud metadata fetches — here is what every operator running production pipelines must audit now.

Claude Code 2.1.247: The /claude-api cost-optimize Command Changes How Operators Audit API Spend
Claude Code 2.1.247 ships a built-in cost-profiling command that walks operators through caching, batch, token hygiene, and model-choice levers, and fixes a silent failure where sub-agents died on their first model call without activating the gateway fallback chain.

Claude Code 2.1.219: Three Governance Changes Every Operator Must Audit Before Deploying
2.1.219 ships sandbox.network.strictAllowlist, raises nested subagent depth from 1 to 3, and caps dynamic workflows at medium by default — three changes that alter security posture, cost exposure, and agent orchestration policy without a single code change.