Covers both Claude Code and Claude Cowork, plus Cursor if you use it. Extract usage metadata from your local Claude Code data (~/.claude), Claude Cowork sessions (the Claude desktop app’s agent mode) and, when it is installed, Cursor, and view it in one self-contained HTML dashboard. Filter by app, or compare them side by side. If there is no Cursor data, Cursor doesn’t appear anywhere in the dashboard.
Most usage tools only read Claude Code’s ~/.claude folder. Cowork keeps its sessions elsewhere (see Claude Cowork), and this tool reads both. See Cursor for what is read from Cursor.
Live demo (randomly generated sample data)
Records tokens, estimated cost, models, tools, latency, errors, subagents, compactions and activity timing. Prompt and response text is never extracted.
Python 3.10+ and the standard library are all you need: no dependencies, no network calls.
python extract.py # ~/.claude -> out/usage.sqlite + out/csv/*.csv
python build_dashboard.py --open # -> out/dashboard.html
python build_artifact.py # -> out/artifact.html, ready to publish as a claude.ai Artifact
skill/claude-usage-report.skill packages these scripts as a shareable skill. It contains no data; each person who runs it reads their own.
extract.py --no-titles omits auto-generated session titles. --no-cowork skips Cowork; --cowork-dir PATH points at a non-default Cowork folder. --no-cursor skips Cursor, --cursor-dir PATH points at a non-default Cursor folder, and --cursor-usage-csv FILE (repeatable) adds billed cost from a Cursor usage export.
Everything is written to out/, which is gitignored. Treat it as personal data.
Every chart has a table view.
Cowork (the Claude desktop app’s agent mode) doesn’t write to ~/.claude. Its sessions live in %APPDATA%\Claude\local-agent-mode-sessions on Windows and ~/Library/Application Support/Claude/local-agent-mode-sessions on macOS. Each session there has:
.claude/projects/**.jsonl), parsed the same way and tagged with source = coworkaudit.jsonl, the agent’s event log. Only result records (one per finished turn: duration, time to first token, cost, denials) and rate_limit_event records are read, into the cowork_turns and rate_limit_events tables. Message and result text are skipped.local_<id>.json per session. Only an allowlist of fields is read (title, created/last-active time, selected folder, scheduled or interactive). The account email, opening prompt and system prompt in that file are ignored.A session’s project is the first folder you picked for it, or “Cowork: scheduled” / “Cowork: no folder”. Typed Cowork prompts carry no origin tag, so a non-subagent prompt that isn’t a tool result or harness message counts as yours.
Cursor keeps its chat history in a SQLite database, %APPDATA%\Cursor\User\globalStorage\state.vscdb on Windows (~/Library/Application Support/Cursor/User/globalStorage/state.vscdb on macOS). It is opened read-only, and reading it takes a minute or two because the file is large. From it:
source = cursor. The project is the conversation’s workspace folder, or “Cursor: no folder”.cursor_messages. User prompts also go into prompts. Message text, thinking and rich text are never read.~/.cursor/ai-tracking/ai-code-tracking.db: per-commit line counts split by agent, Tab and human, into cursor_commits. Commit messages are skipped.The ItemTable in state.vscdb holds auth tokens and is never read.
Limits:
--cursor-usage-csv. That cost is billed, not estimated, and isn’t split by project.PRICES in extract.py), not a bill. The cost Claude Code stores itself only covers the last process of a resumed session, so it is not used. Cowork does log a per-turn cost, which the dashboard shows next to the estimate as “recorded”.extract.py regularly if you want long-term history. Prompt history (history.jsonl) usually goes back further.PRICES in extract.py when model pricing changes.