Back to Blog
Claude Codeトークン使用量コスト分析ログ分析スプレッドシート

Claude Codeの使用量をログから分解——コストが溜まる場所を探る

Claude Codeの使用量を自分のログから分解してみた——コストはどこに溜まるのか

Anthropic社のコーディング支援ツール「Claude Code」は、セッション(1回の作業のまとまり)の履歴をローカルPCにJSONL形式(1行に1件のJSONデータを書いたテキストファイル)で保存しています。各応答には、処理したトークン(LLMが扱う文字量の単位)の使用数も記録されています。つまり、使用量は体感に頼らなくても、手元のログから数値で確認できます。

料金や利用上限の消費は、請求額や上限到達のメッセージで初めて気づくケースが多いと見られます。「なぜ今週はこんなに減りが早いのか」という疑問に、体感だけで答えるのは難しいものです。

本記事では、ログを集計して使用量の内訳を分解する手順と、そこから見えた傾向を整理します。ExcelやGoogleスプレッドシートを日常的に使っている方なら、同じ手順で再現できる内容です。

分析の前提条件

項目 内容
分析期間 【YYYY/MM/DD〜YYYY/MM/DD(○日間)】
セッション数 【○件】
応答レコード数(重複除去後) 【○件】
総トークン数 【○トークン】
利用モデル 【モデル名と各レコード数】
利用環境 【OS、利用プラン(サブスクリプション/API従量課金)】

※【】内は執筆時に実データへ差し替える項目です。以降の本文でも、実測値が入る箇所は同じ表記にしています。

Claude Codeのログには何が記録されているのか?

保存場所とファイル構成

ログは、ホームディレクトリ配下の ~/.claude/projects/ に保存されます。Windowsでは C:\Users\ユーザー名\.claude\projects\ にあたります。構成は次のとおりです。

  • プロジェクト単位のフォルダ:作業したディレクトリのパスをもとにした名前のフォルダが作られます。
  • セッション単位のファイル:フォルダの中に、セッションIDを名前とする .jsonl ファイルが1つずつ作られます。

バージョンによって細部が異なる可能性があるため、実際のフォルダ構成は手元の環境で確認してください。また、古いセッションは一定期間(既定値は設定で変わります)を過ぎると自動削除される仕様があります。長期の推移を見たい場合は、定期的にCSVへ書き出して保存しておく運用が前提になります。

使用量に関わる主な項目

アシスタントの応答にあたるレコードには、usage(使用量)という項目が含まれます。集計で使うのは主に次の4種類です。

項目名(ログ上) 意味
input_tokens キャッシュを使わずに通常どおり入力として処理されたトークン
output_tokens モデルが生成した出力(回答、コード、ツール呼び出しの指示など)
cache_creation_input_tokens 会話内容をキャッシュに新しく書き込んだトークン
cache_read_input_tokens すでにキャッシュにある内容を再利用して読み取ったトークン

キャッシュの位置づけと単価の違い

キャッシュ(プロンプトキャッシュ)とは、直前までの会話内容をモデル側に一時保存し、次の送信時に再利用して処理を効率化する仕組みです。Claude Codeは、やり取りのたびに過去の会話を含めて送信する性質があるため、この仕組みが前提になっています。

単価は、通常の入力トークンを基準にすると、おおむね次のような倍率関係にあります。

  • キャッシュ読み取り:通常入力より大幅に安い(目安として0.1倍程度)
  • キャッシュ作成:通常入力よりやや高い(目安として1.25倍程度)
  • 出力:通常入力より高い(目安として5倍程度)

倍率はモデルやキャッシュの保持時間、料金改定によって変わり得ます。正確な数値は必ずAnthropic公式の料金ページで確認してください。

集計の軸にできる項目

使用量以外にも、次の項目が集計の軸として使えます。

  • timestamp:応答の日時。日別・時間帯別の集計に使います。
  • message.model:使用したモデル名。モデル別の単価計算に必須です。
  • sessionId:セッションの識別子。セッション別の集計に使います。
  • cwd(作業ディレクトリ)やプロジェクトフォルダ名:プロジェクト別の集計に使います。
  • message.id / requestId:応答の識別子。重複の除去に使います。

ログをスプレッドシートで集計するにはどうすればよいのか?

JSONLをCSVに変換する

方法は2つあります。

方法1:既存の集計ツールを使う Claude Codeのログを集計するコミュニティ製のツールが公開されています(「ccusage」など)。コマンド1つで日別・セッション別の集計を出せるため、まず全体像をつかむ目的には手軽です。ただし、どの項目をどう集計しているかはツールごとに異なります。細かい分解が必要なら、自前で変換するほうが融通が利きます。

方法2:スクリプトで変換する Pythonを使える環境なら、次のような短いスクリプトでCSVを作れます。

import csv
import json
from pathlib import Path

