Closed6

Claude Maxお得 and DuckDB便利

trysmrtrysmr

Claude CodeはMaxを契約すると使い放題になるんだけど、/cost してもどれだけコストかかったのか分からないのでお得かどうか判断できなかったけど、/logout するとTotal costが出力されることが判明した。

Total cost: $13.32
Total duration (API): 44m 27.45
Total duration (wall): 2h 6m 53.1s
Total code changes: 1418 lines added, 209 lines removed
Token usage by model:
    claude-3-5-haiku: 92.7k input, 3.8k output, 0 cache read, 0 cache write
    claude-3-7-sonnet: 531 input, 106.7k output, 27.2m cache read, 922.5k cache write

自分の使い方で$13.32。これ毎日使ってたらめっちゃお得やん。

trysmrtrysmr

~/.claude/projectsにプロジェクト(Claude Codeを実行したディレクトリ)ごとにディレクトリが作られ、その下にjsonl形式で利用履歴のようなファイルが作成される。このjsonlにcostUSDという項目がありこれを集計すれば /logout しなくてもClaude Maxでもコストがわかる(はず)。

DuckDBで集計する

SELECT SUM(costUSD) FROM read_json('~/.claude/projects/*/*.jsonl');

詳細

プロジェクト(ディレクトリ)、金額(ドル)、入力トークン、出力トークン

  SELECT regexp_replace(cwd, '^.*/', '') AS project
       , '$ ' || SUM(costUSD) AS total_cost
       , SUM(message.usage.input_tokens) AS input_tokens
       , SUM(message.usage.output_tokens) AS output_tokens
    FROM read_json('~/.claude/projects/*/*.jsonl')
   WHERE costUSD IS NOT NULL
GROUP BY ROLLUP (project) -- 合計
ORDER BY project
;
trysmrtrysmr

ChatGPT o3とやりとりしながら書いてもらった集計するシェルスクリプト

claude_cost.sh
#!/usr/bin/env bash
# summarize_costUSD_by_project_date.sh  (portable: BSD + GNU)
# -------------------------------------------------------------------
# 出力列: project  date  costUSD  input_tokens  cache_creation_input_tokens
#                         cache_read_input_tokens  output_tokens
# 最終行: TOTAL <空白> Σ Σ Σ Σ Σ
# -------------------------------------------------------------------
set -euo pipefail

BASE="${1:-${HOME}/.claude/projects}"      # projects ルート
BLANK=" "                                  # TOTAL 行の日付列用の空白 1 文字
tmp=$(mktemp) ; trap 'rm -f "$tmp"' EXIT

# --- helper --------------------------------------------------------------
epoch_mtime() {           # -> epoch秒
  if stat -c %Y /dev/null &>/dev/null; then  # GNU
    stat -c %Y "$1"
  else                                       # BSD/macOS
    stat -f %m "$1"
  fi
}

ymd_from_epoch() {        # epoch -> YYYY-MM-DD (Asia/Tokyo)
  if date -d @0 +%F &>/dev/null; then        # GNU
    TZ=Asia/Tokyo date -d "@$1" +%F
  else                                       # BSD/macOS
    TZ=Asia/Tokyo date -r  "$1" +%F
  fi
}
# ------------------------------------------------------------------------

# 1) project・date・5 指標を TSV で平坦化
find "$BASE" -type f -name '*.jsonl' -print0 |
  while IFS= read -r -d '' f; do
    proj=${f#*/projects/}; proj=${proj%%/*}
    ymd=$(ymd_from_epoch "$(epoch_mtime "$f")")

    jq -r '[.costUSD // 0,
            .message.usage.input_tokens // 0,
            .message.usage.cache_creation_input_tokens // 0,
            .message.usage.cache_read_input_tokens // 0,
            .message.usage.output_tokens // 0] | @tsv' "$f" |
      awk -v p="$proj" -v d="$ymd" -v OFS='\t' '{print p, d, $0}'
  done >"$tmp"

# 2) 集計 → ソート → ヘッダー+TOTAL 行
{
  # ヘッダー
  printf 'project\tdate\tcostUSD\tinput_tokens\tcache_creation_input_tokens\tcache_read_input_tokens\toutput_tokens\n'

  # 集計(awk は POSIX だけで書く)
  awk -F'\t' '
    { key=$1 FS $2
      cost[key] += $3
      inp [key] += $4      # ← 予約語 in を避け inp
      cci [key] += $5
      cri [key] += $6
      out [key] += $7 }
    END {
      for (k in cost) {
        split(k, a, FS)
        printf "%s\t%s\t%.10g\t%.10g\t%.10g\t%.10g\t%.10g\n",
               a[1], a[2], cost[k], inp[k], cci[k], cri[k], out[k]
      }
    }' "$tmp" |
  sort -k1,1 -k2,2 |
  awk -F'\t' -v blank="$BLANK" '{
          print;
          TC+=$3; TI+=$4; TCC+=$5; TCR+=$6; TO+=$7
       }
       END {
          printf "TOTAL\t%s\t%.10g\t%.10g\t%.10g\t%.10g\t%.10g\n",
                 blank, TC, TI, TCC, TCR, TO
       }' OFS='\t'
}
trysmrtrysmr

プロジェクト(ディレクトリ)、モデル、金額(ドル)、入力トークン、出力トークン

  SELECT regexp_replace(cwd, '^.*/', '') project
       , message.model
       , '$ ' || SUM(costUSD) total_cost
       , SUM(message.usage.input_tokens) input_tokens
       , SUM(message.usage.output_tokens) output_tokens
    FROM read_json('~/.claude/projects/*/*.jsonl')
   WHERE costUSD IS NOT NULL AND message.model IS NOT NULL AND message.model <> '<synthetic>'
GROUP BY GROUPING SETS ((project, message.model), ())
ORDER BY project ASC, message.model ASC
;

プロジェクト(ディレクトリ)、金額(ドル)、入力トークン、出力トークン

  SELECT regexp_replace(cwd, '^.*/', '') project
       , '$ ' || SUM(costUSD) total_cost
       , SUM(message.usage.input_tokens) input_tokens
       , SUM(message.usage.output_tokens) output_tokens
    FROM read_json('~/.claude/projects/*/*.jsonl')
   WHERE costUSD IS NOT NULL AND message.model IS NOT NULL AND message.model <> '<synthetic>'
GROUP BY ROLLUP(project)
ORDER BY project ASC
;
trysmrtrysmr

$HOME/.claude/projects/*/*.jsonlの利用履歴ファイルにあったcostUSDが1.0.9からなくなっている模様。残念。

このスクラップは3ヶ月前にクローズされました