slopmeter
v0.5.1
Published
CLI for generating yearly usage heatmaps for Claude Code, Codex, Cursor, Open Code, and Pi Coding Agent.
Downloads
2,005
Maintainers
Readme
slopmeter
slopmeter is a Node.js CLI that scans local Claude Code, Codex, Cursor, Open Code, and Pi Coding Agent usage data and generates a contribution-style heatmap for the rolling past year.
Requirements
- Node.js
>=22
Run with npm
Use it without installing:
npx slopmeterInstall it globally:
npm install -g slopmeter
slopmeterUsage
slopmeter [--all] [--claude] [--codex] [--cursor] [--opencode] [--pi] [--dark] [--format png|svg|json] [--output ./heatmap-last-year.png]By default, the CLI:
- scans all supported providers
- writes
./heatmap-last-year.png - infers the date window as the rolling last year ending today
Options
--claude: include only Claude Code data--codex: include only Codex data--cursor: include only Cursor data--opencode: include only Open Code data--pi: include only Pi Coding Agent data--all: merge all providers into one combined graph--dark: render the image with the dark theme-f, --format <png|svg|json>: choose the output format-o, --output <path>: write output to a custom path-h, --help: print the help text
Examples
Generate the default PNG:
npx slopmeterWrite an SVG:
npx slopmeter --format svg --output ./out/heatmap.svgWrite JSON for custom rendering:
npx slopmeter --format json --output ./out/heatmap.jsonRender only Codex usage:
npx slopmeter --codexRender only Cursor usage:
npx slopmeter --cursorRender only Pi Coding Agent usage:
npx slopmeter --piRender one merged graph across all providers:
npx slopmeter --allWhen provider flags are present, slopmeter only loads those providers and only prints availability for those providers.
Render a dark-theme SVG:
npx slopmeter --dark --format svg --output ./out/heatmap-dark.svgOutput behavior
- If
--formatis omitted, the format is inferred from the--outputextension when possible. - Supported extensions are
.png,.svg, and.json. - If neither
--formatnor a recognized output extension is provided, PNG is used.
Data locations
- Claude Code:
$CLAUDE_CONFIG_DIR/*/projectsor~/.config/claude/projects,~/.claude/projects - Older Claude Code layouts: falls back to
$CLAUDE_CONFIG_DIR/stats-cache.json,~/.config/claude/stats-cache.json, or~/.claude/stats-cache.jsonfor days not present in project logs - Earliest Claude Code activity fallback: uses
$CLAUDE_CONFIG_DIR/history.jsonl,~/.config/claude/history.jsonl, or~/.claude/history.jsonlto mark activity-only days when token totals are unavailable - 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
When Claude Code falls back to stats-cache.json, the daily input/output/cache split is reconstructed from Claude's cached model totals because the older layout does not keep per-request usage logs.
When Claude Code falls back to history.jsonl, those days are rendered as activity-only cells and do not affect the token totals shown in the header.
Exit behavior
- If no provider flags are passed,
slopmeterrenders every provider with available data. - If
--allis passed,slopmeterloads all providers and renders one combined graph with merged 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.
- If provider flags are passed and a requested provider has no data, the command exits with an error.
- If no provider has data, the command exits with an error.
Environment variables
SLOPMETER_FILE_PROCESS_CONCURRENCY: positive integer file-processing limit for Claude Code and Codex JSONL files. Default:4.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).
JSONL record handling
- Claude Code and Codex JSONL files are streamed through the same bounded record splitter;
slopmeterdoes not materialize whole files in memory. - Oversized Claude Code JSONL records fail the file with a clear error that names the file, line number, byte cap, and
SLOPMETER_MAX_JSONL_RECORD_BYTES. - OpenCode prefers the current SQLite store (
opencode.db) and falls back to the legacy file-backed message layout. - OpenCode legacy JSON message files are read through 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. - Only Codex
turn_contextandevent_msgtoken_countrecords are parsed for usage aggregation. - Oversized irrelevant Codex records are skipped and reported in a warning summary.
- Oversized relevant Codex records fail the 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.
License
MIT