root = Path.home() / ".claude" / "projects"
records = {}  # 重複除去用:(message.id, requestId) をキーにする

for path in root.rglob("*.jsonl"):
    project = path.relative_to(root).parts[0]
    with open(path, encoding="utf-8") as f:
        for line in f:
            try:
                rec = json.loads(line)
            except json.JSONDecodeError:
                continue  # 書き込み途中の壊れた行は飛ばす
            msg = rec.get("message")
            if not isinstance(msg, dict):
                continue
            usage = msg.get("usage")
            if not usage:
                continue
            row = {
                "timestamp": rec.get("timestamp"),
                "session_id": rec.get("sessionId"),
                "project": project,
                "model": msg.get("model"),
                "input": usage.get("input_tokens", 0),
                "output": usage.get("output_tokens", 0),
                "cache_creation": usage.get("cache_creation_input_tokens", 0),
                "cache_read": usage.get("cache_read_input_tokens", 0),
            }
            key = (msg.get("id"), rec.get("requestId"))
            if key == (None, None):
                key = (path.name, line[:80])  # IDが無い場合の代替キー
            records[key] = row  # 同じキーは後勝ちで上書き

with open("claude_usage.csv", "w", newline="", encoding="utf-8-sig") as f:
    writer = csv.DictWriter(f, fieldnames=list(next(iter(records.values())).keys()))
    writer.writeheader()
    writer.writerows(records.values())

出力時の文字コードを utf-8-sig にしているのは、Excelで開いたときの文字化けを防ぐためです。ログの項目名や構造はバージョンで変わる可能性があるため、動かない場合は実際のJSONLを1行開いて項目名を確認してください。

スプレッドシートに取り込み、ピボットテーブルで集計する

  1. CSVをExcelまたはGoogleスプレッドシートで開きます。
  2. timestamp から日付列を作ります(例:=INT(A2) や =LEFT(A2,10)。形式に合わせて調整してください)。
  3. 「挿入」→「ピボットテーブル」を選びます。ピボットテーブルとは、項目別の集計表を、ドラッグ操作で作れる機能です。
  4. 行に「日付」または「session_id」、値に4種類のトークン列(合計)を置きます。

これで日別・セッション別の使用量が一覧できます。行を「model」に変えれば、モデル別の内訳も出せます。

概算コストを出す計算列

別シート(例:「単価」シート)に、モデル別の単価(100万トークンあたり)を入力しておきます。

モデル 入力 出力 キャッシュ作成 キャッシュ読み取り
【モデル名】 【公式料金ページの値】 【同左】 【同左】 【同左】

そのうえで、データシートに次のような計算列を追加します。単価の位置は、実際のシートに合わせて読み替えてください。

=( E2*VLOOKUP(D2,単価!A:E,2,FALSE)
 + F2*VLOOKUP(D2,単価!A:E,3,FALSE)
 + G2*VLOOKUP(D2,単価!A:E,4,FALSE)
 + H2*VLOOKUP(D2,単価!A:E,5,FALSE) ) / 1000000

単価は必ず公式の料金ページで確認し、改定のたびに「単価」シートだけを更新する形にしておくと保守が楽です。サブスクリプションプランの場合、この金額は実際の請求額ではなく、「API従量課金で換算した場合の目安」と位置づけられます。

集計時に起こりやすい誤差

  • 重複レコード:1回の応答がログ上で複数行に分かれて記録される場合があります。その場合、重複を除かないとトークン数が実際より大きく出ます。どの行を採用するか(最初か最後か)で出力トークン数が変わる可能性もあるため、数件を目視で確認しておくと安全です。
  • 中断セッション:途中で中断したセッションは、使用量が最後まで記録されていない場合があります。
  • サブエージェントなどの別ファイル:並行して動く処理が別のファイルに記録される構成の場合、取りこぼしに注意が必要です。
  • ログの自動削除:保持期間を過ぎたセッションは集計できません。

これらを踏まえると、集計値は「厳密な請求額」ではなく「傾向を見るための推計値」として扱うのが妥当と言えます。

トークンの種類別に見ると、どこに使用量が偏っているのか?

構成比の可視化

ピボットテーブルで4種類のトークンの合計を出し、円グラフか積み上げ棒グラフにします。日別の積み上げ棒グラフにすると、どの日にどの種類が増えたかも追えます。

今回の分析結果は次のとおりです。

種類 トークン数 トークン構成比 概算コスト コスト構成比
入力 【○】 【○%】 【○】 【○%】
出力 【○】 【○%】 【○】 【○%】
キャッシュ作成 【○】 【○%】 【○】 【○%】
キャッシュ読み取り 【○】 【○%】 【○】 【○%】

キャッシュ読み取りが大半を占めるか

Claude Codeは毎ターン、過去の会話をまとめて再送します。その大部分はキャッシュ経由で処理されるため、キャッシュ読み取りがトークン数の大半を占める構成になりやすいと見られます。実測では、キャッシュ読み取りの比率は【○%】でした。

