Claude Code の Token 消費をプロジェクト別に Recorder に蓄積する (Stop hook)
Stop hook が Claude Code セッション終了時に JSONL transcript を集計して、Input / Output / CacheRead / CacheCreate の 4 種を Recorder に POST するパターン。Claude Code の起動 dir を 1 つの metric prefix に紐付ける設計なので、`System/Code/<app>/Claude/Tokens` に揃えれば自分の DORA メトリクスと同じツリーに並べられます。Anthropic Console では取れないアプリ別 / dir 別のClaude コスト時系列が手に入ります。
このレシピで取得・記録できるもの
Claude Code の Stop hook で、session 終了時に JSONL transcript を集計して Recorder に POST するパターンです。session ごとに 4 つの値を任意の <MyPrefix> 配下に記録します:
<MyPrefix>/Input— 入力 token (素の prompt)<MyPrefix>/Output— 出力 token<MyPrefix>/CacheRead— prompt cache から再利用された token<MyPrefix>/CacheCreate— prompt cache に書き込んだ token
<MyPrefix> は Claude Code を起動する dir 1 つに対して 1 つ命名 します。System/Code/<app>/Claude/Tokens の形に揃えておくと、DORA レシピ で蓄積する Lines や Deploy 回数と同じツリーに並び、Recorder 上で「LOC 増加 vs Token 消費」「Deploy 回数 vs Token 消費」を 1 画面に重ねられます。これは Anthropic Console (API key 単位の Usage) では出せない切り口です。
前提
- Claude Code がローカルにインストール済み
- Recorder のアカウント
jq(集計に使用)
なぜ hook で送るのか
Claude Code のセッション transcript は ローカルにしか存在しません (~/.claude/projects/<encoded-cwd>/<session-id>.jsonl)。各行に message.usage = {input_tokens, output_tokens, cache_creation_input_tokens, cache_read_input_tokens} がタイムスタンプ付きで残っているので、ローカルから直接読んで Recorder に流すのが自然です。GitHub Actions の cron では到達できないデータ源です。
セットアップ手順
1. Recorder の PAT を発行
Settings → API Tokens で発行 → 文字列をその場でコピー → ~/.zshrc 等で export RECORDER_PAT="..." しておきます。
2. 集計対象の dir を事前確認する
Claude Code は launch cwd を / → - で置換して project dir を作ります。集計したい dir で 1 回 Claude Code を起動すると、~/.claude/projects/ の下に対応する dir が作られます。ls して basename を控えます:
ls ~/.claude/projects/
# 例: -Users-me-code-myapps ← この行を控える3. Stop hook script を配置し、対象 dir と metric prefix を反映する
~/bin/post_claude_tokens.sh を作成。case の 2 行だけ自分の値に書き換えれば、残りはそのままで動きます。
#!/usr/bin/env bash
set -euo pipefail
: "${RECORDER_PAT:?env RECORDER_PAT is not set}"
PAYLOAD=$(cat)
TRANSCRIPT=$(echo "$PAYLOAD" | jq -r '.transcript_path')
PROJECT_BASENAME=$(basename "$(dirname "$TRANSCRIPT")")
# ─── ⬇ ここの 2 行だけ自分の環境に書き換える ⬇ ───
case "$PROJECT_BASENAME" in
-Users-me-code-myapps) # ← 手順 2 で確認した dir basename
METRIC_PREFIX="System/Code/myapps/Claude/Tokens" ;; # ← Recorder 上で使う prefix
*)
exit 0 ;;
esac
# ─── ⬆ ここまで ⬆ ───
read -r INPUT OUTPUT CREAD CCREATE <<<"$(jq -s -r '
reduce .[] as $e (
{input:0, output:0, cread:0, ccreate:0};
.input += ($e.message.usage.input_tokens // 0)
| .output += ($e.message.usage.output_tokens // 0)
| .cread += ($e.message.usage.cache_read_input_tokens // 0)
| .ccreate += ($e.message.usage.cache_creation_input_tokens // 0)
) | "\(.input) \(.output) \(.cread) \(.ccreate)"
' "$TRANSCRIPT")"
post() {
local name=$1 value=$2
curl -sS -X POST https://api.recorder.nasebanal.com/api/v1/records \
-H "Authorization: Bearer $RECORDER_PAT" \
-H "Content-Type: application/json" \
-d "{\"name\":\"$name\",\"unit\":\"tokens\",\"data_type\":\"integer\",\"chart_type\":\"line\",\"value\":$value}"
}
post "$METRIC_PREFIX/Input" "$INPUT"
post "$METRIC_PREFIX/Output" "$OUTPUT"
post "$METRIC_PREFIX/CacheRead" "$CREAD"
post "$METRIC_PREFIX/CacheCreate" "$CCREATE"実行権限を付けます:
chmod +x ~/bin/post_claude_tokens.sh集計対象 dir を複数にしたい場合は case 文に arm を追加するだけです。
4. Claude Code の settings に Stop hook を登録
~/.claude/settings.json:
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "bash ~/bin/post_claude_tokens.sh"
}
]
}
]
}
}5. 動作確認
手順 2 で控えた dir で 1 session 動かして終了させ、Recorder の「タグ一覧」に <MyPrefix>/{Input,Output,CacheRead,CacheCreate} が現れていれば成功です。
⚠️ シークレットの取扱い
RECORDER_PATは~/.zshrc等でexportするだけにして、script に直書きしないでください- 漏洩が疑われたら Recorder Settings → API Tokens で失効 → 新規発行 → 環境変数を上書きしてください
- Stop hook は すべての Claude Code session で発火します。
caseにない project は*) exit 0でサイレントに弾く設計なので、未追跡の作業内容が Recorder に紛れ込むことはありません