Claude Codeを使い込むほど、意図しないタイミングで高価なモデルへ切り替わって課金が膨らんだり、逆に安価なモデルのまま重い設計作業を任せてしまったりと、モデルの切り替えに気を揉む場面が増えてきます。2026年8月28日に公開されたClaude Code 2.1.251では、このモデル切り替えを自動で制御できる新しいフック「PreModelSwitch」「PostModelSwitch」が追加されました。結論からお伝えすると、この2つを使えば「Opusへの切り替えを特定の状況ではブロックする」「切り替えのたびにログを残す」といった制御を、settings.jsonの設定だけで自動化できます。この記事では、新フックの中身と2.1.251の変更点、これまでとの差分、そしてサイト制作や記事の自動化で暴走課金を止める実践設定までを、コピペできる形でまとめます。
この記事の要点
- PreModelSwitchはモデル切り替えの直前に発火し、切り替えをブロック・確認・注記できます。PostModelSwitchは切り替えの直後に発火する記録用のフックです。
- マッチャーは切り替え先モデル(to_model)の正規名で評価するため、「Opusへの切り替えだけを止める」といった条件分岐が組めます。
- 2.1.251では他にも、/usageの支出上限バー、/costのセッション別プロンプトキャッシュ表示、Remote Controlでのサブエージェント実況が追加されました。
- 編集部では、記事を無人で自動生成する工程でPreModelSwitchでOpusへの切り替えをブロックし、想定外の従量課金を止めるガードレールとして使っています。設定例をそのまま載せます。
01Claude Codeのモデル切り替えフックとは|3つのできること
モデル切り替えフックとは、モデルの切り替えを止める・確認する・記録するために、切り替えのタイミングへ独自のスクリプトを差し込める仕組みです。できることはこの3つで、Claude Codeがセッション中に使用モデルを切り替える瞬間をつかまえて動きます。Claude Code 2.1.251で「PreModelSwitch」「PostModelSwitch」の2つが追加されました。これまでフックは、ツール実行の前後(PreToolUse/PostToolUse)やセッション開始時(SessionStart)などに用意されていましたが、モデルの切り替えそのものを対象にしたフックはありませんでした。
PreModelSwitchとPostModelSwitchは何が違うのか
PreModelSwitchは、あなたやクライアントが要求したモデル切り替えを適用する前に発火します。ここで切り替えを止められるのが最大の特徴です。PostModelSwitchは、セッションのモデルが変わった後に発火します。こちらはClaude Codeが自分の判断で切り替えた場合(セッションを再開したときなど)も含めて発火しますが、止める用途ではなく記録・通知のためのフックです。
どちらのフックも、標準入力(stdin)にJSONで切り替えの情報を受け取ります。含まれるのは、セッションID、作業ディレクトリ、イベント名に加えて、切り替え元のfrom_modelと切り替え先のto_modelです。マッチャーはto_modelの正規名で評価されるので、「Opus系へ切り替えるときだけ」といった絞り込みが正規表現で書けます。
| 項目 | PreModelSwitch | PostModelSwitch |
|---|---|---|
| 発火タイミング | 切り替えを適用する直前 | モデルが変わった直後 |
| 切り替えをブロックできるか | できる(exit 2+deny) | できない(記録・通知用) |
| Claude自身の切り替えで発火するか | 要求ベースで発火 | 再開時などClaude起点も含む |
| 主な用途 | モデルの強制・切替の阻止 | 切替ログ・Slack通知 |
02Claude Code 2.1.251で何が新しくなったのか
2.1.251はモデル切り替えフックだけの更新ではありません。編集部が公式のchangelogで確認したところ、コスト管理と可視化まわりの追加がまとまって入っています。ここでは、日常的にClaude Codeを使う人に関わってくる変更を絞って紹介します。
コスト管理と可視化の追加
- /usageに支出上限バーが追加されました。Claudeアプリのゲートウェイ経由で支出上限が設定されている場合、上限までの残りが視覚的に見えるようになり、ステータスライン用に
rate_limits.spend_limitフィールドも渡されます。 - /costにセッション別のプロンプトキャッシュ行が追加されました。ヒット率・ミス数・再キャッシュされたトークン数・ウォーム/コールドの内訳が出るため、キャッシュがどれだけ効果を出しているかを1セッション単位で確認できます。
- SessionStartの再開フックが、セッションの陳腐化(staleness)と再キャッシュの推定コストを受け取れるようになりました。
サブエージェントとセキュリティの改善
Remote Controlのクライアントに、フォアグラウンドで動くサブエージェントのツール呼び出しと結果がライブで流れるようになりました(バックグラウンドのサブエージェントは従来どおりステータス表示のみ)。手元を離れて長時間タスクを回すときに、子エージェントが今何をしているかを追いやすくなります。サブエージェントの役割分担についてはサブエージェントとスキルの使い分けで詳しくまとめています。
セキュリティ面では、権限チェックの後にワークディレクトリ内でシンボリックリンクがすり替えられた場合にファイルツール(Read/Write/Edit)が追従してしまう脆弱性が修正されました。あわせて、マーケットプレイス登録のプラグインコマンドがプラグインディレクトリの外を指せてしまう問題も塞がれています。ネイティブバイナリのサイズも約5MB小さくなりました。
03これまでのモデル切り替えと何が変わるか【差分表】
2.1.251より前は、モデルの切り替えは/modelコマンドやオートモードによる手動・自動の切り替えだけで、その切り替えに割り込む手段がありませんでした。オートモードの挙動はオートモードがデフォルトになった件でも触れています。新フックが入ったことで、切り替えの前後にポリシーを差し込めるようになったのが今回の本質的な差分です。
| 項目 | これまで(2.1.251より前) | 今回(2.1.251) | 実務での意味 |
|---|---|---|---|
| モデル切替への割り込み | できない | Pre/Postフックで割り込み可能 | 切替をブロック・記録・注記できる |
| 高価なモデルへの切替防止 | 手動で気をつけるだけ | to_modelで条件付きブロック | 想定外の課金を仕組みで止められる |
| 支出上限の把握 | 明確なバー表示なし | /usageに支出上限バー | 上限までの残りが一目で分かる |
| キャッシュ効率の確認 | セッション別の内訳なし | /costにキャッシュ行 | ヒット率を見て無駄を減らせる |
アウトプットにはどんな差が出ると想定されるか
ここは編集部が実測した数値ではなく、仕様差からの想定として書きます。まず、PreModelSwitchで高価なモデルへの切り替えをブロックできる仕様から、大量ファイルの一括編集のような従量課金が伸びやすい工程で、安価なモデルに留めやすくなると想定されます。次に、to_modelで条件分岐できる仕様から、「設計フェーズはOpus、単純なコンポーネント量産はSonnet」といったモデルの使い分けを、人手の切り替え忘れに頼らず一定に保てるはずです。結果として、同じ作業を回したときのモデル構成のばらつきが減り、コストと品質の再現性が上がる方向に働くと考えられます。
04モデル切り替えフックの使い方|settings.jsonの設定
フックはsettings.jsonのhooksキーの下に、イベント名ごとに設定します。ここでは、Opusへの切り替えを止めるPreModelSwitchの最小構成を示します。
settings.jsonの最小構成
// .claude/settings.json
{
"hooks": {
"PreModelSwitch": [
{
"matcher": ".*opus.*",
"hooks": [
{ "type": "command", "command": ".claude/hooks/block-opus.sh" }
]
}
]
}
}マッチャーは切り替え先モデル(to_model)の正規名で評価されます。".*opus.*"と書けばOpus系への切り替えだけを拾い、Sonnetへの切り替えには反応しません。呼び出すスクリプト側で、実際にブロックするかどうかを判断します。
#!/bin/bash
# .claude/hooks/block-opus.sh
TO=$(jq -r '.to_model')
jq -n --arg to "$TO" '{
hookSpecificOutput: {
hookEventName: "PreModelSwitch",
permissionDecision: "deny",
permissionDecisionReason: ("この文脈ではOpus(\($to))への切り替えを禁止しています")
}
}'
exit 2 # exit 2 で切り替えを強制ブロックブロックの判定はどう書くのか
止めたいときは、標準出力にhookSpecificOutputを出し、permissionDecisionを"deny"にしたうえでexit 2で終了します。exit 2はJSONの内容で上書きできない強制ブロックで、理由はpermissionDecisionReasonに書いた文字列が表示されます。逆に、条件次第で通したいときはスクリプト内で分岐し、通す場合はexit 0で何も出さずに終えれば通常の切り替えが進みます。記録だけしたいならPostModelSwitchに同じ形でスクリプトを登録し、切り替え内容をファイルやSlackへ書き出します。
05サイト制作・LP制作での実践|工程でモデルを固定する
サイト制作やLP制作では、工程によって必要なモデルの重さが変わります。全体構成やデザイン方針を詰める設計フェーズは重いモデルの地力が要る一方、決まったコンポーネントを量産する段階では軽いモデルで十分なことが多いです。ここでモデルの切り替えを人の記憶に頼ると、単純作業をOpusで回し続けて費用がかさむ、といったずれが起きます。
量産フェーズだけOpusをブロックしてSonnetに固定する
そこで、コンポーネントの量産に入るディレクトリ(例:components/配下だけで作業するとき)では、PreModelSwitchでOpusへの切り替えをブロックし、Sonnetに固定します。判断材料はフックが受け取るcwd(作業ディレクトリ)です。
作業ディレクトリで判定するスクリプト
#!/bin/bash
# .claude/hooks/pin-sonnet-in-components.sh
INPUT=$(cat)
TO=$(echo "$INPUT" | jq -r '.to_model')
CWD=$(echo "$INPUT" | jq -r '.cwd')
# components配下での作業中はOpusへの昇格を止める
if [[ "$CWD" == *"/components"* ]]; then
jq -n '{ hookSpecificOutput: {
hookEventName: "PreModelSwitch",
permissionDecision: "deny",
permissionDecisionReason: "量産フェーズはSonnetに固定しています" } }'
exit 2
fi
exit 0この形にしておくと、設計フェーズでは自由にOpusへ上げられる一方、量産に入ると自動でSonnetに留まります。切り替え忘れによる費用のばらつきが減り、同じLPを繰り返し作るときの再現性が上がると想定されます。反対に、設計だけOpusへ寄せたいなら、条件を反転させて「設計ディレクトリ以外へのOpus切り替えを止める」書き方にします。
06自社ツール開発・自動化での実践|暴走課金を止める
編集部では、記事の下書きを無人で自動生成する社内の仕組みをClaude Codeで回しています。無人実行でいちばん怖いのが、想定外にOpusへ切り替わって従量課金が伸びることです。人が画面を見ていないぶん、暴走に気づくのが遅れます。ここでPreModelSwitchが役立ちます。
無人実行のときだけ高価なモデルをブロックする
自動実行時に環境変数(例:AK_HEADLESS=1)を立てておき、その値が立っているときだけOpusへの切り替えをブロックします。手動で開発しているときは環境変数が無いのでブロックされず、普段の使い勝手は変わりません。
環境変数で無人実行を見分ける
#!/bin/bash
# .claude/hooks/guard-headless.sh
TO=$(jq -r '.to_model' <<< "$(cat)")
# 無人実行フラグが立っているときだけOpusをブロックしSonnet系に留める
if [[ "$AK_HEADLESS" == "1" && "$TO" == *opus* ]]; then
jq -n --arg to "$TO" '{ hookSpecificOutput: {
hookEventName: "PreModelSwitch",
permissionDecision: "deny",
permissionDecisionReason: ("無人実行中はOpus(\($to))を禁止") } }'
exit 2
fi
exit 0あわせて、実行状況は/usageの支出上限バーで確認します。ゲートウェイ経由で支出上限を設定していれば、上限までの残りがバーで見えるので、自動実行を回す前後で残量をチェックする運用がしやすくなります。使用量の上限に達したときの挙動は使用量上限での自動再開設定もあわせて確認しておくと、無人運用の設計が固まります。PostModelSwitchで切り替えのたびにログファイルへ追記しておけば、後から「いつ・どのモデルに・なぜ切り替わったか」を追跡できます。
07使うときの注意点と向いている人
便利なフックですが、使い方を誤ると作業が止まります。導入前に押さえておきたい点をまとめます。
ブロックしすぎると作業が進まなくなる
PreModelSwitchで広く切り替えを止めると、必要な場面でモデルを上げられず、かえって作業効率が落ちます。最初は".*opus.*"のように高価なモデルへの昇格だけに絞り、通す条件を明示するところから始めるのが安全です。PostModelSwitchは切り替えを止められないため、監視や通知の用途に割り切ります。
向いているのは、複数の作業を並行して回す人や、無人でClaude Codeを実行する1人開発者・小規模チームです。モデルの使い分けをルール化したい場面、費用の暴走を仕組みで防ぎたい場面で価値が出ます。逆に、単一のモデルだけで対話的に使うシンプルな運用なら、無理にフックを組む必要はありません。バージョンごとの新機能は2.1.243のキーレスサインインなど、更新のたびに小さく足されていくので、必要なものだけ拾って設定するのが現実的です。
FAQよくある質問
PreModelSwitchとPostModelSwitchはどう使い分けますか?
切り替えを止めたいならPreModelSwitch、記録や通知だけしたいならPostModelSwitchです。ブロックできるのはPreだけで、exit 2とpermissionDecisionのdenyで確定させます。Postは切り替え後に発火し、Claude自身が再開時に切り替えた場合も拾えます。
特定のモデルへの切り替えだけを止められますか?
できます。マッチャーは切り替え先モデル(to_model)の正規名で評価されるため、".*opus.*"と書けばOpus系への切り替えだけにフックがかかります。複数のモデル名を|で並べた正規表現での指定も可能です。
この機能はどのバージョンから使えますか?
Claude Code 2.1.251(2026年8月28日公開)から利用できます。まずはclaude --versionでバージョンを確認し、古い場合はアップデートしてください。
支出上限バーは誰でも表示されますか?
Claudeアプリのゲートウェイ経由で支出上限が設定されている場合に、/usageへ支出上限バーが表示されます。あわせてステータスライン用にrate_limits.spend_limitフィールドが渡されるため、独自のステータス表示にも組み込めます。
フックでブロックすると会話は止まりますか?
止まるのは「モデルの切り替え」だけで、会話そのものは現在のモデルのまま続きます。ブロックの理由がpermissionDecisionReasonの文言として表示されるので、なぜ切り替わらなかったかは画面で分かります。
どの作業をどのモデルに振るかの判断基準はClaudeモデルの仕事別の使い分けで詳しく整理しています。
08まとめ:どこから設定するか
モデル切り替えフックを入れるかどうかは、「モデルの使い分けや費用を、人の注意ではなく仕組みで担保したいか」で決まります。まずはPreModelSwitchで".*opus.*"だけを対象に、無人実行や量産フェーズでOpusへの昇格を止める1本から始めるのが失敗しない進め方です。慣れてきたら作業ディレクトリや環境変数で条件を足し、PostModelSwitchで切り替えログを残す運用へ広げます。支出の把握は/usageの支出上限バー、キャッシュ効率は/costのキャッシュ行で定期的に確認します。関連する使い分けはサブエージェントとスキルの違い、無人運用の設計は使用量上限での自動再開にまとめています。
無人で決まった時刻に動かすところまで広げたい場合は、Claude Codeの定期実行を自動化する方法もあわせて確認してください。
09出典
- Anthropic「Claude Code changelog」(2.1.251 / 2.1.250、2026年8月28日)https://code.claude.com/docs/en/changelog
- Anthropic「Claude Code Hooks reference」https://code.claude.com/docs/en/hooks