Claude Codeをサクサク動かして、トークンを節約するためのプロンプトキャッシングの話。

なお、この記事には生成AIの出力が含まれる。

消えるプロンプトキャッシュ、溶けるトークン

Claude Codeを使っていると、たいていのターンはサクサク返ってくるのに、特定のタイミングでレスポンスが妙に遅いことがある。

たいていそれは、モデルを切り替えた直後だったり、長く放置したあとの最初のプロンプトだったりする。 これは、Claude Codeの裏で効いているプロンプトキャッシュが消えて、これまでのコンテキストを丸ごと処理し直しているからだ。 これが起きると、レスポンスが遅くなるだけじゃなくて、無駄にトークンを消費してしまう。

実際のところ、Claude Codeはデフォルトでプロンプトキャッシュを自動でいい感じに効かしてくれるので、普段はそれほど意識しなくてもいい。 とはいえ、その仕組みと「キャッシュを壊す操作」を知っておくと、セッションをより速く安く保つコツがつかめる。 この記事は、Claude Code公式ドキュメントのHow Claude Code uses prompt cachingをベースに、そういったコツをまとめたものである。

プロンプトキャッシュの基本

まずは、何がキャッシュされ、何をきっかけに効いたり消えたりするのか、その土台となる仕組みを押さえておく。

そもそもプロンプトキャッシングとは

まず前提として、LLM自体はステートレスで、リクエストとリクエストとの間で何も覚えていない。 セッションの中で会話が続いているように見えても、Claude Codeは毎ターン、

  • システムプロンプト(中核の指示やツール定義)
  • プロジェクトコンテキスト(CLAUDE.md など)
  • これまでの全メッセージとツール実行結果
  • 今回の新しい入力

を丸ごとClaude APIに送信している。 だから、MCPツールをたくさん有効にしていたり、会話履歴が長くなると、リクエスト1回当たりの入力トークン量が大きくなって、処理時間や課金額が増えてしまう。 新しい入力はコンテキスト末尾に追記されるので、リクエストの大部分は前回とまったく同じになり、同じ部分について冗長な再処理が走っていることになる。

プロンプトキャッシングはこの「変わっていない先頭部分(プレフィクス)」の再処理を省くための、Claude APIの機能。 再処理を省ければ、処理時間と課金額が削減できる。

プロンプトキャッシュをうまく活用するためのポイントは以下の2つ:

  1. キャッシュは前方一致

    キャッシュは、Claude Codeが送信した内容と前方から比較され、一致(ヒット)した部分が活用されて、残りはミスとなり捨てられる。 プレフィクスのどこか1か所でも変わると、それ以降はすべて計算し直しになる。ファイル単位やセクション単位のキャッシュは存在しない。

  2. コストが非対称

    キャッシュからの読み取りは通常の入力トークンの10%と激安だが、キャッシュへの書き込みは逆に割高になる。

つまり、「読み取りが多く、書き込みが少ない」状態を保つほど速くて安い。 プロンプトキャッシュ運用は、これを意識しておくことが大事。

キャッシュの3レイヤー構造

前方一致が条件なので、Claude Codeは「めったに変わらないものを先頭に、頻繁に変わるものを末尾に」並べることで、プレフィクスをできるだけ長く保とうとしている。 Claude CodeがAPIに送るリクエストはおおまかに次の3レイヤーで構成されている。

レイヤー 主な内容 変わるタイミング 対応するAPI層
システムプロンプト 中核の指示、ツール定義、output style ツール定義変更、Claude Codeアップグレード toolssystem
プロジェクトコンテキスト CLAUDE.md、auto memory、各種ルール セッション開始、/clear/compact system
会話 ユーザープロンプト、Claudeの応答、ツール実行結果 毎ターン messages


この3レイヤーは、Claude Code独自のものではなく、Claude APIのキャッシュ構造の上に乗っている。 APIのプロンプトキャッシュは toolssystemmessages という厳密な順序で構築され、各層は前の層の上に積み上がる。 Claude Codeの3レイヤーをここに対応づけると、ツール定義は tools、中核の指示(i.e. Claude Code組み込みのシステムプロンプト)やoutput style・CLAUDE.md・auto memory・各種ルールは system、そして会話のやり取りは messages に入る。

大事なのは、下位のレイヤーが変わると、それより上位のレイヤーがすべて無効化されるということ。 これは toolssystemmessages の順でプレフィクスを照合するというAPI層の階層的なキャッシュ無効化メカニズムそのものである。 逆に、毎ターン変化する会話レイヤーへの追記は、その下のシステムプロンプトとプロジェクトコンテキストのキャッシュを壊さない。 だから、単にプロンプトをやり取りするような使い方だとキャッシュがよく効く。

