Block Expensive Model Escalation Without Justification

Separate concern from the approved-model-list governance hook: this isn't about whether a model is *allowed*, it's about making sure escalating to a more expensive tier mid-session was a deliberate choice, not a default reflex, by requiring a one-line justification first.

Cost & Usage Controls Event: PreModelSwitch Claude Code Open source · Free

1. Save this as the hook script

#!/usr/bin/env python3
"""PreModelSwitch hook — blocks escalating to a pricier model tier
without a justification env var set."""
import json, os, sys

data = json.load(sys.stdin)
to_model = data.get("to_model", "")

EXPENSIVE_TIERS = ("opus",)

if any(t in to_model.lower() for t in EXPENSIVE_TIERS) and not os.environ.get("MODEL_SWITCH_REASON"):
    print(f"BLOCKED: switching to {to_model} is a cost escalation. Set "
          f"MODEL_SWITCH_REASON=\"<why>\" first.", file=sys.stderr)
    sys.exit(2)

sys.exit(0)

Save to a path inside your project, e.g. .claude/hooks/block-model-escalation-without-justification.sh, then chmod +x it.

2. Wire it into .claude/settings.json

{
  "hooks": {
    "PreModelSwitch": [
      {
        "hooks": [
          {"type": "command", "command": "python3 .claude/hooks/block-model-escalation-without-justification.py"}
        ]
      }
    ]
  }
}

Before you use this

A hook runs with your local shell's permissions — review the script above before adding it, the same way you'd review any script you didn't write yourself. See our guide on hook security risks for the specific CVEs this category of feature has already produced.

Related hooks

← All hooks
FEEDBACK