About this project

Vole is a local-first usage, cost and anomaly monitor for AI coding agents. It targets the situation where several agents run side by side, each burning tokens independently and none of them signalling when something has gone wrong — stuck in a tool loop, retrying against a broken API, or repeatedly re-reading the same large context. Where other tools answer "how much did I spend?", Vole asks "is anything going wrong right now?" and reports spend as a side effect. Data handling Vole reads the log files the tools already write to disk — for example ~/.claude/projects/**/*.jsonl for Claude Code, ~/.local/share/opencode/opencode.db for OpenCode, ~/.codex/sessions/**/rollout-*.jsonl for Codex CLI, ~/.grok/logs/unified.jsonl for Grok CLI, plus local stores for Cursor, Devin and Antigravity — and normalises them into a single schema. Everything runs locally: no scraping, no cloud APIs, no login, and no prompt or tool content is stored. The only optional permission requested is notifications, for alerts when a critical incident fires. Supported tools and fidelity policy Coverage varies by tool: Claude Code and OpenCode provide exact tokens and cost; Codex CLI and Grok CLI provide exact tokens but have no published rate; Cursor, Devin and Antigravity record no tokens locally and are therefore covered as activity only. The project states there is no "estimated" tier by policy — a token count is either read verbatim from the tool's own logs or genuinely absent, and rows without tokens still count as calls but are excluded from token and cost aggregates. Estimating Cursor tokens from lines of code was considered and explicitly rejected. The app A menu-bar item shows live tokens, cost or just the icon, tinted while an incident is open. Clicking it opens a panel with headline figures, a sparkline and per-tool bars; a dashboard provides the full view. Its signature element is an incident-annotated timeline that stacks tokens per tool and names the bucket, its tokens and any incidents that fired there on hover. The app embeds its own collector, starts it itself, and updates in place: a release publishing a checksummed archive offers one-click install that verifies the published SHA-256 before swapping the bundle, and a release without a checksum never silent-installs. Command line and MCP Alongside the app, Vole exposes terminal commands over the same data: pnpm top (live sessions, context versus window, tokens per minute, cache countdown), pnpm digest (a markdown agent-usage summary with range and JSON options), pnpm pr (usage on the current branch for a PR description), pnpm statusline, and pnpm mcp, a stdio MCP server. The MCP server exposes vole_summary, vole_live_sessions, vole_session, vole_incidents, vole_breakdown, vole_whatif and vole_digest, so an agent can ask what its own session has cost or whether Vole has flagged it. The server reads the local database and answers on stdout. Anomaly rules Five rules ship: billable_burn_spike (a 10-minute window costing more than 3x that session's typical window), repeat_call_loop (45+ calls in 5 minutes while output stays flat), error_storm (over 20% error ratio across 15 minutes with at least 5 errors), rate_limit_pressure (Codex reports over 80% of quota consumed) and context_pressure (a call carried at least 80% of the model's context window). Baselines are leave-one-out, comparing a window against the median of all other windows, and loop detection requires two signals so that a productive burst of calls is not mistaken for a loop. Cost model Cost is equivalent API value at list price — what the usage would have cost through the API — and the UI notes that subscription plans are not billed per token. Rates live in packages/core/src/data/pricing.json, versioned with effective_from, and a per-installation ~/.vole/pricing.json merges over it so a model can be added without a release; rows stored before a model had a rate are repriced retroactively. Unknown models return NULL, never 0. Verification and testing The project ships pnpm test for unit tests of rules, queries, bucketing and confidence invariants, and pnpm verify, which reconciles every stored row against its own source record using an independently re-implemented cost formula. Verification compares per record rather than per total and fails on an empty store so a vacuous pass cannot occur. A pnpm seed command writes 30 days of synthetic history tagged source='seed', charted separately from live data. Building and limitations Building from source requires Node 22+, pnpm and Xcode 26, tested on macOS 26 arm64; pnpm app:bundle builds and opens the app, or the collector and app can be run separately. Documented limitations include shallow coverage for tools that record no local tokens, is_error covering API errors only so error_storm can under-count, generation speeds being lower bounds for some tools, context windows resolving only for first-party model ids, and approximate timing for Antigravity based on file mtimes. The project is MIT licensed and welcomes contributions, with two stated review rules: never invent a number, and every collector is idempotent.