普段よくやる操作で、特に注意すべきなのは以下の プロンプト本文には現れない2つのキャッシュキー

  • モデル: モデルごとに別のキャッシュを持つ。
  • effort level: 同じモデルでもeffortのレベルごとに別のキャッシュになる。

どちらもセッションの途中で変えると、たとえAPIに送信する内容がまったく同じでも全部が再処理になる。 これが次章で説明する「キャッシュを壊す操作」の代表格である。

プロンプトキャッシュ管理

仕組みがわかったところで、ここからは日々の操作がキャッシュをどう壊し、あるいは壊さないのかを具体的に見ていく。

キャッシュを壊す操作(避けられるもの)

以下の操作は、次のAPIリクエストでキャッシュの一部または全部を外す。 結果として、その直後の1ターンだけ遅く・高くなり、そのあと新しいプレフィクスが改めてキャッシュされる。 多くは「コストがあると知っていれば作業中に避けられる」ものだ。

  • モデルの切り替え (/model)

    モデルごとに別キャッシュ扱いになるので、切り替えた次のリクエストは全履歴をキャッシュなしで再処理される。注意点として、opusplan 設定はplanモードの出入りのたびにOpus⇄Sonnetを行き来するため、モデル切り替えが自動で発生する。

    Fable 5の自動フォールバックも同様。

  • effortの変更 (/effort)

    モデルと並ぶキャッシュキー。 Claude Codeは、会話が始まったあとでeffortの変更をしようとすると、キャッシュ無効化について確認メッセージを出してくれる。

  • fast modeをONにする

    リクエストヘッダがキャッシュキーに含まれるため、ONにした最初のターンは全履歴を読み直し、そのトークンはfast modeの料金で課金される。 コストがかかるのは会話につき1回きりだけど、長いセッションの途中でONにするほど高くつく。使うならセッションの最初に設定すべし。

  • MCPサーバの接続/切断

    ツールが遅延ロード(後述)であれば影響はないんだけど、ユーザーが追加したMCPサーバーのツール定義がシステムプロンプト層に入るケースでは、MCPサーバーの再接続でキャッシュが壊れる。 ユーザー操作による再接続じゃなくても、stdioサーバのプロセス終了やHTTPセッションの失効で起こりうる。

  • プラグインの無効/有効

    プラグインといってもMCPサーバを提供するプラグインだけだけど、無効/有効の切り替えで上記MCPの問題が起こる。 skillsやcommands、agents、hooksなどはキャッシュ上層への追記なので安全。

  • ツール全体のdeny

    Bash のような素のツール名や Bash(*)"*" をdenyルールに追加すると、ツール定義(システムプロンプト層)が変わってキャッシュが壊れる。一方、Bash(rm *) のようなスコープ付きdenyや、allow/askルールは、Claudeが見るツールの集合を変えないので安全。

  • コンテキスト圧縮 (/compact)

    会話履歴を要約で置き換えるので、会話レイヤーのキャッシュは再処理になる。 ただし、要約の生成自体は既存のキャッシュを読んで行われ、圧縮後のターンは履歴が短くなるぶん実はむしろ速くなる。

    放置してキャッシュがTTL(後述)で消えた後auto-compactionになるようなケースだと、要約の生成にもキャッシュが聞かないので大分損。

    作業の区切りでキャッシュが効くうちに/compactするのが得策。

  • Claude Codeのアップグレード

    Claude Codeのアップグレードは大抵システムプロンプトやツール定義の更新を含むので、次の起動時に先頭からキャッシュを作り直す。 (更新適用はあくまで再起動時で、セッション途中ではない。)

    さらに、アップグレード後に --resume 付きでClaude Codeを起動して長い会話を再開すると、履歴全体を新しいシステムプロンプトの後ろで読み直すことになり、最も高くつくリクエストになりうる。 --resume を使うなら、 DISABLE_AUTOUPDATER=1 でClaude Codeの自動アップグレードを無効化して、いいタイミングで手動でアップグレードするのが吉。

キャッシュを壊さない操作(安心していいもの)

