CLI tool that generates usage heatmaps for Claude Code, Codex, Cursor, Open Code, Pi Coding Agent, Hermes Agent, and Helios for the rolling past year (ending today).
packages/
cli/
registry/
web/
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)
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 --opencode
slopmeter --pi
slopmeter --hermes
slopmeter --helios- 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
--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:
dailyrows withdate,input,output,cache,totaldaily[].breakdownper-model usage for that day, sorted bytokens.total(includesinputandoutput)insights(mostUsedModel,recentMostUsedModel) when available
packages/web contains a small Next.js page meant for Vercel deployment. It renders the original slopmeter SVG layout on the web:
- one merged all-provider section
- one section per available provider
- custom hover tooltips on active cells
# optional frozen import from another machine
mkdir -p .slopmeter-data/imports
cp /path/to/windows-export.json .slopmeter-data/imports/windows-history.json
# optional one-time T3 Chat export kept outside the repo
mkdir -p ~/.local/share/slopmeter
cp /path/to/t3-chat-export.json ~/.local/share/slopmeter/t3-chat-export.json
# merge local usage + import and write only the local published artifact
SLOPMETER_WEB_SKIP_BLOB_UPLOAD=1 bun run publish:web
# run the web app locally against .slopmeter-data/published/daily-usage.json
bun run dev:web- The page reads
SLOPMETER_WEB_SVG_URLat runtime. - The hosted app serves from
/by default. SetSLOPMETER_WEB_BASE_PATHonly if you intentionally want a subpath deployment. bun run publish:webscans this machine's current usage, merges the optional Windows import at.slopmeter-data/imports/windows-history.json, merges the optional one-time T3 import at~/.local/share/slopmeter/t3-chat-export.json, writes.slopmeter-data/published/daily-usage.jsonplus.slopmeter-data/published/heatmap-last-year.svg, and uploads both artifacts to Vercel Blob.- Set
BLOB_READ_WRITE_TOKENfor real uploads. - Optional overrides:
SLOPMETER_WEB_BASE_PATHSLOPMETER_WEB_IMPORT_PATHSLOPMETER_WEB_T3_IMPORT_PATHSLOPMETER_WEB_T3_MAX_BYTESSLOPMETER_WEB_LOCAL_OUTPUT_PATHSLOPMETER_WEB_LOCAL_SVG_OUTPUT_PATHSLOPMETER_WEB_BLOB_PATHSLOPMETER_WEB_SVG_BLOB_PATHSLOPMETER_WEB_SKIP_BLOB_UPLOAD=1
- 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 and GSD session logs, grouped by the model that handled each turn.
- Hermes and Helios stay separate provider sections even when they route to other backends underneath.
- T3 Chat is hosted-page-only and is sourced from a one-time local export during
publish:web. - 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.
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).GSD_HOME: alternate GSD base directory. Default:~/.gsd.HERMES_HOME: alternate Hermes base directory. Default:~/.hermes.HELIOS_HOME: alternate Helios base directory. Default:~/.helios.
- 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 and GSD 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 - 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 - 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 - GSD-2:
$GSD_HOME/sessionsor~/.gsd/sessions, merged intopi - Hermes Agent:
$HERMES_HOME/state.dbor~/.hermes/state.db - Helios:
$HELIOS_HOME/helios.dbor~/.helios/helios.db - T3 Chat hosted import:
SLOPMETER_WEB_T3_IMPORT_PATHor~/.local/share/slopmeter/t3-chat-export.json