Claude Code ã®å©çšãã°ã SQLite ã«åã蟌ãã§ API æç®ããã302äžåã ã£ã
Claude Code ãªã©ã®ãµãã¹ã¯ãªãã·ã§ã³ãã©ã³ã§äœ¿ã£ãŠãããšãå®éã«ã©ãã ã䜿ã£ãã®ããèŠããŸããã
ããã§ãããŒã«ã«ã«æ®ã£ãŠããå©çšãã°ãå šéš SQLite ã«åã蟌ã¿ãAnthropic API ã®å ¬åŒåäŸ¡ã§æç®ããŠã¿ãŸããã4ãæåŒ±ã73,548ã¿ãŒã³ã§ API æç®302äžå ã§ããïŒ1 USD = 159åïŒã
䜿ã£ãã®ã¯ phuryn/claude-usageïŒMITïŒããã©ãŒã¯ããŠãèªåçšã«ã¬ãŒãå¶éã®å¯èŠåãªã©ãè¶³ãããã®ã§ãã
ãã®èšäºã§ã¯ãéèšã®æé ãšãéäžã§èžãã å䟡èšç®ã®èœãšãç©ŽãæžããŸããèœãšã穎ã®ã»ãã¯ãæå ã®ãã©ãŒã¯ãç·é¡ã®33%ãèŠèœãšããŠãããšããå®å®³ãåºãã®ã§ãåçš®ã®éèšãæžã人ã«ã¯åœ¹ã«ç«ã€ãšæããŸãã
ãã°ã¯ã©ãã«ããã
Claude Code ã¯äŒè©±ã JSONL ã§ããŒã«ã«ã«æ®ããŸãã
~/.claude/projects/<ãããžã§ã¯ãã®ãã¹ããšã³ã³ãŒããããã£ã¬ã¯ããª>/<session-id>.jsonl
1è¡ã1ã¬ã³ãŒãã§ãtype ã assistant ã®ã¬ã³ãŒãã«èª²é察象ã®ããŒã¯ã³æ°ãå
¥ã£ãŠããŸãã
{
"type": "assistant",
"timestamp": "2026-08-17T10:00:00.000Z",
"cwd": "/path/to/project",
"message": {
"model": "claude-opus-4-8",
"usage": {
"input_tokens": 12,
"output_tokens": 843,
"cache_creation_input_tokens": 5120,
"cache_read_input_tokens": 210344
}
}
}
éèŠãªã®ã¯ããŒã¯ã³ã4çš®é¡ããããšã§ããå ¥åã»åºåã«å ããŠããã£ãã·ã¥ã®æžã蟌ã¿ãšèªã¿åºãã奿 ã§èšé²ãããŸããããšã§èŠãããã«ãéé¡ã®å€§éšåã¯ãã®2ã€ãå ããŸãã
SQLite ã«åã蟌ã
JSONL ã®ãŸãŸéèšããŠãããã®ã§ãããäœåºŠãæ¡ä»¶ãå€ããŠèŠããã®ã§ãããŒãã«ã«èœãšããŸãã
import json, sqlite3
from pathlib import Path
db = sqlite3.connect("usage.db")
db.execute("""
CREATE TABLE IF NOT EXISTS turns (
message_id TEXT PRIMARY KEY,
session_id TEXT,
timestamp TEXT,
model TEXT,
input_tokens INTEGER,
output_tokens INTEGER,
cache_creation_tokens INTEGER,
cache_read_tokens INTEGER,
cwd TEXT
)""")
for fp in Path.home().joinpath(".claude/projects").rglob("*.jsonl"):
for line in fp.open(encoding="utf-8", errors="replace"):
try:
rec = json.loads(line)
except ValueError:
continue
if rec.get("type") != "assistant":
continue
msg = rec.get("message") or {}
u = msg.get("usage") or {}
if not u:
continue
db.execute(
"INSERT OR IGNORE INTO turns VALUES (?,?,?,?,?,?,?,?,?)",
(msg.get("id"), fp.stem, rec.get("timestamp"), msg.get("model"),
u.get("input_tokens", 0), u.get("output_tokens", 0),
u.get("cache_creation_input_tokens", 0), u.get("cache_read_input_tokens", 0),
rec.get("cwd")))
db.commit()
message_id ãäž»ããŒã«ããŠããã®ã¯ãåãã»ãã·ã§ã³ãåã¹ãã£ã³ãããšãã®äºéèšäžãé²ãããã§ãããã°ã¯è¿œèšãããã®ã§ãååã蟌ã¿ã¯æ¥åžžçã«èµ·ããŸãã
éé¡ã«æç®ãã
å䟡ã¯å ¬åŒã®æé衚ã䜿ããŸãã100äžããŒã¯ã³ãããã® USD ã§æã£ãŠãããšèšç®ã楜ã§ãã
PRICING = {
"claude-opus-4-8": {"input": 5.0, "output": 25.0, "cache_read": 0.50, "cache_write": 6.25},
# ... 䜿ã£ãŠããã¢ãã«ãåæãã
}
def calc_cost(model, inp, out, cache_read, cache_write):
p = PRICING.get(model)
if p is None:
return None # â ãããéèŠã0.0 ãè¿ããªã
return (inp * p["input"] + out * p["output"]
+ cache_read * p["cache_read"] + cache_write * p["cache_write"]) / 1_000_000
PRICING ã«ç¡ãã¢ãã«ã§ None ãè¿ããŠããã®ãããã®èšäºã®ããã²ãšã€ã®äž»é¡ã§ããçç±ã¯åŸè¿°ããŸãã
çµæ
73,548ã¿ãŒã³ã436äŒè©±ã33ãããžã§ã¯ãåã®éèšçµæã§ãã
| çš®å¥ | ããŒã¯ã³æ° | éã®å²å | éé¡ã®å²å |
|---|---|---|---|
| å ¥å | 6,203,046 | 0.03% | 0.2% |
| åºå | 83,387,632 | 0.4% | 13.1% |
| ãã£ãã·ã¥èªã¿åºã | 21,235,024,583 | 97.3% | 66.5% |
| ãã£ãã·ã¥æžã蟌㿠| 510,024,816 | 2.3% | 20.2% |
èªåãæã¡èŸŒãã æç€ºã¯ãéé¡ã®0.2%ãããããŸããã§ããã ããã³ãããçãæžãç¯çŽã¯ãéé¡ã®èгç¹ã§ã¯ã»ãŒæå³ããªãã£ãããšã«ãªããŸãã
éé¡ã®3åã®2ã¯ãã£ãã·ã¥ã®èªã¿åºãã§ããå䟡ã¯å ¥åã®10åã®1ã§ãããæµããéã255åããã®ã§é転ããŸãã
äŒè©±ã®äžã®äœçœ®ã§åãããšãããå°ãã¯ã£ããããŸãã
| äŒè©±ã®äžã®äœçœ® | 1ã¿ãŒã³ã®ã³ã¹ã | 1ã¿ãŒã³ãããã®ãã£ãã·ã¥èªã¿åºã |
|---|---|---|
| æåã®10ã¿ãŒã³ | $0.1232 | 49,693 |
| 1000ã¿ãŒã³ç®ä»¥é | $0.3157 | 412,423 |
åã質åã§ããé·ãç¶ããäŒè©±ã®äžã§èããš2.6åããããŸããèªã¿çŽãããã³ã³ããã¹ãã8.3åã«èšããããã§ãã
ïŒ1000ã¿ãŒã³ãè¶ ããäŒè©±ã¯15æ¬ãããªããæ¯çã¯1.7ã27.1åãšã°ãã€ããŸããæé·ã®1æ¬ãé€ããŠãåŸåã¯å€ãããŸããã§ããïŒ
èœãšã穎ïŒå䟡衚ã«ãªãã¢ãã«ã 0 åã«ãããšãéãã«å£ãã
ãããããæ¬é¡ã§ãã
䜿ã£ãŠããããŒã«ã¯ãPRICING ã«ç¡ãã¢ãã«ã 0 å ãšããŠæ±ãå®è£
ã«ãªã£ãŠããŸãããããŒã«ã«ã§åãããŠããã¢ãã«ãä»ç€Ÿã®ã¢ãã«ãæ··ãã£ããšãã«ãClaude ã®å䟡ã§èª²éããªãããã§ããèšèšãšããŠã¯åŠ¥åœã ãšæããŸãã
åé¡ã¯ãæ°ããåºã Anthropic ã®ã¢ãã«ããç¥ããªãã¢ãã«ãã«èŠããããšã§ãã
å®éãããã¢ãã«ã® 15,784ã¿ãŒã³ã»42åããŒã¯ã³ã $0.00 ãšè¡šç€ºãããŠããŸãããæ£ããèšç®ãããš $6,272.75ãå
šã¿ãŒã³ã®21%ãç·é¡ã®33%ã§ããç·é¡ã¯191äžåãšåºãŠããŠãæ£ããã¯302äžåã§ããã
ãã©ãŒã¯ããŠèªåã®éå ·ãšããŠäœ¿ã£ãŠãã以äžãå䟡衚ãçŸå®ã«è¿œãã€ããªããªãéšåã¯èªåã§èŠåŒµããããããŸããããããäžæµä»»ãã«ããŠããã®ãæå ã§ããã
èŠåã¯åºãŸããã ãšã©ãŒãç°åžžçµäºããªããéèšè¡šã« $0.00 ãšäžŠã¶ã ãã§ããèŠãç®ã«ã¯ããã®ã¢ãã«ã¯äœ¿ã£ãŠããªãããã䜿ã£ããç¡æã ã£ããã®ã©ã¡ããã«ããèŠããŸããã
åå ã¯ãã0åã ã£ãããšãããããåãããªãããåã 0 ã§è¡šããŠããããšã§ãããã®2ã€ã¯ãŸã£ããå¥ã®æ å ±ã§ãåè ã¯äºå®ãåŸè ã¯èšæž¬ã®å€±æã§ããåãå€ã§åºåããæç¹ã§ãåãåãåŽããåºå¥ã§ããªããªããŸãã
察çã¯å䟡衚ãžã®è¿œèšã§ã¯ãããŸããã远èšã¯æ¬¡ã®ã¢ãã«ãåºãæ¥ã«ãŸãç ŽããŸããæäœéãæ¬¡ã®ã©ã¡ãããå ¥ããŠãã ããã
unknown = set()
def calc_cost(model, ...):
p = PRICING.get(model)
if p is None:
unknown.add(model)
return None
...
# å®è¡ã®æåŸã«
if unknown:
print(f"warning: å䟡æªå®çŸ©ã®ã¢ãã«ããããŸã: {sorted(unknown)}", file=sys.stderr)
print("ãåèšã¯éå°ã«åºãŠããŸãã", file=sys.stderr)
- æªå®çŸ©ã¢ãã«ãå®è¡çµäºæã«èŠåãã
- éèšè¡šã§ã¯ 0 åã§ã¯ãªã
n/aãšããŠè¡šç€ºããåèšã«æ³šèšãä»ãã
ã©ã¡ããæ°è¡ã§æžã¿ãéããª33%ã®ãããç®ã«èŠããããã«å€ãããŸãã
ããã²ãšã€ã®èœãšã穎ïŒéšåäžèŽã®ãã©ãŒã«ããã¯
åãããŒã«ã«ãå䟡衚ã«å®å šäžèŽããªãã¢ãã«åãæ¥ããšããååã®äžéšãäžèŽããæ¢åã¢ãã«ã®å䟡ã䜿ãåŠçãå ¥ã£ãŠããŸãããäžä»£ãå€ãã£ãŠã系統ã¯åãã ããããšããèãã§ãã
ãããå£ããŸãããããæ°ããã¢ãã«ãæ§äžä»£ã®å䟡ã«è§£æ±ºãããå®éãã50%é«ãéé¡ãåºããŠããŸããã
0 åã®ã»ãã¯ãããããããšæ°ã¥ãäœå°ããããŸãããå°ãé«ãã ãã®æ°åã¯èŠãã ãã§ã¯å€æã§ããŸãããããããã©ãŒã«ããã¯ãåãã圢跡ã¯ã©ãã«ãæ®ããŸããã
ä»ã®ã¢ãã«ã§éé¡ãåã£ãŠããã®ããèšèšãæ£ããã£ãããã§ã¯ãªãããã®äžä»£ã§åäŸ¡ãæ®ã眮ãããŠããããã§ããã
ãã©ãŒã«ããã¯ãæ®ããªãããã©ãŒã«ããã¯ããããšãæ»ãå€ã«å«ããŠãåŒã³åºãåŽããæšå®å€ããšããŠæ±ããããã«ããŠãã ããã
ãŸã 解決ã§ããŠããªãããš
ãã£ãã·ã¥ã®æžã蟌ã¿ã«ã¯æå¹æéã5åã®ãã®ãš1æéã®ãã®ããããå䟡ãéããŸããããããã°ã«ã¯ããŒã¯ã³æ°ããæ®ãããã©ã¡ãã ã£ãããå€å¥ã§ããŸããã
å šéšã5åã ãšä»®å®ãããš302äžåãå šéšã1æéã ãš339äžåã«ãªããŸããå®éã¯æ··ãã£ãŠããã®ã§ãçã®å€ã¯ãã®éã®ã©ããã§ãããã°ãèŠããããããã以äžã¯è©°ããããŸããã§ããã
ãŸãšã
- Claude Code ã®å©çšãã°ã¯ããŒã«ã«ã® JSONL ã«ããã
assistantã¬ã³ãŒãã®usageã«4çš®é¡ã®ããŒã¯ã³ãå ¥ã - éé¡ã®3åã®2ã¯ãã£ãã·ã¥ã®èªã¿åºããå ¥åããŒã¯ã³ã¯0.2%ãããªã
- é·ãç¶ããäŒè©±ã¯1ã¿ãŒã³ããã2.6åããããåºåãã§äŒè©±ãåãã®ãå¹ã
- å䟡ãåŒããªãã¢ãã«ã 0 åã«ãããšãéèšã¯éãã«å£ããããäžæãã 0 ã§è¡šããªãããš
- ãã©ãŒã¯ããŠäœ¿ãéå ·ã¯ãå€éšã®å€åã§è ãéšåïŒå䟡衚ãªã©ïŒãèªåã§èŠåŒµã
åãããšãèªåã®ãã°ã§ããããæ¹ãžã
äžæµã¯ phuryn/claude-usageïŒMITïŒã§ãããã®èšäºã®æ°åã¯ãããããã©ãŒã¯ãã chiisanasoft/claude-usage ã§åºããŠããŸãããã©ãŒã¯åŽã«ã¯ããã®èšäºã§æžãã察çââå䟡ãåŒããªãã¢ãã«ã® n/a 衚瀺ãšå®è¡åŸã®èŠåãclaude-sonnet-5 / claude-opus-5 ã®æç€ºãšã³ããªââãå
¥ããŠãããŸãã
ãªã claude-fable-5 ã®å䟡ã¯ãäžæµã§ã¯ãã§ã«è¿œå æžã¿ã§ããæ¬æã® 33% ã®åãããŒãã¯ãç§ãå€ããã©ãŒã¯ã䜿ãç¶ããŠããããã«èµ·ãããã®ã§ãäžæµã®ææ°çã§ã¯èµ·ããŸããã
éé¡ã®å èš³ããäŒè©±1æ¬ãããã®åãïŒã³ã¹ãã®66%ã¯äžäœ6.7%ã®äŒè©±ã䜿ã£ãŠããŸããïŒã«ã€ããŠã¯ãnote ã®ã»ãã«æžããŠããŸãããã²ã芧ãã ããã
Discussion