逆に、「壊しそうで壊さない」操作も知っておくと無駄に身構えずに済む。これらは末尾への追記で済むか、そもそもリクエストに触れない。

  • プロジェクトのファイル編集

    ファイルの内容がコンテキストに入るのはClaude Codeがそれを読んだ時だけで、読み取りは会話の末尾に追記される。 あとからファイルを編集しても、過去読み取った内容がさかのぼって書き換わることはない。 代わりに「ファイルが変わった」という <system-reminder> が末尾に足され、必要ならClaudeが読み直す。

  • CLAUDE.md のセッション途中の編集

    CLAUDE.md はセッション開始時に読み込まれてキャッシュのプロジェクトコンテキスト層に入るんだけど、セッション中に CLAUDE.md を書き換えても意外にキャッシュは壊れない。 これは、書き換えてもClaude Codeが読み込まないから。 つまり裏を返せば、編集してもその場では反映されないということ。 変更がClaude Codeに反映されるのは /clear/compact、再起動のあと。

  • output styleの変更

    これも CLAUDE.md と同じで、セッション途中で変更してもキャッシュは壊さないけど変更も反映されない(次の /clear か再起動で効く)。

  • permission modeの変更

    default↔accept editsのような切り替えはシステムプロンプトもツール定義も変えないので安全。 例外は opusplan 設定でのplanモードで、これは前述のようにモデル切り替えによるキャッシュ破壊になる。

  • skill / command の呼び出し

    指示は呼び出した地点でユーザーメッセージとして末尾に挿入される。それより前は何も変わらない。

  • /recap

    /compact と違い、履歴を置き換えずに要約をコマンド出力として末尾に足すだけなので、キャッシュは無傷。

  • /rewind

    過去のターンへ会話を切り詰めるだけ。 残った履歴はその時点でキャッシュが作られた内容そのものなので、以前のキャッシュエントリにヒットする。

  • サブエージェント

    サブエージェントは独自のシステムプロンプトとツールで別のキャッシュを持って動くので、親のキャッシュは無傷のまま。 ちなみにforkは親のコンテキストをそのまま引き継ぐので、最初のリクエストから親のキャッシュを読める。

ツール検索とMCPツールのキャッシュ

MCPまわりはキャッシュの挙動が直感に反しやすいので、もう少し解説を加える。

挙動を理解するのに重要なポイントは、2026年2月17日にClaude Code v2.2.0でデフォルト有効になったツール検索 (tool search)で、これが有効か無効かで話がまるごと変わる。

ツール検索が有効なとき、MCPツールの定義はセッション開始時にコンテキストに載らず、遅延ロード(deferred)される。 セッション開始時に読み込まれるのはツール名とサーバーの説明だけで、Claude Codeはタスクで必要になったときに初めて ToolSearch で関連するMCPツールを検出し、実際に使うツールだけがコンテキストに入る。 しかもそれは会話レイヤーの末尾への追記だ。だからMCPサーバをいくつ足してもプレフィクスは変わらず、サーバの接続や切断もキャッシュを壊さない。 前述の「MCPサーバの接続/切断」で「ツールが遅延ロード(後述)であれば影響はない」というのは、この仕組みのことを指している。

問題は、ツール検索が無効になる以下のケース。

  • Vertex AIのモデルを使用
    • Bedrockはセーフっぽい
  • ANTHROPIC_BASE_URLLLMゲートウェイ経由でモデルにつなぐ
  • Haikuモデルを使う
  • MCPサーバーに alwaysLoad が設定されている

これらのケースではツール定義がシステムプロンプト層に載り、前述の「MCPサーバの接続/切断」問題が起こる。

ツール検索による遅延ロードの有無は ENABLE_TOOL_SEARCH 環境変数で制御できる。

