◉CLAUDE LABEN
●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り44日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました●2.1.301 — vim の % モーション、VS Code パネルでの LaTeX 数式表示、使用量上限待ちのリトライ監視の上限が入りました(10/15)●2.1.299 — 200K トークン超で約54分放置した会話はアイドル圧縮。MCP の許可ルールは名指ししたサーバーだけに一致します●SONNET 4.5 — Claude API での提供終了は 11/30、残り44日。移行先は Sonnet 5.5●WINDOWS — 日本語の環境でだけフックが黙って壊れる報告があり、文字コードの確認が呼びかけられています●FAST MODE — Opus 5.5 の Fast mode がリサーチプレビューを終え、ベータヘッダーが不要になりました(10/15)●NEW — Cowork に渡したフォルダの先頭に、十行の約束ファイルを置いてみました
記事一覧/Claude Code
⟐ Claude Code/2026-09-02中級

モデル切り替えの記録と歯止めを、フック2本で作る

PreModelSwitch と PostModelSwitch を使い、無人実行中のモデル切り替えを記録するフックと、約束していない切り替えだけを止めるフックをゼロから作ります。実測値つきの手順です。

Claude Code265hooks22PreModelSwitchPostModelSwitch自動化87

✦ プレミアム記事

先週、無人で回している定期タスクの週次消費が思ったより伸びていたので、内訳を確かめようとしました。ところが手元のログには「どの枠が、いつ、どのモデルに切り替わったか」がどこにも残っていませんでした。残っていたのは各タスクの成否と成果物だけです。

個人開発で定型作業を自動化していると、枠ごとにモデルを変えるのは自然な設計になります。整形や置換のような定型作業は軽いモデル、文章の書き直しのような判断の要る作業は重いモデル、という具合です。ただ、その振り分けが「そのつもり」で終わっていて、実際にどう動いたかを一度も記録していませんでした。

Claude Code v2.1.251 で PreModelSwitch と PostModelSwitch という2つのフックイベントが追加されています。これを使って、記録する仕組みと、約束していない切り替えを止める仕組みを別々に作ります。分けて作るところに理由があるので、そこから書きます。

週次の消費は、切り替えの記録がないと事後に説明できません

Claude Code の週次上限はモデル横断の共有プールです。ステータスラインの JSON を見ると rate_limits.seven_day のほかに seven_day_opus・seven_day_sonnet という内枠があり、ひとつのプールの中にモデル別の枠が同居している構造が読み取れます。

つまり、ある枠が想定より重いモデルで走った分だけ、別の枠の余地が削られます。そして 9月14日からは、この週次上限がプロモーション前の水準に対して +25% で恒久化されます。現在の +50% と比べれば水準は下がるので、配分を測り直しておく価値があります。

測り直すには記録が要ります。事後に /usage で総量を見ても、「どの作業がどのモデルを食ったか」までは分解できません。切り替えが起きた瞬間にしか取れない情報があるので、その瞬間に書き出す仕組みを先に用意します。

2つのフックが受け取るもの

PreModelSwitch は切り替えの直前、PostModelSwitch はセッションのモデルが変わった後に発火します。他のフックが tool_name などを受け取るのに対して、この2つは切り替えそのものを説明するフィールドを受け取ります。

フィールド型意味
from_modelstring切り替え前のモデル
to_modelstring切り替え先のモデル
requested_modelstring | null明示的に要求されたモデル。自動的な切り替えでは null になります
source"command" | "picker" | "sdk"切り替えの経路。/model コマンド、対話的なピッカー、SDK 経由の3種です
context_tokensnumberその時点のコンテキストのトークン数
prompt_cache_warmbooleanプロンプトキャッシュが温まっているか
cache_ttl"5m" | "1h"キャッシュの有効期間
estimated_cache_write_usdnumberキャッシュ書き込みの推定費用(USD)
pricing"configured" | "catalog" | "default"費用の推定に使った価格表の出所

これに加えて、他のフックと共通の session_id・transcript_path・cwd が入ります。PostModelSwitch は同じフィールドを受け取り、source の取り得る値が2つ増えます。

source があるおかげで、人が画面の前でモデルを選んだ切り替えと、無人実行の中で起きた切り替えを区別できます。この区別が、あとで歯止めを作るときの分かれ目になります。

✦

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
✦無人実行でモデルが入れ替わっても、PostModelSwitch で残した1行の記録から、どの枠がどのモデルを消費したのかを後から説明できるようになる
✦PreModelSwitch に重い処理を置いたせいで切り替えそのものが止まる、という事故を書き始める前に避けられるようになる
✦モデル単価の差だけで判断していた切り替えの見積もりに、estimated_cache_write_usd が示すキャッシュ書き込みの費用を足して考えられるようになる
Stripe による安全な決済 · いつでもキャンセル可能
✦

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • ✦コピー&ペーストで使える実装コード付き
  • ✦毎日新しい上級ガイドを追加
  • ✦¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

⟐ Claude Code2026-08-28
検証スクリプトの出力を、そのまま hook から返してはいけません
hook に足した検査は正しく動いていたのに、会話のほうが先に容量を使い果たしていました。833ファイルで58バイトの検査と42KBの検査を実測で並べ、出力が会話に届く経路と、予算を機械的に守らせるラッパーの書き方をまとめます。
⟐ Claude Code2026-10-15
日本語フォルダ名を守るはずのフックが、一度も止めてくれませんでした — Python の stdin が cp932 で読んでいた話
「経理」「議事録」などの日本語フォルダを守る PreToolUse フックが、Python の stdin 既定が cp932 の環境では素通りします。再現の手順と 3 行の直し方、確認用の 1 コマンドを書き残します。
⟐ Claude Code2026-10-14
onFailure を block にしても、jq が無い環境では公式例の rm -rf ブロックは素通りしました
PreToolUse の門番フックは、落ちたときに通すのか止めるのか。公式例を jq の無い環境で走らせると exit 0 で素通りしました。終了コード10通りの実測、直し方、settings.json を走査して素通りを洗い出すスクリプトをまとめます。