#!/usr/bin/env python3 """SessionEnd hook: append one metadata + token-usage line to ~/.claude/log.md.""" import json, sys, pathlib from datetime import datetime try: data = json.load(sys.stdin) except Exception: data = {} ts = datetime.now().strftime("%Y-%m-%dT%H:%M:%S") cwd = data.get("cwd", "?") reason = data.get("reason", "?") sid = data.get("session_id") or "?" sid_short = sid[:8] def find_transcript(): tp = data.get("transcript_path") if tp and pathlib.Path(tp).exists(): return pathlib.Path(tp) if cwd == "?" or sid == "?": return None slug = cwd.replace("/", "-") candidate = pathlib.Path.home() / ".claude" / "projects" / slug / f"{sid}.jsonl" return candidate if candidate.exists() else None def sum_tokens(path): totals = {"input": 0, "output": 0, "cache_read": 0, "cache_write": 0} try: with path.open() as f: for line in f: try: rec = json.loads(line) except Exception: continue if rec.get("type") != "assistant": continue u = rec.get("message", {}).get("usage") or {} totals["input"] += u.get("input_tokens", 0) totals["output"] += u.get("output_tokens", 0) totals["cache_read"] += u.get("cache_read_input_tokens", 0) totals["cache_write"] += u.get("cache_creation_input_tokens", 0) except Exception: pass return totals def fmt(n): if n >= 1_000_000: return f"{n/1_000_000:.1f}M" if n >= 1_000: return f"{n/1_000:.1f}k" return str(n) tpath = find_transcript() if tpath: t = sum_tokens(tpath) total = sum(t.values()) tok_str = ( f"tokens=total:{fmt(total)} " f"in:{fmt(t['input'])} out:{fmt(t['output'])} " f"cache_r:{fmt(t['cache_read'])} cache_w:{fmt(t['cache_write'])}" ) else: tok_str = "tokens=unavailable" line = f"- {ts} | session={sid_short} | cwd={cwd} | reason={reason} | {tok_str}\n" log = pathlib.Path.home() / ".claude" / "log.md" if not log.exists(): log.write_text("# Session Log\n\n") with log.open("a") as f: f.write(line)