トークン比率とコスト比率は一致しない

数が多い種類が、必ずしも高コストとは限りません。仕組みを理解するために、次の仮の計算例(実測値ではありません)を見てください。単位は万トークン、単価倍率は「入力=1、出力=5、キャッシュ作成=1.25、キャッシュ読み取り=0.1」と仮定します。

種類 トークン数 構成比 入力換算コスト コスト構成比
入力 1 約0.2% 1 約1%
出力 2 約0.4% 10 約12%
キャッシュ作成 20 約3.8% 25 約29%
キャッシュ読み取り 500 約95.6% 50 約58%

この例では、トークン数の95%超を占めるキャッシュ読み取りも、コストでは6割弱にとどまります。出力は0.4%のトークン数で1割強のコストを占めます。単価の高い出力やキャッシュ作成は、量が少なくてもコストへの寄与が相対的に大きくなる場合があると見られます。

実測のコスト構成でどの種類が最大だったかは【実データで記載】です。トークン数だけを見て「キャッシュ読み取りを減らせばよい」と判断するのは早計で、必ず単価を掛けた比率とセットで見る必要があります。

なぜ長いセッションほどコストが膨らみやすいのか?

会話全体が毎回再送される仕組み

LLMは、前のやり取りを内部に記憶しているわけではありません。そのため、新しい指示を送るたびに、過去の会話全体がコンテキスト(モデルが一度に参照する情報の範囲)として再送されます。

10ターン目の送信には1〜9ターン目の内容が含まれ、50ターン目の送信には1〜49ターン目の内容が含まれます。ターンが進むほど1回あたりの処理量が増え、累積では加速度的に増える構造です。キャッシュで単価は抑えられても、量そのものは増え続けます。

ターン数と累積トークン数の関係

セッションごとに「応答回数(ターン数)」と「累積トークン数」を集計し、散布図にします。ピボットテーブルでセッション別の件数とトークン合計を出し、それをグラフ化すれば作れます。

今回のデータでは、ターン数が【○】を超えるセッションで、1ターンあたりの平均トークン数が【○倍】になっていました。【散布図を挿入。近似曲線が直線より上に反るかを確認】

コンテキストが肥大化する要因

コンテキストを押し上げる要因として、主に次の3つが考えられます。

  • 長いファイルの読み込み:大きなファイルを読み込むと、その内容が以降のすべてのターンに含まれ続けます。
  • ツール実行結果の出力:テストやビルドの長いログ出力が会話に積み上がります。
  • 繰り返しの修正指示:「やり直し」のたびに、失敗した試行の履歴も残ります。

区切る・要約して引き継ぐ

話題が変わった時点でセッションを新しくする、または要約して引き継ぐことで、再送される量を抑えられる可能性があります。Claude Codeには、会話を要約して圧縮するコマンドや、会話をリセットするコマンドが用意されています。使い方は公式ドキュメントで確認してください。

ただし、区切ると過去の文脈が失われ、改めて説明し直すコストが発生します。区切るタイミングは、コストと作業の連続性のバランスで決まる問題と言えます。

作業内容によって使用量はどれくらい違うのか?

作業タイプ別の比較

セッションを、次のような作業タイプに分類して比較します。

  • 新規実装
  • バグ修正
  • リファクタリング(動作を変えずにコードを整理する作業)
  • 調査・質問

分類は、セッションの最初の指示文を読んで手作業でラベル付けし、スプレッドシートに「作業タイプ」列を追加する方法で行いました。ピボットテーブルでラベル別に集計した結果は次のとおりです。

作業タイプ セッション数 平均ターン数 平均トークン数 平均概算コスト
新規実装 【○】 【○】 【○】 【○】
バグ修正 【○】 【○】 【○】 【○】
リファクタリング 【○】 【○】 【○】 【○】
調査・質問 【○】 【○】 【○】 【○】

探索を伴う作業と読み取りトークン

コードベース全体を探索する作業では、多数のファイルを読み込むためにコンテキストが大きくなり、キャッシュ読み取りやキャッシュ作成が増えやすいと見られます。リファクタリングや「どこに原因があるか分からないバグ修正」は、この傾向が出やすい作業と位置づけられます。実測では【傾向が出たか/出なかったかを記載】でした。

平均コストが高いセッションの共通点

1回あたりの平均コストが上位のセッションを抜き出し、共通点を探しました。確認する観点は次のとおりです。

  • ターン数が多いか
  • 大きなファイルや長い出力を扱っているか
  • 同じ修正指示が繰り返されていないか
  • 途中で話題が変わっていないか

上位【○件】に共通していた点は【実データで記載】でした。

限界

作業タイプの分類は手作業のため、主観が入ります。1つのセッションで実装と調査が混在する場合も多く、分類の境界は曖昧です。したがって、この比較は厳密な

Share:
View all posts