挙動
未設定 上記無効になるケース以外は遅延ロード。
true 常に遅延ロードのベータヘッダを送る。実際遅延ロードになるかはモデルやプラットフォーム次第
auto ツール定義がコンテキストの10%以内に収まれば事前ロード、超える分だけ遅延ロード
auto:N しきい値を N パーセントに変えた auto(例:auto:5
false 遅延ロード無効


特定のMCPサーバーだけツール検索を介さず常にロードしたいなら、.mcp.json のそのサーバーエントリに alwaysLoad: true を付ける。 ただし事前ロードはコンテキストを食うので、毎ターン必ず使う少数のツールに絞るのがよい。

最後に、CLAUDE.md 編集時の挙動と同様に、MCP設定を編集しても、その時点ではキャッシュは変わらない.mcp.json をいじっても、新しい設定が効くのはあくまで再起動後で、セッションの途中で勝手に反映されたりはしない。 つまり、セッション中にMCP設定を編集してもその場でキャッシュを壊すことはない、ということでもある。

キャッシュの寿命(TTL)

キャッシュされたプレフィクスは、一定時間使われないと失効する。 この時間がTTL。TTLはキャッシュがヒットするたびにリセットされるので、作業し続けている限りキャッシュは生き残る。 会議から帰ってきたあとの最初のターンが遅かったりするのは、TTLによるキャッシュ失効が原因である。

Claude CodeのTTLには5分と1時間の2種類があり、1時間のほうがキャッシュ書き込み料金がかなり割増になる。

それぞれのTTLでのキャッシュ料金(基本入力トークン料金に対する倍率)は以下のとおり。

TTL キャッシュ読み込み料金の倍率 キャッシュ書き込み料金の倍率
5分 0.1倍 1.25倍
1時間 0.1倍 2倍


Claude Codeは認証方法に応じてどちらを使うかを自動で選ぶ。

  • Claudeサブスク(Pro / Maxなど)

    デフォルトでTTLは1時間になる。ただしプランの利用枠を超えてusage creditsで課金される状態になると、自動的に5分に切り替わる。

  • APIキー / 他プロバイダ

    トークン課金なので、デフォルトはキャッシュ書き込みが安い5分。 1時間にしたいなら ENABLE_PROMPT_CACHING_1H=1 を設定する。 逆に常に5分へ固定したいときは FORCE_PROMPT_CACHING_5M=1

キャッシュのスコープ

Claude Codeのキャッシュは実質「マシン × 作業ディレクトリ」単位。 システムプロンプトに作業ディレクトリやプラットフォーム、シェル、OSバージョン、auto-memoryのパスが埋め込まれるため、別のディレクトリで起動したセッションはプレフィクスが食い違い、互いのキャッシュを共有しない。 つまり、同じgitリポジトリのworktreeであっても、作業ディレクトリが違えばキャッシュは別扱いになる。

一方、同じディレクトリで並行して走らせたセッションはプレフィクスが一致するので、互いのキャッシュを読み合える。

逐次のセッションの場合は、起動時のgitリポジトリの状態(ブランチや直近のコミット)まで一致したときにだけ共有される。

キャッシュが効いているか確認する

なんだか最近重い・高い、と感じたら、推測せずに数字を見よう。APIは毎レスポンスで2つのトークン数を返す。

  • cache_creation_input_tokens: 今回キャッシュに書き込んだトークン数
  • cache_read_input_tokens: 今回キャッシュから読み出したトークン数

キャッシュ読み取りが大きく、書き込みが小さい状態が理想だ。 キャッシュ書き込みが多い場合、プレフィクスの何かが変わり続けているサインなので、前述の「キャッシュを壊す操作」を疑うといい。

Claude Codeでは /usage で手軽に確認できる。

まとめ: 速く安く保つコツ

最後に、実践として効くポイントを整理しておく。

  • セッションの冒頭でモデルとeffortを決め、途中で変えない。
  • fast modeを使うならセッションの最初にONにする(途中ほど高い)。
  • コンテキスト圧縮は自動にまかせず、作業の自然な区切りで /compact を自分のタイミングで打つ。
  • 作業中はMCP(遅延ロード無効時のみ)やdeny設定、モデルといった、下位レイヤーのキャッシュを脅かす操作をむやみにしない。

結局のところ、Claude Codeはキャッシュを自動でうまく管理してくれる。 注意すべきは、設定をいじる一部の操作が静かにキャッシュを壊し、その1ターンを遅く・高くしてしまうこと。 プロンプトキャッシングの仕組みを知っていれば、その「壊すタイミング」を自分の都合のいい瞬間に選べる。

キャッシュ読み取りの割合を高く保つちょっとした習慣が、長時間セッションの速度とコストにじわじわ効いてくる

おまけ: Headroomプロキシをかます場合

プロンプトキャッシングやトークン節約に関連して、Headroom というツールに触れておく。

Headroomは、ツール出力やログ、ファイル、RAGチャンクなどをLLMに渡る前に圧縮してトークンを削減するコンテキスト圧縮プロキシで、headroom wrap claude のようにClaude Codeをラップして起動する。

このときHeadroomは ANTHROPIC_BASE_URL を自分のローカルプロキシ(既定で localhost:8787)に向ける。 前述のとおり ANTHROPIC_BASE_URL でLLMゲートウェイを挟むと、Claude Codeは基本的にツール検索を諦めてツール定義を事前ロードしてしまうので、キャッシュ観点ではまずそうに見えるんだけど、Headroomは headroom wrap claude のときに ENABLE_TOOL_SEARCH でツール検索を明示的に有効化してくれるので、遅延ロードが維持されて問題は起きない。

ただしこれは2026年6月8日リリースのHeadroom v0.24.0以降の挙動なので、それ以前のバージョンを使っている場合は遅延ロードが無効になってコンテキストが膨らんだりキャッシュが消えがちになるので注意。

もう一点気をつけたいのが、Headroomの Effort routing(output shaper)機能。 これは、ツール結果を受けて続くだけのターンではモデルのthinking effortを下げ、新しい質問やエラーのときはフルのeffortに戻す、という具合にターンごとにeffortを自動で切り替える仕組み。 出力トークンを減らすには効くが、前述のとおりeffortはキャッシュキーなので、ターンごとにeffortが切り替わるとそのたびにキャッシュが取り直しになり、キャッシュが効きにくくなる懸念がある。 トークン削減とキャッシュ維持がここでトレードオフになりうる、というのは頭の隅に置いておきたい。


参考