Go back

Claude Codeのトークン、どこで溶けているのか。公式の解説を読んで運用を見直した

Posted on:

同じような作業をしているのに、日によってトークン消費がぜんぜん違う。ずっとその理由がわかっていませんでした。

Anthropicが公開しているMaximizing the value of your Claude Code sessionsを読んで、ようやく腑に落ちたので整理しておきます。

きっかけ

Claude Codeを使っていると、体感でしかコストを把握できません。長く話し込んだ日は高い、という程度の理解でした。

ところが公式の解説を読むと、コストが増える場所はかなりはっきりしていました。しかも、その多くはセッションの始め方と終わり方で決まります。モデルを変えるより先に、運用のほうを直すべきでした。

コストを決めているのは単価ではない

価格を左右する要素は3つあります。モデル、入力と出力のトークン、そしてプロンプトキャッシュです。

出力トークンは入力トークンのおよそ5倍のコストがかかります。ただ、実務で効いてくるのは3つ目のキャッシュのほうでした。

直前のリクエストと同じトークン列で始まるリクエストは、キャッシュから読み込まれます。新しく増えた部分だけが通常価格になるので、差はかなり大きくなります。

問題は、このキャッシュが意外と簡単に無効化される点です。

  • /model/effort の変更
  • ファストモードの切り替え
  • /compact の実行
  • 時間経過(1時間、APIキー利用なら5分)

会話の途中でモデルを切り替える操作は、それまでの履歴をもう一度フル価格で送り直すのと変わりません。モデルとエフォートレベルは、作業を始める前に決めておくのが正解でした。

毎ターン、履歴全部を送っている

もうひとつ大きいのが、コンテキストの中身と、それを何ターン抱えたままにするかです。

ツール定義、システムプロンプト、CLAUDE.md、セッション中に読み込んだファイル、実行したコマンドの出力。これらはすべてコンテキストに残り、ターンごとに再送されます。CLAUDE.mdは地図であって、マニュアルではないと以前書きましたが、地図であっても毎ターン再送されている以上、サイズそのものがそのままコストに直結します。

長いセッションが高くつくのは、賢く考えているからではなく、同じ履歴を何度も送り直しているからでした。

セッション開始時に /context を見る

新しいセッションで一度だけ /context を実行すると、何が積まれているかがわかります。スラッシュコマンドを棚卸ししたときにも触れたコマンドですが、CLAUDE.md が育ちすぎていないか、使っていないMCPサーバーのツール定義が乗っていないか。ここを削るだけで、以降の全ターンが軽くなります。

ファイルは @メンション で渡す

「src/foo.tsを読んで」とファイル名を書くと、Claudeが探して読む動作が入ります。

@ でメンションすればファイルがメッセージに直接添付されるため、Read呼び出しや探索のコストを省けます。地味ですが、毎回発生する差です。

出力の多いコマンドを会話に残さない

これが個人的に一番刺さりました。テストやビルドの長いログは、実行したターンだけの話ではありません。

コマンド出力は会話に残り、セッションが終わるまで毎ターン送られ続けます。静かにするフラグを付けるか、サブエージェント経由で実行して結果だけ受け取る形にします。

区切りで /clear、離席前に /compact

タスクが変わったら /clear を打ちます。前のタスクの文脈を次のタスクに持ち込む理由はありません。

離席する前には /compact を打っておきます。キャッシュは1時間で切れるので、生きているうちに要約したほうが、戻ってきてから全履歴を読み直すより安く済みます。

不要なターンだけを消したいときは /rewind が向いています。こちらはキャッシュを壊しません。

サブエージェントに逃がす

サブエージェントはメインとは別のコンテキストで動き、結果だけを親に返します。

そのぶん独自のターンとコストは発生しますが、本筋の会話に残す必要のない調査や、大量の出力を伴う作業を切り出す先としては有効です。エージェントチームの運用メモで書いたとおり、チームメイトがリーダーの会話履歴を引き継がないのも同じ構造でした。

読んでみて変わったこと

これまでコストの話題になると、モデルを下げるかどうかという発想になりがちでした。

実際に効くのは、送っているコンテキストの量と、キャッシュを壊さない操作の順番です。どちらもモデルの選択とは別のレイヤーにあります。

セッションを「会話」ではなく「毎ターン全部を再送している状態」として見ると、/clear を打つ回数が自然と増えました。

まとめ

  • モデルとエフォートレベルは開始前に決める。途中変更はキャッシュを壊す
  • 新しいセッションで /context を確認し、不要な積載を削る
  • ファイル参照は @メンション、うるさいコマンドはサイレント化かサブエージェント
  • タスクの区切りで /clear、離席前に /compact、ターン削除は /rewind

参考

https://claude.com/blog/maximizing-the-value-of-your-claude-code-sessions

https://redamoon.net/log/post/000131/

https://redamoon.net/log/post/000136/