CLI tool that generates usage heatmaps for Antigravity, Claude Code, Codex, Cursor, Gemini CLI, Open Code, and Pi Coding Agent for the rolling past year (ending today).
packages/
cli/
registry/
tooling/
typescript-config/
bun install
bun run check# Build once
bun run build
# Run from built output
node packages/cli/dist/cli.js
# Run the CLI package directly in dev mode
bun run --cwd packages/cli dev
# Or if installed as a package binary
slopmeter# Output file (default: `./heatmap-last-year.png`; explicit provider flags add suffixes like `./heatmap-last-year_cursor.png`, and `--all` uses `./heatmap-last-year_all.png`)
slopmeter --output ./out/heatmap.svg
slopmeter -o ./out/heatmap.svg
# Output format
slopmeter --format png
slopmeter --format svg
slopmeter --format json
slopmeter -f svg
# Dark theme
slopmeter --dark
slopmeter --dark --format svg
# Merge all providers into one graph
slopmeter --all
# Provider filters (optional)
slopmeter --claude
slopmeter --codex
slopmeter --cursor
slopmeter --antigravity
slopmeter --gemini
slopmeter --opencode
slopmeter --pi- Monday-first contribution-style heatmap for the last year.
- Top metrics per provider:
LAST 30 DAYSINPUT TOKENSOUTPUT TOKENSTOTAL TOKENS(includes cache tokens)
- Bottom metrics per provider:
MOST USED MODEL(with total tokens)RECENT USE (LAST 30 DAYS)(with total tokens)LONGEST STREAKCURRENT STREAK
Model names are normalized to remove a trailing date suffix like -20251101.
- Default format is PNG.
- If
--outputis omitted, the default filename isheatmap-last-year.<ext>,heatmap-last-year_<providers>.<ext>for explicit provider flags, orheatmap-last-year_all.<ext>for--all. - If
--formatis omitted, format is inferred from--outputextension (.png,.svg, or.json). - If neither provides a format, PNG is used.
- Use
--format json(or an.jsonoutput filename) to export data for interactive rendering. - Export includes fixed
version: "2026-03-03". - Each provider includes:
titleandcolorsdailyrows withdate,input,output,cache,totaldaily[].breakdownper-model usage for that day, sorted bytokens.total(includesinputandoutput)insights(mostUsedModel,recentMostUsedModel) when available
- If no provider flags are passed, the CLI renders all providers with available data.
- If
--allis passed, the CLI renders one merged graph across all providers with consolidated totals, streaks, and model rankings. - Pi Coding Agent usage is derived from assistant messages in Pi session logs, grouped by the model that handled each turn.
- Antigravity usage is derived from local Antigravity language server trajectory RPCs plus trajectory IDs from local Antigravity unified state.
- If provider flags are passed,
slopmeteronly loads those providers and only prints availability for those providers. - If no provider flags are passed, the CLI loads all providers and prints availability for all providers.
- If explicit provider flags are passed and any requested provider has no data, the command exits with an error.
- If no provider flags are passed and no provider has data, the command exits with an error.
ANTIGRAVITY_CONFIG_DIR: override the Antigravity config root used for log discovery.ANTIGRAVITY_LOG_PATH: override Antigravity log discovery with an explicitAntigravity.logfile path.ANTIGRAVITY_LS_PID: force a language server PID for RPC discovery.ANTIGRAVITY_LS_HTTP_PORT: force the Antigravity LS HTTP port.ANTIGRAVITY_LS_CSRF_TOKEN: force the Antigravity LS CSRF token.ANTIGRAVITY_STATE_DB_PATH: override Antigravity unified-state DB discovery with an explicitstate.vscdbpath.ANTIGRAVITY_MAX_TRAJECTORIES: cap the number of cascades scanned per run. Default:200.ANTIGRAVITY_MAX_STEP_PAGES: cap per-cascade step page fetches (20-step page size). Default:100.SLOPMETER_FILE_PROCESS_CONCURRENCY: positive integer file-processing limit for Claude Code and Codex JSONL files. Default:16.SLOPMETER_MAX_JSONL_RECORD_BYTES: byte cap for Claude Code and Codex JSONL records, OpenCode JSON documents, and OpenCode SQLitemessage.datapayloads. Default:67108864(64 MB).
- Claude Code and Codex now share the same bounded JSONL record splitter and do not materialize whole files in memory.
- Oversized Claude Code JSONL records fail the affected file with a clear error that names the file, line number, byte cap, and
SLOPMETER_MAX_JSONL_RECORD_BYTES. - OpenCode legacy JSON message files use a bounded JSON document reader before
JSON.parse. - OpenCode SQLite
message.datapayloads use the same byte cap beforeJSON.parse. - Oversized OpenCode JSON documents and SQLite message payloads fail clearly with the source path or row label, byte cap, and
SLOPMETER_MAX_JSONL_RECORD_BYTES. - Codex now streams JSONL records and only parses records that affect usage aggregation.
- Oversized irrelevant Codex records are skipped and summarized with a warning after processing.
- Oversized relevant Codex records fail the affected file with a clear error that names the file, line number, byte cap, and
SLOPMETER_MAX_JSONL_RECORD_BYTES. - Pi Coding Agent session logs are streamed and only assistant messages are parsed for usage aggregation.
- Claude Code:
$CLAUDE_CONFIG_DIR/*/projects(comma-separated dirs) or defaults~/.config/claude/projectsand~/.claude/projects - Codex:
$CODEX_HOME/sessionsor~/.codex/sessions - Antigravity: discovers local Antigravity language server metadata from
%APPDATA%/Antigravity/logs/**/Antigravity.log(Windows),~/Library/Application Support/Antigravity/logs/**/Antigravity.log(macOS), or~/.config/Antigravity/logs/**/Antigravity.log(Linux), then reads usage from local LS protobuf RPC endpoints - Cursor: reads
cursorAuth/accessTokenandcursorAuth/refreshTokenfrom$CURSOR_STATE_DB_PATH,$CURSOR_CONFIG_DIR/User/globalStorage/state.vscdb,~/Library/Application Support/Cursor/User/globalStorage/state.vscdb(macOS),%APPDATA%/Cursor/User/globalStorage/state.vscdb(Windows), or~/.config/Cursor/User/globalStorage/state.vscdb(Linux), then loads usage from Cursor's CSV export endpoint - Gemini CLI:
$GEMINI_CONFIG_DIR/tmp/**/chats/session-*.jsonor~/.gemini/tmp/**/chats/session-*.json - Open Code: prefers
$OPENCODE_DATA_DIR/opencode.dbor~/.local/share/opencode/opencode.db, and falls back to$OPENCODE_DATA_DIR/storage/messageor~/.local/share/opencode/storage/message - Pi Coding Agent:
$PI_CODING_AGENT_DIR/sessionsor~/.pi/agent/sessions