Track your AI coding-assistant usage across every machine β and own the data.
Each machine pushes a single JSON file to a git repo you control. Pull from anywhere to see a merged heatmap, stats table, and cost breakdown across Claude Code, Codex, and Cursor.
- π One picture of everything β Claude Code + Codex + Cursor, merged across all your machines.
- π You own the data β it lives in a git repo you create. No accounts, no telemetry, no third-party servers.
- π No API tokens for sync β uses your local
git, so whatever auth already works in your terminal (SSH keys, credential manager) just works. - β‘ Zero-setup preview β run
npx aitrack show --tuiand see your local usage before configuring anything. - π° Real cost estimates β per-model pricing applied to Claude Code token + cache usage.
Synced via git: Claude Code, Codex (OpenAI). Cursor is read locally on demand and never written to your repo (see Where data comes from).
A live terminal table (aitrack show --tui) β same data also renders to a PNG heatmap via aitrack show:
βββββββββββββββ¬βββββββ¬βββββββββ¬βββββββββ¬βββββββββ¬ββββββββββββ¬ββββββββββ¬βββββββββββββ
β Provider β Days β Input β Output β Total β Est. cost β Streak β Peak month β
βββββββββββββββΌβββββββΌβββββββββΌβββββββββΌβββββββββΌββββββββββββΌββββββββββΌβββββββββββββ€
β Claude Code β 28 β 184.2M β 1.4M β 185.6M β $142.80 β 12 / 12 β May 2026 β
β Codex β 64 β 612.0M β 3.1M β 615.1M β $318.40 β 0 / 9 β Apr 2026 β
βββββββββββββββΌβββββββΌβββββββββΌβββββββββΌβββββββββΌββββββββββββΌββββββββββΌβββββββββββββ€
β TOTAL β 92 β 796.2M β 4.5M β 800.7M β $461.20 β β β β β
βββββββββββββββ΄βββββββ΄βββββββββ΄βββββββββ΄βββββββββ΄ββββββββββββ΄ββββββββββ΄βββββββββββββ
Today at a glance (aitrack usage today):
βββββββββββββββ¬βββββββββ¬ββββββββββββββββββββ¬βββββββββ
β Provider β Tokens β Model β Price β
βββββββββββββββΌβββββββββΌββββββββββββββββββββΌβββββββββ€
β Claude Code β 31.5M β claude-opus-4-8 β $25.38 β
β Claude Code β 827.0K β claude-sonnet-4-6 β $0.47 β
β Codex β 12.4M β gpt-5-codex β $6.40 β
βββββββββββββββΌβββββββββΌββββββββββββββββββββΌβββββββββ€
β TOTAL β 44.7M β β $32.25 β
βββββββββββββββ΄βββββββββ΄ββββββββββββββββββββ΄βββββββββ
Preview instantly β no setup required:
npx aitrack show --tui # stats table from local Claude/Codex (+ Cursor if available)
npx aitrack usage today # today's usage, per provider + model
npx aitrack show # heatmap PNG from the same local-first readYour local data is staged at ~/.config/aitrack/pending/data/ so a later init/sync can adopt it into your repo.
Then, to sync across machines:
# 1. Create an EMPTY git repo (no README/license) β e.g. github.com/new β "aitrack-data"
# 2. Configure + clone it locally:
npx aitrack init
# 3. Push this machine's data:
npx aitrack sync
# 4. View everything, from any machine:
npx aitrack showinit asks for your repo's remote URL (SSH or HTTPS β whatever you normally use) and clones it to ~/.config/aitrack/repo/. sync writes data/{your-hostname}.json and pushes it. show always reads fresh local Claude/Codex data, so you never need to sync first just to preview.
Run aitrack init once per machine with the same repo URL, then aitrack sync on each. Every machine writes its own data/{hostname}.json, so there are no merge conflicts.
| Command | What it does |
|---|---|
aitrack init |
Interactive setup β provide your repo URL and clone it locally |
aitrack sync |
Read local data, write it to the cloned repo, and push |
aitrack show |
Merge all sources and render a heatmap PNG (add --tui for a terminal table) |
aitrack usage today |
Today's usage as a table: provider / tokens / model / price |
aitrack usage week |
Rolling 7-day usage table |
aitrack usage month |
Rolling 30-day usage table |
aitrack usage year |
Current calendar-year usage table |
aitrack usage all |
All-time usage table |
aitrack recompute-costs |
Refresh costs: re-read local JSONL; reprice other machines from stored cache |
show flags: --tui (terminal table instead of PNG), --all (single merged heatmap), --dark (dark mode), --no-cursor (skip Cursor), --no-open (don't auto-open the PNG), -o <path> (custom output path), --year <year> (filter to one calendar year). --no-cursor also works on every usage subcommand.
~/.config/aitrack/
βββ config.json # repo URL + optional machineId
βββ pending/
β βββ data/ # staged machine JSON before init/sync
β βββ my-pc.json
βββ repo/ # local clone of your data repo
βββ data/
βββ my-pc.json
βββ work-laptop.json
- Sync uses a local git clone at
~/.config/aitrack/repo/with your existing git credentials β ordinary pulls and pushes. show(PNG or--tui) always reads fresh local Claude/Codex JSONL on the current machine and merges in other machines' synced files. Nosyncneeded to preview.- Before
init, local usage is staged in~/.config/aitrack/pending/data/and adopted on the nextinit/sync. - Cursor is loaded only on the current machine: aitrack reads
cursorAuth/accessTokenfrom Cursor's localstate.vscdb, then calls Cursor's own CSV usage export over HTTPS. The token is used solely for that request β it is never written to your repo or sent anywhere else. Use--no-cursorto skip it. - Heatmap intensity anchors on the 90th-percentile day rather than the absolute max, so one huge day doesn't flatten the rest of the year.
Claude Code cost is an API-equivalent estimate from per-model pricing and token/cache usage, keyed by Claude API model id with the date suffix stripped (see src/readers/claude.ts). Cursor and Codex local-session cost are left unknown because their local data doesn't expose a reliable all-history cost. If stored costs are missing or pricing changed, run aitrack recompute-costs.
Stored at ~/.config/aitrack/config.json:
{
"repoUrl": "git@github.com:your-username/aitrack-data.git",
"machineId": "work-laptop"
}machineId is optional β without it, sync uses your OS hostname as the filename. Set a stable name during init if your hostname might collide across machines or change after a reinstall. Existing hostname-based files keep working when read.
| Provider | Source |
|---|---|
| Claude Code | ~/.claude/projects/**/*.jsonl or $XDG_CONFIG_HOME/claude/projects/**/*.jsonl |
| Codex | ~/.codex/sessions/*.jsonl or $CODEX_HOME/sessions/*.jsonl |
| Cursor (show only) | local state.vscdb, then Cursor's HTTPS CSV export β never synced to your repo |
Default state.vscdb locations (override with CURSOR_STATE_DB_PATH or CURSOR_CONFIG_DIR):
- macOS:
~/Library/Application Support/Cursor/User/globalStorage/state.vscdb - Windows:
%APPDATA%\Cursor\User\globalStorage\state.vscdb - Linux:
~/.config/Cursor/User/globalStorage/state.vscdb
Optional: CURSOR_WEB_BASE_URL (default https://cursor.com).
Each machine's file in the repo:
{
"hostname": "my-pc",
"lastUpdated": "2026-04-12T10:00:00.000Z",
"days": {
"2026-04-12": {
"claude_code": {
"byModel": {
"claude-sonnet-4-6": { "inputTokens": 45000, "outputTokens": 3200, "costUSD": 0.183 }
},
"totals": { "inputTokens": 45000, "outputTokens": 3200, "costUSD": 0.183 }
},
"codex": {
"byModel": { "codex-1": { "inputTokens": 12000, "outputTokens": 800 } },
"totals": { "inputTokens": 12000, "outputTokens": 800 }
}
}
}
}- Node.js 22+
- git installed and on your
PATH - A git remote you can push to (GitHub or any host)
Native dependencies (better-sqlite3, @napi-rs/canvas) install automatically; on some systems you may need build tools if prebuilt binaries aren't available.