A high-performance CLI tool and visualization dashboard for tracking token usage and costs across multiple AI coding agents.
Note
Token Stats is a fork focused on token-stats.com and the @token-stats/cli npm package.
Install: bunx @token-stats/cli@latest · Site: token-stats.com · Repo: Annihilater/token-stats
🇺🇸 English | 🇰🇷 한국어 | 🇯🇵 日本語 | 🇨🇳 简体中文
| Overview | Models |
|---|---|
![]() |
![]() |
| Daily Summary | Stats |
|---|---|
![]() |
![]() |
| Frontend (3D Contributions Graph) | Wrapped 2025 |
|---|---|
![]() |
![]() |
Run
bunx @token-stats/cli@latest submitto submit your usage data to the leaderboard and create your public profile!
Token Stats helps you monitor and analyze your token consumption from:
Based on the open-source tokscale project (MIT).
| Logo | Client | Data Location |
|---|---|---|
![]() |
OpenCode | ~/.local/share/opencode/opencode.db (1.2+, all channels including opencode-stable.db) or/and ~/.local/share/opencode/storage/message/ (legacy/unmigrated) |
![]() |
Claude Code | ~/.claude/projects/ and ~/.claude/transcripts/ |
![]() |
OpenClaw | ~/.openclaw/agents/ (+ legacy: .clawdbot, .moltbot, .moldbot) |
![]() |
Codex CLI | ~/.codex/sessions/ |
![]() |
Sakana Fugu | via Codex — ~/.codex/sessions/*.jsonl (model_provider: sakana) |
![]() |
GitHub Copilot CLI | ~/.copilot/otel/*.jsonl (+ COPILOT_OTEL_FILE_EXPORTER_PATH) |
![]() |
Hermes Agent | $HERMES_HOME/state.db and $HERMES_HOME/profiles/*/state.db (fallback: ~/.hermes/...) |
![]() |
Gemini CLI | $GEMINI_CLI_HOME/tmp/*/chats/*.json (fallback: ~/.gemini/tmp/*/chats/*.json) |
![]() |
Cursor IDE | Cursor API export cached at ~/.config/tokscale/cursor-cache/usage*.csv (not ~/.cursor) |
![]() |
Amp (AmpCode) | ~/.local/share/amp/threads/ |
![]() |
Codebuff | ~/.config/manicode/ (+ manicode-dev, manicode-staging; override via CODEBUFF_DATA_DIR) |
![]() |
Droid (Factory Droid) | ~/.factory/sessions/ |
![]() |
Pi | ~/.pi/agent/sessions/ and ~/.omp/agent/sessions/ (Oh My Pi) |
![]() |
Kimi CLI / Kimi Code | kimi-cli: ~/.kimi/sessions/ kimi-code: ~/.kimi-code/sessions/ (override via KIMI_CODE_HOME) |
![]() |
Qwen CLI | ~/.qwen/projects/ |
![]() |
Roo Code | ~/.config/Code/User/globalStorage/rooveterinaryinc.roo-cline/tasks/ (+ server: ~/.vscode-server/data/User/globalStorage/rooveterinaryinc.roo-cline/tasks/) |
![]() |
Kilo | ~/.config/Code/User/globalStorage/kilocode.kilo-code/tasks/ (+ server: ~/.vscode-server/data/User/globalStorage/kilocode.kilo-code/tasks/) |
![]() |
Kilo CLI | ~/.local/share/kilo/kilo.db |
![]() |
Mux | ~/.mux/sessions/ |
![]() |
Crush | $XDG_DATA_HOME/crush/projects.json (project registry; fallback: ~/.local/share/crush/projects.json) |
![]() |
Goose | ~/.local/share/goose/sessions/sessions.db (+ macOS Application Support, legacy Block/goose paths; override via GOOSE_PATH_ROOT) |
![]() |
Google Antigravity | Cached via token-stats antigravity sync to ~/.config/tokscale/antigravity-cache/sessions/*.jsonl (live RPC against the local language server) |
![]() |
Antigravity CLI | ~/.gemini/antigravity-cli/conversations/*.db (override the Gemini home via GEMINI_CLI_HOME; local SQLite, read directly — no antigravity sync needed) |
![]() |
Trae IDE / Trae Solo (international) | Cached via token-stats trae sync to ~/.config/tokscale/trae-cache/sessions/*.json (account-level usage from the official API) |
![]() |
Warp / Oz | Cached via token-stats warp sync to ~/.config/tokscale/warp-cache/usage.json (aggregate requests and spend only; no token transcripts) |
![]() |
Grok Build | $GROK_HOME/sessions/*/*/updates.jsonl (fallback: ~/.grok/sessions/*/*/updates.jsonl) |
![]() |
Zed Agent | ~/.local/share/zed/threads/threads.db (macOS: ~/Library/Application Support/Zed/threads/threads.db; Windows: %LOCALAPPDATA%/Zed/threads/threads.db; hosted Zed models only, not external ACP agents) |
![]() |
Kiro | ~/.kiro/sessions/cli/*.json (+ *.jsonl), ~/.local/share/kiro-cli/data.sqlite3 (macOS: ~/Library/Application Support/kiro-cli/data.sqlite3), and Kiro IDE globalStorage snapshots (Kiro/User/globalStorage/kiro.kiroagent; macOS Application Support, Linux ~/.config/Kiro, Windows %APPDATA%\Kiro) |
![]() |
Cline | VS Code globalStorage tasks (Linux: ~/.config/Code/...; macOS: ~/Library/Application Support/Code/...; Windows: %APPDATA%\Code\...; server: ~/.vscode-server/data/User/globalStorage/saoudrizwan.claude-dev/tasks/) |
![]() |
gajae-code (gjc) | ~/.gjc/agent/sessions/ (override via GJC_CODING_AGENT_DIR, GJC_CONFIG_DIR, PI_CONFIG_DIR; $XDG_DATA_HOME/gjc/sessions/ on Linux/macOS) |
![]() |
Jcode | ~/.jcode/sessions/session_*.json + session_*.journal.jsonl sidecars (override via JCODE_HOME) |
![]() |
MiMo Code | ~/.local/share/mimocode/mimocode.db (XDG data dir; SQLite) |
![]() |
Junie | ~/.junie/sessions/*/events.jsonl |
![]() |
Command Code | ~/.commandcode/projects/**/*.jsonl (token usage estimated from transcripts at ~4 chars/token; not persisted on disk) |
![]() |
ZCode | ~/.zcode/cli/db/db.sqlite (v2 usage database) and ~/.zcode/projects/**/*.jsonl (legacy transcripts) |
![]() |
OpenCodeReview | ~/.opencodereview/sessions/**/*.jsonl |
![]() |
CodeBuddy (CLI, IDE, VS Code plugin) | ~/.codebuddy/projects/**/*.jsonl + extension logs |
![]() |
WorkBuddy | ~/.workbuddy/projects/**/*.jsonl + SQLite fallback |
![]() |
Devin CLI | ~/.local/share/devin/cli/sessions.db (SQLite) |
![]() |
Devin Desktop | ACP events: macOS ~/Library/Application Support/Devin/User/acp-events/; Linux ~/.config/Devin/User/acp-events/; Windows %APPDATA%\Devin\User\acp-events\ |
![]() |
Synthetic | Re-attributed from other sources via hf: model prefix or synthetic provider (+ Octofriend: ~/.local/share/octofriend/sqlite.db) |
Get real-time pricing calculations using 🚅 LiteLLM's pricing data, with support for tiered pricing models and cache token discounts.
This project is inspired by the Kardashev scale, a method proposed by astrophysicist Nikolai Kardashev to measure a civilization's level of technological advancement based on its energy consumption. A Type I civilization harnesses all energy available on its planet, Type II captures the entire output of its star, and Type III commands the energy of an entire galaxy.
In the age of AI-assisted development, tokens are the new energy. They power our reasoning, fuel our productivity, and drive our creative output. Just as the Kardashev scale tracks energy consumption at cosmic scales, Token Stats measures your token consumption as you scale the ranks of AI-augmented development. Whether you're a casual user or burning through millions of tokens daily, Token Stats helps you visualize your journey up the scale—from planetary developer to galactic code architect.
- Overview
- Features
- Installation
- Usage
- Frontend Visualization
- Social Platform
- Wrapped 2025
- Development
- Supported Platforms
- Session Data Retention
- Data Sources
- Pricing
- Contributing
- Acknowledgments
- License
- Interactive TUI Mode - Beautiful terminal UI powered by Ratatui (default mode)
- 6 interactive views: Overview, Models, Daily, Hourly, Stats, Agents (plus an optional Minutely view, opt-in via
minutelyTabEnabled) - Keyboard & mouse navigation
- GitHub-style contribution graph with configurable color themes
- Real-time filtering and sorting
- Zero flicker rendering
- 6 interactive views: Overview, Models, Daily, Hourly, Stats, Agents (plus an optional Minutely view, opt-in via
- Multi-platform support - Track usage across OpenCode, Claude Code, Codex CLI, Copilot CLI, Cursor IDE, Gemini CLI, Amp, Codebuff, Droid, OpenClaw, Hermes Agent, Pi, Kimi CLI, Qwen CLI, Roo Code, Kilo, Mux, Kilo CLI, Crush, Goose, Antigravity, Antigravity CLI, Zed, Kiro, Trae, Warp/Oz, Cline, Gajae-Code, Grok Build, Jcode, MiMo Code, Command Code, Junie, ZCode, OpenCodeReview, CodeBuddy, WorkBuddy, Devin CLI, Devin Desktop, and Synthetic
- Real-time pricing - Fetches current pricing from LiteLLM with 1-hour disk cache; automatic OpenRouter fallback and Cursor model pricing for newly released models
- Detailed breakdowns - Input, output, cache read/write, and reasoning token tracking
- Native Rust core - All parsing and aggregation done in Rust for 10x faster processing
- Web visualization - Interactive contribution graph with 2D and 3D views
- Flexible filtering - Filter by platform, date range, or year
- Task-attributed reports - LLM-powered session summarization and task grouping with multi-backend support (Apple FM, Claude, Codex, Gemini, Kiro)
- Export to JSON - Generate data for external visualization tools
- Social Platform - Share your usage, compete on leaderboards, and view public profiles
# Run with bunx (recommended)
bunx @token-stats/cli@latest
# Or with npx
npx @token-stats/cli@latest
# Light mode (table rendering only)
bunx @token-stats/cli@latest --lightThat's it! This gives you the full interactive TUI experience with zero setup.
Package Structure:
@token-stats/cliis the npm package (launcher + optional native binaries for each platform). Unscopedtoken-statscannot be published on npm (name too similar to existingtokenstats).
For local development or building from source:
# Clone the repository
git clone https://github.com/Annihilater/token-stats.git
cd token-stats
# Install Bun (if not already installed)
curl -fsSL https://bun.sh/install | bash
# Install dependencies
bun install
# Run the CLI in development mode
bun run cliNote:
bun run cliis for local development. When installed viabunx @token-stats/cli, the command runs directly. The Usage section below shows the installed binary commands.
The native Rust module is required for CLI operation. It provides ~10x faster processing through parallel file scanning and SIMD JSON parsing:
# Build the native core (run from repository root)
bun run build:coreNote: Native binaries are pre-built and included when you install via
bunx @token-stats/cli@latest. Building from source is only needed for local development.
# Launch interactive TUI (default)
token-stats
# Launch TUI with specific tab
token-stats models # Models tab
token-stats monthly # Daily view (shows daily breakdown)
token-stats hourly # Hourly tab
# Use legacy CLI table output
token-stats --light
token-stats models --light
# Launch TUI explicitly
token-stats tui
# Export contribution graph data as JSON
token-stats graph --output data.json
# Output data as JSON (for scripting/automation)
token-stats --json # Default models view as JSON
token-stats models --json # Models breakdown as JSON
token-stats monthly --json # Monthly breakdown as JSON
token-stats models --json > report.json # Save to fileThe interactive TUI mode provides:
- 8 Views: Overview (chart + top models), Usage (subscription quotas), Models, Daily, Hourly, Stats (contribution graph), Agents. A per-minute view (Minutely) is hidden by default and can be enabled with
minutelyTabEnabledinsettings.json— see Configuration - Keyboard Navigation:
←/→/Tab/BackTab: Switch views↑/↓orHome/End: Navigate listsEnter: Open daily detail (Daily tab) / select graph cell (Stats tab)EscorBackspace: Close dialog or exit detail viewc/d/t: Sort by cost/date/tokensj: Jump to todays: Open source picker dialogg: Open group-by picker dialog (model, client+model, client+provider+model, workspace+model, session+model, client+session+model)h: Toggle Daily/Hourly chart granularity (Overview tab)v: Toggle Table/Profile view (Hourly tab)y: Copy selected row to clipboardp: Cycle through color themesr: Refresh data;Shift+Rtoggles auto-refresh;+/-adjusts intervale: Export to JSONqorCtrl+C: Quit
- Mouse Support: Click tabs, buttons, and filters
- Themes: Green, Halloween, Teal, Blue, Pink, Purple, Orange, Monochrome, YlGnBu, Graphite, Lagoon, Dusk
- Settings Persistence: Preferences saved to
~/.config/tokscale/settings.json(see Configuration)
Press g in the TUI or use --group-by in --light/--json mode to control how model rows are aggregated:
| Strategy | Flag | TUI Default | Effect |
|---|---|---|---|
| Model | --group-by model |
✅ | One row per model — merges all clients and providers |
| Client + Model | --group-by client,model |
One row per client-model pair | |
| Client + Provider + Model | --group-by client,provider,model |
Most granular — no merging | |
| Workspace + Model | --group-by workspace,model |
Group local usage by workspace key, then model | |
| Session + Model | --group-by session,model |
One row per session_id and model — attribute cost to a specific agent-CLI session |
|
| Client + Session + Model | --group-by client,session,model |
One row per client, session, and model — useful for multi-agent runners that join on session_id |
--group-by model (most consolidated)
| Clients | Providers | Model | Cost |
|---|---|---|---|
| OpenCode, Claude, Amp | github-copilot, anthropic | claude-opus-4-5 | $2,424 |
| OpenCode, Claude | anthropic, github-copilot | claude-sonnet-4-5 | $1,332 |
--group-by client,model (CLI default)
| Client | Provider | Model | Cost |
|---|---|---|---|
| OpenCode | github-copilot, anthropic | claude-opus-4-5 | $1,368 |
| Claude | anthropic | claude-opus-4-5 | $970 |
--group-by client,provider,model (most granular)
| Client | Provider | Model | Cost |
|---|---|---|---|
| OpenCode | github-copilot | claude-opus-4-5 | $1,200 |
| OpenCode | anthropic | claude-opus-4-5 | $168 |
| Claude | anthropic | claude-opus-4-5 | $970 |
--group-by session,model (per-session cost attribution)
token-stats models --json --group-by session,model emits one entry per (session_id, model). Each entry includes a top-level sessionId field so downstream tools (e.g. multi-agent IDEs) can join cost data back to a specific agent-CLI session:
{
"groupBy": "session,model",
"entries": [
{
"sessionId": "019e1e27-af49-7cd1-89b7-7bad1c3f3be2",
"client": "codex",
"provider": "openai",
"model": "gpt-5",
"input": 25251,
"output": 47,
"cacheRead": 1920,
"cacheWrite": 0,
"reasoning": 40,
"messageCount": 12,
"cost": 0.0123
}
]
}Use --group-by client,session,model when you also need the client name on every row (one spawn across all 20+ supported CLIs at once).
Use --client (short -c) to scope reports to one or more clients. The flag is repeatable, accepts comma-separated values, and works with every report command:
# Show only OpenCode usage
token-stats --client opencode
# Comma-separated: combine multiple clients
token-stats --client opencode,claude
# Repeated: same effect, useful with shell aliases
token-stats -c opencode -c claude
# Cursor IDE uses Token Stats' API cache; run login + sync --json first
token-stats --client cursor
# Synthetic (synthetic.new) is detected from other agent sessions
token-stats --client synthetic
# Combine with other filters
token-stats --client opencode,claude --week --jsonPossible values: opencode, claude, codex, copilot, gemini, cursor, amp, codebuff, droid, openclaw, hermes, pi, kimi, qwen, roocode, kilocode, kilo, mux, crush, goose, antigravity, antigravity-cli, zed, kiro, trae, warp, cline, gjc, grok, jcode, micode, commandcode, junie, zcode, opencodereview, codebuddy, synthetic.
Breaking change (v4.0.0): The per-client boolean flags (
--opencode,--claude,--codex, etc.) have been removed and now error. Use the canonical--client/-cflag instead — e.g.token-stats --client opencode,claude.
Date filters work across all commands that generate reports (token-stats, token-stats models, token-stats monthly, token-stats graph):
# Quick date shortcuts
token-stats --today # Today only
token-stats --yesterday # Yesterday only
token-stats --week # Last 7 days
token-stats --month # Current calendar month
# Custom date range (inclusive, local timezone)
token-stats --since 2024-01-01 --until 2024-12-31
# Filter by year
token-stats --year 2024
# Combine with other options
token-stats models --week --client claude --json
token-stats monthly --month --benchmarkNote: Date filters use your local timezone. Both
--sinceand--untilare inclusive. v2.2.0 note: Session active-time daily buckets also use your local timezone, so users outside UTC may see active-time dates align with local token/cost report days instead of UTC day boundaries.
Look up real-time pricing for any model:
# Look up model pricing
token-stats pricing "claude-3-5-sonnet-20241022"
token-stats pricing "gpt-4o"
token-stats pricing "grok-code"
# Force specific provider source
token-stats pricing "grok-code" --provider openrouter
token-stats pricing "claude-3-5-sonnet" --provider litellm
# Inspect custom pricing overrides
token-stats pricing list-overridesLookup Strategy:
The pricing lookup uses a multi-step resolution strategy:
- Custom Pricing Overrides - Exact user-defined entries from
~/.config/tokscale/custom-pricing.json - Exact Match - Direct lookup in LiteLLM/OpenRouter databases
- Alias Resolution - Resolves friendly names (e.g.,
big-pickle→glm-4.7) - Tier Suffix Stripping - Removes quality tiers (
gpt-5.2-xhigh→gpt-5.2) - Version Normalization - Handles version formats (
claude-3-5-sonnet↔claude-3.5-sonnet) - Provider Prefix Matching - Tries common prefixes (
anthropic/,openai/, etc.) - Cursor Model Pricing - Hardcoded pricing for models not yet in LiteLLM/OpenRouter (e.g.,
gpt-5.3-codex) - Fuzzy Matching - Word-boundary matching for partial model names
Create custom-pricing.json in Token Stats' config directory (~/.config/tokscale/custom-pricing.json on macOS/Linux by default; the same directory resolved by TOKSCALE_CONFIG_DIR when set) to override prices for model IDs that upstream pricing databases do not yet cover correctly.
{
"$schema": "https://token-stats.com/custom-pricing.schema.json",
"models": {
"accounts/fireworks/routers/kimi-k2p6-turbo": {
"input_cost_per_million_tokens": 2.00,
"output_cost_per_million_tokens": 8.00,
"cache_read_input_token_cost_per_million_tokens": 0.30,
"source": "https://docs.fireworks.ai/serverless/pricing",
"notes": "Fireworks Kimi K2.6 Turbo (preview)"
},
"accounts/fireworks/models/kimi-k2p6": {
"input_cost_per_million_tokens": 0.95,
"output_cost_per_million_tokens": 4.00,
"cache_read_input_token_cost_per_million_tokens": 0.16
},
"kimi-k2p6-turbo": {
"input_cost_per_million_tokens": 2.00,
"output_cost_per_million_tokens": 8.00
}
}
}Override prices are entered in dollars per million tokens, matching how most API providers publish pricing; Token Stats converts them to per-token rates internally. At least one of input_cost_per_million_tokens or output_cost_per_million_tokens must be present and positive, and cache-read/cache-creation fields are optional. LiteLLM-style per-token field names such as input_cost_per_token, output_cost_per_token, and cache_read_input_token_cost are also accepted for copy/paste compatibility, but the per-million names are the recommended user-facing form. To omit a tier or cache price, leave the field out; negative or non-finite values are treated as invalid and the whole model entry is skipped so typos do not silently alter accounting. Optional source and notes fields are ignored by Token Stats and can be used for your own bookkeeping.
Overrides are exact-only and case-insensitive. Token Stats checks the raw model ID first, then the existing synthetic /models/ normalization, then falls through to LiteLLM, OpenRouter, Cursor pricing, and fuzzy matching if no override matches. Raw exact matches beat normalized exact matches, so accounts/fireworks/routers/kimi-k2p6-turbo can override one gateway-specific model while kimi-k2p6-turbo can cover normalized /models/ paths. Overrides are loaded once at startup; restart the command after editing the file. This is the recommended local fix for wrong-model pricing bugs while waiting on upstream LiteLLM pricing updates.
Provider Preference:
When multiple matches exist, original model creators are preferred over resellers:
| Preferred (Original) | Deprioritized (Reseller) |
|---|---|
xai/ (Grok) |
azure_ai/ |
anthropic/ (Claude) |
bedrock/ |
openai/ (GPT) |
vertex_ai/ |
google/ (Gemini) |
together_ai/ |
meta-llama/ |
fireworks_ai/ |
Example: grok-code matches xai/grok-code-fast-1 ($0.20/$1.50) instead of azure_ai/grok-code-fast-1 ($3.50/$17.50).
# Login to Token Stats (opens browser for GitHub auth)
token-stats login
# Save an existing Token Stats API token without browser auth
token-stats login --token tt_xxx
# Check who you're logged in as
token-stats whoami
# Display your saved API token as a QR code (useful for sharing to another device)
# Encodes {"token":"tt_xxx","username":"..."} — scan with any QR reader
token-stats qr
# Submit your usage data to the leaderboard
token-stats submit
# Submit in CI/headless environments without writing credentials
# Precedence: TOKSCALE_API_TOKEN env > saved credentials file (~/.config/tokscale/credentials.json).
# When the env var is set, the saved file is ignored for that invocation.
TOKSCALE_API_TOKEN=tt_xxx token-stats submit
# Revoke a token: visit Settings > API Tokens on the leaderboard site
# (https://token-stats.com/settings) and click "Revoke" on the token row.
# Revocation takes effect immediately — subsequent requests with that
# token will get HTTP 401 "Invalid API token".
# Submit with filters
token-stats submit --client opencode,claude --since 2024-01-01
# Preview what would be submitted (dry run)
token-stats submit --dry-run
# Logout
token-stats logoutAutosubmit schedules the normal token-stats submit flow with the operating system scheduler. It is useful for keeping your public profile current without a manual terminal run.
# Enable periodic submission. Uses launchd on macOS, systemd user timers on Linux
# when available, cron as a Linux fallback, and Windows Task Scheduler on Windows.
token-stats autosubmit enable --interval 24h
# Keep the same client and date filters you would pass to submit.
token-stats autosubmit enable --interval 2h --client opencode,claude --week
# Show saved settings and the last run/error.
token-stats autosubmit status
token-stats autosubmit status --json
# Run once now, even if the saved interval has not elapsed.
token-stats autosubmit run --force
# Disable autosubmit and remove the scheduler entry.
token-stats autosubmit disableScheduled runs are non-interactive: they never prompt for GitHub auth or star confirmation. Run token-stats login --token tt_xxx once, or set TOKSCALE_API_TOKEN in the scheduler environment. Token Stats records scheduler state in settings.json, writes logs under ~/.config/tokscale/autosubmit/, and uses a lock file so overlapping scheduler ticks do not submit twice.
Cursor IDE support uses Cursor's web API export, cached by Token Stats at ~/.config/tokscale/cursor-cache/usage*.csv. Token Stats does not parse local Cursor Agent CLI state under ~/.cursor.
Setup:
- Open https://www.cursor.com/settings in your browser and sign in.
- Copy the
WorkosCursorSessionTokencookie value:- Network tab: make any request to
cursor.com/api/*, then copy the value afterWorkosCursorSessionToken=from theCookierequest header. - Application tab: open Cookies ->
https://www.cursor.com, then copy theWorkosCursorSessionTokenvalue.
- Network tab: make any request to
- Run
token-stats cursor login --name workand paste the token. - Run
token-stats cursor sync --jsonto populate~/.config/tokscale/cursor-cache/usage.csv. - Run
token-stats --client cursoror any report command.
Treat the session token like a password. It is stored locally in ~/.config/tokscale/cursor-credentials.json.
# Login to Cursor (requires session token from browser)
# --name is optional; it just helps you identify accounts later
token-stats cursor login --name work
# Check Cursor authentication status and session validity
token-stats cursor status
# List saved Cursor accounts
token-stats cursor accounts
# Manually refresh cached Cursor usage
token-stats cursor sync --json
# Switch active account (controls which account syncs to cursor-cache/usage.csv)
token-stats cursor switch work
# Logout from a specific account (keeps history; excludes it from aggregation)
token-stats cursor logout --name work
# Logout and delete cached usage for that account
token-stats cursor logout --name work --purge-cache
# Logout from all Cursor accounts (keeps history; excludes from aggregation)
token-stats cursor logout --all
# Logout from all accounts and delete cached usage
token-stats cursor logout --all --purge-cacheBy default, Token Stats aggregates usage across all saved Cursor accounts by reading cursor-cache/usage*.csv. The active account syncs to usage.csv; additional accounts sync to usage.<account>.csv.
When you log out, Token Stats moves cached usage to cursor-cache/archive/ so it is no longer aggregated. Use --purge-cache to delete cached usage instead.
Antigravity sync currently works on macOS and Linux only. The Antigravity-enabled editor must be running and its local language server available; token-stats reads usage from that local language server and caches normalized artifacts locally.
# Check whether token-stats can see running Antigravity language servers
token-stats antigravity status
# Sync usage from local Antigravity language servers into Token Stats' cache
token-stats antigravity sync
# Delete the cached Antigravity artifacts
token-stats antigravity purge-cacheCache location: ~/.config/tokscale/antigravity-cache/
How it works: token-stats antigravity sync discovers local Antigravity session candidates, fetches confirmed usage data from the local language server RPC, and stores normalized JSONL artifacts for the Token Stats core parser to parse later. Run sync before reports if you want the freshest Antigravity data.
Trae (ByteDance's AI IDE) ships in two international product lines — Trae IDE and Trae Solo. They share the same account-level usage data (same backend, same JWT), so token-stats reports them as a single trae client. You can install either or both desktop apps; token-stats auto-discovers credentials from whichever is present.
Credentials are identified per desktop app via --variant:
--variant ide— credentials from Trae IDE (~/Library/Application Support/Trae/)--variant solo— credentials from Trae Solo (~/Library/Application Support/TRAE SOLO/)
token-stats trae sync calls the official query_user_usage_group_by_session API exactly once per run (regardless of how many desktop apps are installed) and persists the raw JSON to a local cache.
# Log in (auto-detects credentials from any installed Trae desktop client)
token-stats trae login
# Manual JWT entry (for environments where auto-detect can't find storage.json,
# e.g. Linux/Windows or a headless server). Open https://www.trae.ai/account-setting#usage
# in your browser, then F12 → Network → filter `query_user_usage` and copy the
# `Authorization` header value.
token-stats trae login --manual --variant solo
# Show which variants have cached credentials
token-stats trae status
# Sync usage (uses the first available credential source)
token-stats trae sync --since 30
# Forget cached credentials for one variant
token-stats trae logout --variant soloCache location: ~/.config/tokscale/trae-cache/
How it works: token-stats either decrypts the desktop client's iCubeAuthInfo://* blob (globalStorage/storage.json) to recover a JWT, or accepts one pasted via --manual. It then calls POST /trae/api/v1/pay/query_user_usage_group_by_session paginated and stores the raw JSON. Run sync before reports if you want the freshest Trae data.
Note on pricing: Trae cost figures are vendor-reported — token-stats surfaces the
dollar_floatvalue returned by Trae's own API rather than recomputing cost from token counts through Token Stats' pricing engine. Numbers will match what you see ontrae.ai/account-setting#usage, not what token-stats would otherwise calculate for the same usage.
China variants: The China editions (
trae.com.cn) are intentionally not supported. The CN backend does not expose a session-level usage query API. Trae CN / Trae Solo CN support will be added once an official endpoint becomes available upstream.
Warp/Oz does not expose local token transcripts. Token Stats only syncs the aggregate request and spend counters returned by Warp's GraphQL API, then reports them as warp / aggregate-requests rows with zero token buckets.
# Save a bearer token or Cookie header copied from an authenticated Warp request
token-stats warp login
# Inspect credential/cache state and diagnostics
token-stats warp status
# Sync aggregate requests and spend into Token Stats' local cache
token-stats warp sync
# Remove saved credentials; add --purge-cache to delete synced usage too
token-stats warp logout --purge-cacheCache location: ~/.config/tokscale/warp-cache/usage.json
How it works: token-stats warp sync calls Warp's authenticated GraphQL API for account and workspace aggregate counters. Token Stats preserves request counts as message counts and vendor-reported spend as cost, but it never converts requests into synthetic tokens. Warp is excluded from default submit data because the public leaderboard accepts token-attributed usage, not aggregate request counters.
The report command generates a task-attributed usage breakdown. It uses an LLM to summarize each session into a short title and category, then groups related sessions into high-level task clusters for a bird's-eye view of where your tokens went.
# Basic report (today, default Apple FM summarizer)
token-stats report
# Last 7 days
token-stats report --week
# Use Claude Code as the summarizer backend
token-stats report --week --summarizer claude
# Use Codex, Gemini, or Kiro
token-stats report --summarizer codex
token-stats report --summarizer gemini
token-stats report --summarizer kiro
# Skip LLM summarization (show raw data only)
token-stats report --no-summarize
# Re-summarize from scratch (resets cached summaries in range)
token-stats report --week --rebuild
# Output as JSON
token-stats report --week --json
# Filter by workspace or client
token-stats report --workspace my-project --client opencodeSummarizer backends:
| Backend | Command | Notes |
|---|---|---|
apple-fm |
(default) | On-device Apple Foundation Models via native Rust FFI (no Python). Enabled in the prebuilt Apple Silicon (macOS arm64) binary; runs on macOS 26+ with Apple Intelligence on, and transparently falls back to a built-in Rust heuristic everywhere else (Intel Macs, older macOS, Linux, Windows) — so the default works on every platform. |
claude |
claude -p |
Requires Claude Code CLI installed and authenticated. |
codex |
codex --quiet |
Requires Codex CLI installed and authenticated. |
gemini |
gemini -p |
Requires Gemini CLI installed and authenticated. |
kiro |
kiro --non-interactive |
Requires Kiro CLI installed and authenticated. |
How it works:
- Sessions are scanned and inserted into a local SQLite wiki database (
wiki.dbin your platform config dir — e.g.~/.config/tokscale/on Linux,~/Library/Application Support/tokscale/on macOS) - Unsummarized sessions are sent to the chosen LLM backend in batches, which returns a title, category, description, and complexity for each
- A second LLM pass groups all titled sessions into 3–8 high-level task clusters (e.g. "Kiro Auth", "Token Stats Report", "System Config")
- Results are cached in the wiki DB — subsequent runs skip already-summarized sessions
Example output:
Task Group Sess Tokens Cost
───────────────────────────────────────────────────────────────────────
Token Stats Development 19 4.2B $22.66
Add task-attributed report command
Implement wiki DB schema
Fix pricing lookup for new models
System Config 28 2.1B $10.06
Configure OpenCode workspace settings
Update shell aliases
Kiro Auth 4 890.5M $3.10
Implement JWT refresh flow
Token Stats can fetch and display your real-time subscription quota across AI providers. This shows how much of your plan you've used and when limits reset.
# Show subscription usage for all detected providers
token-stats usage
# Output as JSON (for scripting)
token-stats usage --json
# Lightweight terminal output (no TUI)
token-stats usage --lightIn the TUI, navigate to the Usage tab to see subscription data. Use [Refresh] to refresh subscription quotas. The keyboard refresh shortcut r uses the same refresh path.
Note: Subscription quotas and balances are vendor-reported — token-stats calls each provider's own quota endpoint and surfaces the response verbatim. Numbers reflect what the provider reports (which is also what shows up in their official dashboards) and are not independently verified against Token Stats' own usage tracking.
| Provider | Auth Method | Metrics | Setup |
|---|---|---|---|
| Claude | OAuth (credentials file or macOS Keychain) | Session (5hr), Weekly, Opus quotas | Run claude to log in |
| Codex (OpenAI) | OAuth (~/.config/codex/auth.json, ~/.codex/auth.json, or saved Token Stats accounts) |
Session, Weekly quotas | Use [Add Codex] in the TUI Usage tab, run codex to log in, or import an existing auth with token-stats codex import --name work |
| Z.ai | API key (env var) | Token limits, Web Searches | Set ZAI_API_KEY or GLM_API_KEY |
| Amp | API key (~/.local/share/amp/secrets.json) |
Free tier balance, Credits | Run amp to log in |
| GitHub Copilot | GitHub token (keychain or ~/.config/gh/hosts.yml) |
Premium interactions, Chat quotas | Run gh auth login |
| Grok Build | OAuth (~/.grok/auth.json) |
Credits, subscription plan | Run grok login |
| Kimi | OAuth (~/.kimi/credentials/kimi-code.json) |
Session, Weekly quotas | Run kimi to log in |
| MiniMax | API key (env var) | Prompt quotas per model | Set MINIMAX_API_KEY or MINIMAX_API_TOKEN |
| MiniMax Token Plan | API key (env var) | Interval + weekly remaining-percent quotas (per region: CN minimaxi.com + Global minimax.io) | Set MINIMAX_TOKEN_PLAN_CN_KEY and/or MINIMAX_TOKEN_PLAN_GLOBAL_KEY |
| Sakana (Fugu) | Session cookie (env var or file) — billing-console HTML scrape, no public API | 5-hour, Weekly quota windows (plan tier + monthly price as metadata) | Set SAKANA_SESSION_COOKIE (see docs/providers/sakana.md) |
Providers are auto-detected — only those with valid credentials are shown. If a provider is missing, ensure you've logged in or set the required environment variable.
Token Stats can save multiple Codex OAuth accounts for subscription usage display. The TUI Usage tab groups saved accounts under one Codex section. The active account is marked with *; inactive accounts can be selected with [Use]; account removal uses [Remove] followed by [Confirm].
To add an account without leaving the TUI, click [Add Codex] in the Usage tab. Token Stats starts codex login with a temporary CODEX_HOME, displays the login output in the Usage tab, imports the resulting auth into Token Stats' saved account store, and then refreshes usage. This keeps the login isolated and does not switch the current Codex auth; click [Use] on a saved account when you want Token Stats to write that account into the real Codex auth file.
The CLI commands are still available for scripted or manual account management, plus a separate opt-in account-activity snapshot:
# Save the current Codex auth as a named Token Stats account
token-stats codex import --name work
# List saved Codex accounts
token-stats codex accounts
token-stats codex accounts --json
# Switch the active Codex account and write Codex auth.json
token-stats codex switch work
# Stop tracking a saved Codex account (removes it from Token Stats' store
# only — the codex CLI's own auth.json/login is never touched)
token-stats codex remove personal
# Check subscription usage for the active or a named account
token-stats codex status
token-stats codex status --name personal --json
# Fetch the active Codex app-server account activity separately from local totals
token-stats codex activity
token-stats codex activity --jsonWhen saved Codex accounts exist, token-stats usage --json includes structured account metadata for each Codex entry and the TUI displays those entries under one Codex group. Without saved accounts, Token Stats falls back to the current Codex auth discovery path (CODEX_HOME/auth.json, ~/.config/codex/auth.json, ~/.codex/auth.json, then macOS Keychain).
token-stats codex activity uses only the installed Codex app-server's active authentication to fetch a timestamped, account-level snapshot. It is supplemental data: it is never included in local totals, reports, exports, submissions, or leaderboards.
╭──────────────────────────────────────────────────────────╮
│ Session 85% left [=========---] resets in 2h 15m │
│ Weekly 72% left [========----] resets Fri 3pm │
│ Plan Max 20x │
╰──────────────────────────────────────────────────────────╯
╭──────────────────────────────────────────────────────────╮
│ Session 40% left [=====-------] resets in 4h 30m │
│ Weekly 90% left [==========--] resets Mon 12am │
│ Account user@example.com │
│ Plan Pro │
╰──────────────────────────────────────────────────────────╯
Token Stats stores settings in ~/.config/tokscale/settings.json:
{
"colorPalette": "blue",
"includeUnusedModels": false,
"defaultClients": ["opencode", "claude"],
"scanner": {
"extraScanPaths": {
"codex": [
"/Users/me/workspace/project-a/.codex/sessions",
"/Users/me/workspace/project-b/.codex/archived_sessions"
],
"hermes": [
"/Users/me/.hermes/profiles/director_planning",
"/Users/me/.hermes/profiles/research/state.db"
]
}
}
}| Setting | Type | Default | Description |
|---|---|---|---|
colorPalette |
string | "blue" |
TUI color theme (green, halloween, teal, blue, pink, purple, orange, monochrome, ylgnbu, graphite, lagoon, dusk) |
includeUnusedModels |
boolean | false |
Show models with zero tokens in reports |
autoRefreshEnabled |
boolean | false |
Enable auto-refresh in TUI |
autoRefreshMs |
number | 60000 |
Auto-refresh interval (30000-3600000ms) |
nativeTimeoutMs |
number | 300000 |
Maximum time for native subprocess processing (5000-3600000ms) |
defaultClients |
string[] | [] |
Client filter applied when no --client/-c flag is passed. Accepts the same ids as --client (e.g. ["opencode", "claude", "synthetic"]). Unknown ids are silently dropped. CLI flags always override this list completely — no merging. |
light.writeCache |
boolean | false |
When true, token-stats --light overwrites the TUI cache atomically after rendering. CLI flags --write-cache / --no-write-cache override per-invocation. |
minutelyTabEnabled |
boolean | false |
Show the per-minute Minutely tab in the TUI and aggregate per-minute usage during data loading. Default-off because minute-granularity is a niche/diagnostic view for most users and the per-minute bucketing has a non-trivial cost on large datasets. |
autosubmit |
object | disabled | Saved token-stats autosubmit state: interval, client/date filters, scheduler backend, last run time, and last error. Prefer token-stats autosubmit enable/status/disable over editing this object by hand. |
scanner.extraScanPaths |
object | {} |
Additional per-client scan roots for sessions outside Token Stats' default home-root locations |
Use scanner.extraScanPaths for persistent extra roots such as project-level .codex directories or imported Gemini/OpenClaw histories. Token Stats automatically discovers Hermes profile databases under $HERMES_HOME/profiles/*/state.db (or ~/.hermes/profiles/*/state.db when HERMES_HOME is unset). Use scanner.extraScanPaths.hermes only for non-standard Hermes profile locations; entries may point at a profile directory containing state.db or directly at a state.db file. Token Stats merges these paths with the default scan roots on every run and deduplicates overlapping roots by canonical path.
Use defaultClients to pin a personal default — for example, set it to ["opencode", "claude"] if those are the only clients you use, and token-stats (with no flags) will scope every report to them automatically. Pass --client on the command line to override for a single run.
The Minutely tab shows a per-minute breakdown of token usage and is most useful for diagnosing burst patterns, debugging a single session, or watching activity in near-real-time alongside autoRefreshEnabled. It is hidden by default because the per-minute aggregation runs over every parsed message during data loading, which adds RAM and CPU cost that most users do not need.
To enable it, set minutelyTabEnabled to true in ~/.config/tokscale/settings.json:
{
"minutelyTabEnabled": true
}After restart, the Minutely tab appears between Hourly and Stats in the tab strip, and Tab / BackTab / Left / Right navigation cycles through it. Set the flag back to false to hide the tab and skip the aggregation again.
The regenerable CLI/TUI/pricing/Wrapped caches now live under ~/.config/tokscale/cache/ (or ${TOKSCALE_CONFIG_DIR}/cache/ when overridden). Integration sync artifacts remain in client-specific cache roots such as ~/.config/tokscale/antigravity-cache/ and ~/.config/tokscale/trae-cache/:
tui-data-cache.json— TUI startup cachesource-message-cache-v2/+source-message-cache.lock— sharded source-message cache + lock filepricing-litellm.json/pricing-openrouter.json— pricing cachesopencode-migration.json— OpenCode migration recordfonts/andimages/— Wrapped asset caches
It is safe to delete this directory. Token Stats will recreate and repopulate it on demand.
Environment variables override config file values. For CI/CD or one-off use:
| Variable | Default | Description |
|---|---|---|
TOKSCALE_NATIVE_TIMEOUT_MS |
300000 (5 min) |
Overrides nativeTimeoutMs config |
TOKSCALE_API_TOKEN |
unset | Token Stats personal API token for non-interactive submit and delete-submitted-data runs. Create one from Settings > API Tokens or save it locally with token-stats login --token tt_xxx. |
TOKSCALE_EXTRA_DIRS |
unset | One-off extra session roots as client:/abs/path,client:/abs/path |
TOKSCALE_CONFIG_DIR |
unset | Overrides the config directory root (where settings.json, star-cache.json, cache/, antigravity-cache/, and trae-cache/ live). Absolute path recommended; relative paths resolve against the process CWD. Useful for CI sandboxes or pinning a non-default location. When set, token-stats will not fall back to the legacy macOS ~/Library/Application Support/tokscale/ path. |
TOKSCALE_FM_DEBUG |
unset | When set, prints Apple Foundation Models diagnostics (macOS version gate, dlopen dylib path, load/symbol errors) to stderr to explain why on-device apple-fm did or didn't engage. |
# Example: Increase timeout for very large datasets
TOKSCALE_NATIVE_TIMEOUT_MS=600000 token-stats graph --output data.json
# Example: one-off extra scan roots
TOKSCALE_EXTRA_DIRS='codex:/Users/me/workspace/project-a/.codex/sessions,gemini:/Users/me/imports/imac/gemini/tmp' token-stats
# Example: submit from CI without an interactive browser login
TOKSCALE_API_TOKEN=tt_xxx token-stats submitNote: For persistent extra roots, prefer
scanner.extraScanPathsin~/.config/tokscale/settings.json.TOKSCALE_EXTRA_DIRSis best for one-off overrides or CI/CD.
Token Stats can aggregate token usage from Codex CLI headless outputs for automation, CI/CD pipelines, and batch processing.
What is headless mode?
When you run Codex CLI with JSON output flags (e.g., codex exec --json), it outputs usage data to stdout instead of storing it in its regular session directories. Headless mode allows you to capture and track this usage.
Storage location: ~/.config/tokscale/headless/
On macOS, Token Stats also scans ~/Library/Application Support/tokscale/headless/ when TOKSCALE_HEADLESS_DIR is not set.
Token Stats automatically scans this directory structure:
~/.config/tokscale/headless/
└── codex/ # Codex CLI JSONL outputs
Environment variable: Set TOKSCALE_HEADLESS_DIR to customize the headless log directory:
export TOKSCALE_HEADLESS_DIR="$HOME/my-custom-logs"Recommended (automatic capture):
| Tool | Command Example |
|---|---|
| Codex CLI | token-stats headless codex exec -m gpt-5 "implement feature" |
Manual redirect (optional):
| Tool | Command Example |
|---|---|
| Codex CLI | codex exec --json "implement feature" > ~/.config/tokscale/headless/codex/ci-run.jsonl |
Diagnostics:
# Show scan locations and headless counts
token-stats sources
token-stats sources --jsonCI/CD integration example:
# In your GitHub Actions workflow
- name: Run AI automation
run: |
mkdir -p ~/.config/tokscale/headless/codex
codex exec --json "review code changes" \
> ~/.config/tokscale/headless/codex/pr-${{ github.event.pull_request.number }}.jsonl
# Later, track usage
- name: Report token usage
run: token-stats --jsonNote: Headless capture is supported for Codex CLI only. If you run Codex directly, redirect stdout to the headless directory as shown above.
The frontend provides a GitHub-style contribution graph visualization:
- 2D View: Classic GitHub contribution calendar
- 3D View: Isometric 3D contribution graph with height based on token usage
- Multiple color palettes: GitHub, GitLab, Halloween, Winter, and more
- 3-way theme toggle: Light / Dark / System (follows OS preference)
- GitHub Primer design: Uses GitHub's official color system
- Interactive tooltips: Hover for detailed daily breakdowns
- Day breakdown panel: Click to see per-source and per-model details
- Year filtering: Navigate between years
- Source filtering: Filter by platform (OpenCode, Claude, Codex, Copilot, Cursor, Gemini, Amp, Codebuff, Droid, OpenClaw, Hermes Agent, Pi, Kimi, Qwen, Roo Code, Kilo, Mux, Kilo CLI, Crush, Goose, Antigravity, Antigravity CLI, Zed, Kiro, Trae, Warp, Cline, Gajae-Code, Grok Build, Jcode, MiMo Code, Command Code, Junie, ZCode, OpenCodeReview, CodeBuddy, WorkBuddy, Devin CLI, Devin Desktop, Synthetic)
- Stats panel: Total cost, tokens, active days, streaks
- FOUC prevention: Theme applied before React hydrates (no flash)
cd packages/frontend
bun install
bun run devOpen http://localhost:3000 to access the social platform.
Token Stats includes a social platform where you can share your usage data and compete with other developers.
- Leaderboard - See who's using the most tokens across all platforms
- User Profiles - Public profiles with contribution graphs and statistics
- Period Filtering - View stats for all time, this month, or this week
- GitHub Integration - Login with your GitHub account
- Local Viewer - View your data privately without submitting
You can embed your public Token Stats stats directly in your GitHub profile README:
[](https://token-stats.com/u/<username>)Replace <username> with your GitHub username. With no query parameters this
renders the default classic card; append any of the parameters below to
customize the design.
| Parameter | Values | Effect |
|---|---|---|
template |
classic (default) · minimal · terminal · graph · orbit · vitals · blueprint · receipt |
Card design |
color |
blue · green · teal · purple · pink · orange · monochrome · halloween · YlGnBu |
Accent color and contribution-graph palette |
theme |
dark (default) · light |
Light or dark card |
sort |
tokens (default) · cost |
Which leaderboard the rank is taken from |
tokens, cost |
compact · full |
Number format, set independently — 20.9B vs 20,941,000,000 |
rank |
plain (default, #134) · percent (top 12%) · total (#134 / 1,174) |
How the leaderboard rank is shown |
graph |
1 to append the contribution graph (off by default) |
Supported by classic, minimal, terminal, orbit, blueprint, receipt |
view |
2d (default) · 3d |
Switch between the selected 2D card and the isometric contribution view |
compact |
1 |
Uses the compact Classic layout or compact number formatting in the 3D view |
Examples:




You can also use a shields.io-style badge for a more compact display:
- Replace
<username>with your GitHub username - Optional query params:
metric=tokens(default),metric=cost, ormetric=rankstyle=flat(default) orstyle=flat-squaresort=tokens(default) orsort=costto control ranking basiscompact=1to use compact number notation (e.g.,1.2M,$3.4K)label=<text>to override the left-side labelcolor=<hex>to override the right-side color (e.g.,color=ff5733)
- Examples:
https://token-stats.com/api/badge/<username>/svg?metric=cost&compact=1https://token-stats.com/api/badge/<username>/svg?metric=rank&sort=cost&style=flat-square
- Login - Run
token-stats loginto authenticate via GitHub, or create an API token in Settings for CI/headless use - Submit - Run
token-stats submitto upload your usage data - View - Visit the web platform to see your profile and the leaderboard
Submitted data goes through Level 1 validation:
- Mathematical consistency (totals match, no negatives)
- No future dates
- Required fields present
- Duplicate detection
Generate a beautiful year-in-review image summarizing your AI coding assistant usage—inspired by Spotify Wrapped.
bunx @token-stats/cli@latest wrapped |
bunx @token-stats/cli@latest wrapped --clients |
bunx @token-stats/cli@latest wrapped --agents --disable-pinned |
|---|---|---|
![]() |
![]() |
![]() |
# Generate wrapped image for current year
token-stats wrapped
# Generate for a specific year
token-stats wrapped --year 2025The generated image includes:
- Total Tokens - Your total token consumption for the year
- Top Models - Your 3 most-used AI models ranked by cost
- Top Clients - Your 3 most-used platforms (OpenCode, Claude Code, Cursor, etc.)
- Messages - Total number of AI interactions
- Active Days - Days with at least one AI interaction
- Cost - Estimated total cost based on LiteLLM pricing
- Streak - Your longest consecutive streak of active days
- Contribution Graph - A visual heatmap of your yearly activity
The generated PNG is optimized for sharing on social media. Share your coding journey with the community!
Quick setup: If you just want to get started quickly, see Development Setup in the Installation section above.
# Bun (required)
bun --version
# Rust (for native module)
rustc --version
cargo --versionAfter following the Development Setup, you can:
# Build native module (optional but recommended)
bun run build:core
# Run in development mode (launches TUI)
cd packages/cli && bun src/index.ts
# Or use legacy CLI mode
cd packages/cli && bun src/index.ts --lightAdvanced Development
| Script | Description |
|---|---|
bun run cli |
Run CLI in development mode (TUI with Bun) |
bun run build:core |
Build native Rust module (release) |
bun run build:cli |
Build CLI TypeScript to dist/ |
bun run build |
Build both core and CLI |
bun run dev:frontend |
Run frontend development server |
Package-specific scripts (from within package directories):
packages/cli:bun run dev,bun run tuipackages/core:bun run build:debug,bun run test,bun run bench
Note: This project uses Bun as the package manager for development.
# Test native module (Rust)
cd packages/core
bun run test:rust # Cargo tests
bun run test # Node.js integration tests
bun run test:all # Bothcd packages/core
# Build in debug mode (faster compilation)
bun run build:debug
# Build in release mode (optimized)
bun run build
# Run Rust benchmarks
bun run bench# Export graph data to file
token-stats graph --output usage-data.json
# Date filtering (all shortcuts work)
token-stats graph --today
token-stats graph --week
token-stats graph --since 2024-01-01 --until 2024-12-31
token-stats graph --year 2024
# Filter by platform
token-stats graph --client opencode,claude
# Show processing time benchmark
token-stats graph --output data.json --benchmarkShow processing time for performance analysis:
token-stats --benchmark # Show processing time with default view
token-stats models --benchmark # Benchmark models report
token-stats monthly --benchmark # Benchmark monthly report
token-stats graph --benchmark # Benchmark graph generation# Export data for visualization
token-stats graph --output packages/frontend/public/my-data.jsonThe native Rust module provides significant performance improvements:
| Operation | TypeScript | Rust Native | Speedup |
|---|---|---|---|
| File Discovery | ~500ms | ~50ms | 10x |
| JSON Parsing | ~800ms | ~100ms | 8x |
| Aggregation | ~200ms | ~25ms | 8x |
| Total | ~1.5s | ~175ms | ~8.5x |
Benchmarks for ~1000 session files, 100k messages
The native module also provides ~45% memory reduction through:
- Streaming JSON parsing (no full file buffering)
- Zero-copy string handling
- Efficient parallel aggregation with map-reduce
# Generate synthetic data
cd packages/benchmarks && bun run generate
# Run Rust benchmarks
cd packages/core && bun run bench| Platform | Architecture |
|---|---|
| macOS | x86_64 |
| macOS | aarch64 (Apple Silicon) |
| Linux | x86_64 (glibc) |
| Linux | aarch64 (glibc) |
| Linux | x86_64 (musl) |
| Linux | aarch64 (musl) |
| Windows | x86_64 |
| Windows | aarch64 |
On Linux, the launcher detects glibc vs musl automatically (via process.report, the musl dynamic loader at /lib/ld-musl-*.so.1, and ldd). If detection ever picks the wrong flavor — e.g. in minimal containers — set TOKSCALE_LIBC=musl (or TOKSCALE_LIBC=gnu) to force it.
Token Stats fully supports Windows. The TUI and CLI work the same as on macOS/Linux.
Installation on Windows:
# Install Bun (PowerShell)
powershell -c "irm bun.sh/install.ps1 | iex"
# Run token-stats
bunx @token-stats/cli@latestAI coding tools store their session data in cross-platform locations. Most tools use the same relative paths on all platforms:
| Tool | Unix Path | Windows Path | Source |
|---|---|---|---|
| OpenCode | ~/.local/share/opencode/ |
%USERPROFILE%\.local\share\opencode\ |
Uses xdg-basedir for cross-platform consistency (source) |
| Claude Code | ~/.claude/ |
%USERPROFILE%\.claude\ |
Same path on all platforms |
| OpenClaw | ~/.openclaw/ (+ legacy: .clawdbot, .moltbot, .moldbot) |
%USERPROFILE%\.openclaw\ (+ legacy paths) |
Same path on all platforms |
| Codex CLI | ~/.codex/ |
%USERPROFILE%\.codex\ |
Configurable via CODEX_HOME env var (source) |
| Copilot CLI | ~/.copilot/otel/ |
%USERPROFILE%\.copilot\otel\ |
Requires OTEL file export; also auto-ingests COPILOT_OTEL_FILE_EXPORTER_PATH |
| Hermes Agent | ~/.hermes/ |
%USERPROFILE%\.hermes\ |
Configurable via HERMES_HOME env var (source) |
| Gemini CLI | ~/.gemini/ |
%USERPROFILE%\.gemini\ |
Configurable via GEMINI_CLI_HOME env var |
| Amp | ~/.local/share/amp/ |
%USERPROFILE%\.local\share\amp\ |
Uses xdg-basedir like OpenCode |
| Cursor | API sync | API sync | Data fetched from Cursor API and cached as usage*.csv; local ~/.cursor session data is not parsed |
| Droid | ~/.factory/ |
%USERPROFILE%\.factory\ |
Same path on all platforms |
| Pi | ~/.pi/ and ~/.omp/ |
%USERPROFILE%\.pi\ and %USERPROFILE%\.omp\ |
Same path on all platforms (supports both Pi and Oh My Pi) |
| Kimi CLI | ~/.kimi/ |
%USERPROFILE%\.kimi\ |
Same path on all platforms |
| Kimi Code | ~/.kimi-code/ |
%USERPROFILE%\.kimi-code\ |
Same path on all platforms |
| Qwen CLI | ~/.qwen/ |
%USERPROFILE%\.qwen\ |
Same path on all platforms |
| Roo Code | ~/.config/Code/User/globalStorage/rooveterinaryinc.roo-cline/tasks/ |
%USERPROFILE%\.config\Code\User\globalStorage\rooveterinaryinc.roo-cline\tasks\ |
VS Code globalStorage task logs |
| Kilo | ~/.config/Code/User/globalStorage/kilocode.kilo-code/tasks/ |
%USERPROFILE%\.config\Code\User\globalStorage\kilocode.kilo-code\tasks\ |
VS Code globalStorage task logs |
| Cline | Linux: ~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/tasks/; macOS: ~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/tasks/; server: ~/.vscode-server/data/User/globalStorage/saoudrizwan.claude-dev/tasks/ |
%APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\tasks\ |
VS Code globalStorage task logs |
| Mux | ~/.mux/sessions/ |
%USERPROFILE%\.mux\sessions\ |
Same path on all platforms |
| Codebuff | ~/.config/manicode/projects/ (+ manicode-dev, manicode-staging) |
%USERPROFILE%\.config\manicode\projects\ |
Override via CODEBUFF_DATA_DIR env var |
| Kilo CLI | ~/.local/share/kilo/ |
%USERPROFILE%\.local\share\kilo\ |
Uses xdg-basedir like OpenCode |
| Crush | $XDG_DATA_HOME/crush/ (fallback: ~/.local/share/crush/) |
%USERPROFILE%\.local\share\crush\ (or %XDG_DATA_HOME%\crush\ if set) |
Uses XDG data directory with fallback |
| Goose | ~/.local/share/goose/sessions/ (+ macOS Application Support, legacy Block paths) |
%USERPROFILE%\.local\share\goose\sessions\ |
Configurable via GOOSE_PATH_ROOT env var |
| Antigravity | ~/.config/tokscale/antigravity-cache/sessions/ |
— | token-stats antigravity sync is currently supported on macOS/Linux only |
| Zed Agent | ~/.local/share/zed/threads/threads.db |
%LOCALAPPDATA%\Zed\threads\threads.db |
Hosted Zed model usage only; external ACP agents are not included |
| Kiro | ~/.kiro/sessions/cli/ and ~/.local/share/kiro-cli/data.sqlite3 |
%USERPROFILE%\.kiro\sessions\cli\ and %USERPROFILE%\.local\share\kiro-cli\data.sqlite3 |
Parses Kiro session files plus the Kiro CLI SQLite database when present |
| Trae | ~/.config/tokscale/trae-cache/sessions/ |
%APPDATA%\tokscale\trae-cache\sessions\ |
Synced once via token-stats trae sync; credentials are auto-discovered from any installed Trae IDE or Trae Solo desktop app |
| Warp/Oz | ~/.config/tokscale/warp-cache/usage.json |
%APPDATA%\tokscale\warp-cache\usage.json |
Synced via token-stats warp sync; aggregate requests and spend only, no token transcripts |
| Grok Build | ~/.grok/sessions/ |
%USERPROFILE%\.grok\sessions\ |
Configurable via GROK_HOME env var; parses updates.jsonl session updates |
| Jcode | ~/.jcode/sessions/ |
%USERPROFILE%\.jcode\sessions\ |
Configurable via JCODE_HOME env var; parses session_*.json snapshots plus session_*.journal.jsonl sidecars |
| MiMo Code | ~/.local/share/mimocode/ |
%USERPROFILE%\.local\share\mimocode\ |
Uses XDG data directory; SQLite database mimocode.db |
| Gajae-Code | ~/.gjc/agent/sessions/ |
%USERPROFILE%\.gjc\agent\sessions\ |
Configurable via GJC_CODING_AGENT_DIR (also GJC_CONFIG_DIR/PI_CONFIG_DIR; $XDG_DATA_HOME/gjc/sessions/ flattens on Linux/macOS) |
| Junie | ~/.junie/sessions/ |
%USERPROFILE%\.junie\sessions\ |
Same home-relative path on all platforms; parses events.jsonl usage events |
| ZCode | ~/.zcode/cli/db/db.sqlite and ~/.zcode/projects/ |
%USERPROFILE%\.zcode\cli\db\db.sqlite and %USERPROFILE%\.zcode\projects\ |
Parses v2 SQLite model usage plus legacy *.jsonl session transcripts; Z.ai's ADE for GLM models |
| OpenCodeReview | ~/.opencodereview/sessions/ |
%USERPROFILE%\.opencodereview\sessions\ |
Parses *.jsonl session transcripts; Alibaba's AI code review tool |
| CodeBuddy | ~/.codebuddy/projects/ + extension logs |
%USERPROFILE%\.codebuddy\projects\ + CodeBuddy / VS Code extension logs |
Parses CodeBuddy CLI, IDE, and VS Code plugin token usage |
| WorkBuddy | ~/.workbuddy/projects/ + ~/.workbuddy/workbuddy.db |
%USERPROFILE%\.workbuddy\projects\ + %USERPROFILE%\.workbuddy\workbuddy.db |
Parses WorkBuddy token usage, with the aggregate SQLite database as a fallback |
| Devin CLI | ~/.local/share/devin/cli/sessions.db |
%USERPROFILE%\.local\share\devin\cli\sessions.db |
Reads the authoritative local SQLite usage database |
| Devin Desktop | Linux: ~/.config/Devin/User/acp-events/; macOS: ~/Library/Application Support/Devin/User/acp-events/ |
%APPDATA%\Devin\User\acp-events\ |
Parses ACP usage events; the CLI database resolves matching session titles when present |
| Synthetic | Re-attributed from other sources | Re-attributed from other sources | Detects hf: model prefix + synthetic provider |
Note: On Windows,
~expands to%USERPROFILE%(e.g.,C:\Users\YourName). These tools intentionally use Unix-style paths (like.local/share) even on Windows for cross-platform consistency, rather than Windows-native paths like%APPDATA%.
Token Stats stores its configuration in:
- TUI settings:
%APPDATA%\tokscale\settings.json(platform default; override withTOKSCALE_CONFIG_DIR) - Cache:
%APPDATA%\tokscale\cache\(consolidated cache root) - Legacy cache paths:
%USERPROFILE%\.cache\tokscale\and%LOCALAPPDATA%\tokscale\cache\equivalents from older releases may still exist until regenerated data is written to the new path - Cursor credentials:
%USERPROFILE%\.config\tokscale\cursor-credentials.json - Trae credentials and synced usage:
%APPDATA%\tokscale\trae-cache\ - Token Stats account credentials:
%USERPROFILE%\.config\tokscale\credentials.json
By default, some AI coding assistants automatically delete old session files. To preserve your usage history for accurate tracking, disable or extend the cleanup period.
| Platform | Default | Config File | Setting to Disable | Source |
|---|---|---|---|---|
| Claude Code | ~/.claude/settings.json |
"cleanupPeriodDays": 9999999999 |
Docs | |
| Gemini CLI | Disabled | $GEMINI_CLI_HOME/settings.json (fallback: ~/.gemini/settings.json) |
"general.sessionRetention.enabled": false |
Docs |
| Codex CLI | Disabled | N/A | No cleanup feature | #6015 |
| OpenCode | Disabled | N/A | No cleanup feature | #4980 |
Default: 30 days cleanup period
Add to ~/.claude/settings.json:
{
"cleanupPeriodDays": 9999999999
}Setting an extremely large value (e.g.,
9999999999days ≈ 27 million years) effectively disables cleanup.
Default: Cleanup disabled (sessions persist forever)
If you've enabled cleanup and want to disable it, remove or set enabled: false in $GEMINI_CLI_HOME/settings.json (fallback: ~/.gemini/settings.json):
{
"general": {
"sessionRetention": {
"enabled": false
}
}
}Or set an extremely long retention period:
{
"general": {
"sessionRetention": {
"enabled": true,
"maxAge": "9999999d"
}
}
}Default: No automatic cleanup (sessions persist forever)
Codex CLI does not have built-in session cleanup. Sessions in ~/.codex/sessions/ persist indefinitely.
Note: There's an open feature request for this: #6015
Default: No automatic cleanup (sessions persist forever)
OpenCode does not have built-in session cleanup. Sessions in ~/.local/share/opencode/storage/ persist indefinitely.
Note: See #4980
Location: ~/.local/share/opencode/opencode.db (v1.2+) or storage/message/{sessionId}/*.json (legacy)
OpenCode 1.2+ stores sessions in SQLite. Token Stats reads from SQLite first and falls back to legacy JSON files for older versions.
OpenCode picks the db filename from the release channel the binary was built against: the latest and beta channels use opencode.db, while other channels use opencode-<channel>.db (e.g. opencode-stable.db, opencode-nightly.db). Token Stats scans all of them, so users running multiple channels side by side get a unified view.
If you launched opencode with OPENCODE_DB pointing at a file outside ~/.local/share/opencode, add the absolute path to ~/.config/tokscale/settings.json so token-stats can find it on every run:
{
"scanner": {
"opencodeDbPaths": [
"/custom/location/opencode.db",
"/another/location/opencode-stable.db"
]
}
}Paths are merged with auto-discovery, deduped by canonical path, and non-existent entries are silently skipped (so stale config never breaks a scan). opencode.db-wal, opencode.db-shm, and other SQLite sidecars are rejected.
If you keep sessions outside Token Stats' default home-root locations, you can also persist extra scan roots per client:
{
"scanner": {
"extraScanPaths": {
"codex": [
"/Users/me/workspace/project-a/.codex/sessions",
"/Users/me/workspace/project-b/.codex/archived_sessions"
],
"gemini": ["/Users/me/imports/imac/gemini/tmp"],
"hermes": [
"/Users/me/.hermes/profiles/director_planning",
"/Users/me/.hermes/profiles/research/state.db"
],
"openclaw": ["/Users/me/imports/imac/openclaw/agents"]
}
}
}This is useful for project-level .codex directories, imported histories, and Hermes profile databases outside the default $HERMES_HOME/state.db or ~/.hermes/state.db location. Token Stats still scans its default roots, then merges scanner.extraScanPaths and TOKSCALE_EXTRA_DIRS on top with canonical-path deduplication. It does not auto-discover your whole workspace.
Each message contains:
{
"id": "msg_xxx",
"role": "assistant",
"modelID": "claude-sonnet-4-20250514",
"providerID": "anthropic",
"tokens": {
"input": 1234,
"output": 567,
"reasoning": 0,
"cache": { "read": 890, "write": 123 }
},
"time": { "created": 1699999999999 }
}Location: ~/.claude/projects/{projectPath}/*.jsonl and ~/.claude/transcripts/*.jsonl
JSONL format with assistant messages containing usage data:
{"type": "assistant", "message": {"model": "claude-sonnet-4-20250514", "usage": {"input_tokens": 1234, "output_tokens": 567, "cache_read_input_tokens": 890}}, "timestamp": "2024-01-01T00:00:00Z"}Wrapper transcript files under ~/.claude/transcripts/ are counted only when they contain real Claude usage metadata. Files with user/tool events but no usage block are skipped rather than estimated.
Token Stats' claude client is Claude Code token accounting, not Claude Desktop chat accounting. Claude Desktop stores app data under locations such as ~/Library/Application Support/Claude, but Anthropic does not document a stable local per-message token ledger for consumer desktop chat or chat-history exports. Run token-stats clients to see a diagnostic when Claude Desktop data is present but only Claude Code JSONL roots are scannable. token-stats usage can show best-effort Claude subscription quota bars from Claude Code credentials, while organization/API usage belongs to Anthropic's Admin Usage and Cost APIs and is intentionally separate from local transcript scanning.
Location: ~/.codex/sessions/*.jsonl
Event-based format with token_count events:
{"type": "event_msg", "payload": {"type": "token_count", "info": {"last_token_usage": {"input_tokens": 1234, "output_tokens": 567}}}}Location: ~/.copilot/otel/*.jsonl or the explicit path in COPILOT_OTEL_FILE_EXPORTER_PATH
Copilot support reads file-exported OpenTelemetry JSONL. Enable it before running Copilot:
export COPILOT_OTEL_ENABLED=true
export COPILOT_OTEL_EXPORTER_TYPE=file
mkdir -p "$HOME/.copilot/otel"
export COPILOT_OTEL_FILE_EXPORTER_PATH="$HOME/.copilot/otel/copilot-otel-$(date +%Y%m%d-%H%M%S).jsonl"PowerShell:
$otelDir = "$HOME/.copilot/otel"
New-Item -ItemType Directory -Force -Path $otelDir | Out-Null
$env:COPILOT_OTEL_ENABLED = "true"
$env:COPILOT_OTEL_EXPORTER_TYPE = "file"
$env:COPILOT_OTEL_FILE_EXPORTER_PATH = Join-Path $otelDir ("copilot-otel-{0}.jsonl" -f (Get-Date -Format "yyyyMMdd-HHmmss"))Using a timestamped filename is recommended so each Copilot session writes to a fresh file instead of accumulating into one huge OTEL log.
Token Stats treats chat spans as the source of truth for token accounting and ignores tool spans plus cumulative metrics in phase 1:
{"type":"span","name":"chat gpt-5.4-mini","attributes":{"gen_ai.operation.name":"chat","gen_ai.response.model":"gpt-5.4-mini","gen_ai.conversation.id":"session-id","gen_ai.usage.input_tokens":1234,"gen_ai.usage.output_tokens":567,"gen_ai.usage.cache_read.input_tokens":890,"gen_ai.usage.reasoning.output_tokens":123}}Copilot's OTEL payloads currently do not expose stable workspace metadata, so Copilot rows may appear without workspace attribution. Token Stats prices these rows from the reported model when possible and does not trust
github.copilot.costdirectly.
Location: $GEMINI_CLI_HOME/tmp/{projectHash}/chats/*.json (fallback: ~/.gemini/tmp/{projectHash}/chats/*.json)
Session files containing message arrays:
{
"sessionId": "xxx",
"messages": [
{"type": "gemini", "model": "gemini-2.5-pro", "tokens": {"input": 1234, "output": 567, "cached": 890, "thoughts": 123}}
]
}Location: ~/.config/tokscale/cursor-cache/usage*.csv (synced via Cursor API)
Cursor data is fetched from the Cursor API using your session token and cached locally. Token Stats reads those cache files for reports; it does not parse local ~/.cursor session data. See Cursor IDE Commands for setup.
Location: ~/.config/tokscale/antigravity-cache/sessions/*.jsonl (synced via local Antigravity language server RPC)
Antigravity data is not fetched automatically by the root command. Run token-stats antigravity sync while the Antigravity-enabled editor is open to refresh the local cache, then use normal token-stats reports and filters against the cached JSONL artifacts.
Location: ~/.config/tokscale/trae-cache/sessions/*.json (synced via official usage API)
Trae data is not fetched automatically by the root command. Run token-stats trae login once, then token-stats trae sync before reports. Token Stats parses the synced API dumps as session-level records and preserves the cost totals reported by Trae.
Location: ~/.config/tokscale/warp-cache/usage.json (synced via authenticated GraphQL API)
Warp/Oz data is not fetched automatically by the root command. Run token-stats warp login, then token-stats warp sync before reports. Token Stats records only aggregate request counts and spend because Warp does not expose token-attributed local transcripts.
Location: $GROK_HOME/sessions/*/*/updates.jsonl (fallback: ~/.grok/sessions/*/*/updates.jsonl)
Grok Build data is parsed directly from local session updates. Current logs expose cumulative totalTokens counters without a stable input/output split, so Token Stats records positive per-turn deltas as input tokens. grok-composer-2.5-fast is temporarily mapped to the Composer 2.5 Fast pricing override until a dedicated public price is available.
Location: $JCODE_HOME/sessions/session_*.json (fallback: ~/.jcode/sessions/session_*.json) plus matching session_*.journal.jsonl sidecars.
Jcode data is parsed directly from local session snapshots. Token Stats reads assistant messages[].token_usage fields (input_tokens, output_tokens, cache_read_input_tokens, cache_creation_input_tokens, and reasoning_output_tokens) without spoofing another client identity. Matching journal sidecars are merged into the same session stream before deduplication so recent appended messages are included until Jcode checkpoints them into the snapshot. Stable message IDs are used for replay dedupe; malformed/custom records without IDs use a scoped fallback key.
Location: ~/.openclaw/agents/*/sessions/sessions.json (also scans legacy paths: ~/.clawdbot/, ~/.moltbot/, ~/.moldbot/)
Index file pointing to JSONL session files:
{
"agent:main:main": {
"sessionId": "uuid",
"sessionFile": "/path/to/session.jsonl"
}
}Session JSONL format with model_change events and assistant messages:
{"type":"model_change","provider":"openai-codex","modelId":"gpt-5.2"}
{"type":"message","message":{"role":"assistant","usage":{"input":1660,"output":55,"cacheRead":108928,"cost":{"total":0.02}},"timestamp":1769753935279}}Location: $HERMES_HOME/state.db (fallback: ~/.hermes/state.db) plus standard profile databases at $HERMES_HOME/profiles/*/state.db (or sibling ~/.hermes/profiles/*/state.db when HERMES_HOME points at an active profile)
Hermes stores session-level usage in a SQLite sessions table. Token Stats imports rows where model is present and token or cost totals are non-zero, uses started_at as the timestamp, preserves message_count, and prefers actual_cost_usd over estimated_cost_usd.
Location: ~/.pi/agent/sessions/<encoded-cwd>/*.jsonl and ~/.omp/agent/sessions/<encoded-cwd>/*.jsonl (Oh My Pi)
JSONL format with session header and message entries:
{"type":"session","id":"pi_ses_001","timestamp":"2026-01-01T00:00:00.000Z","cwd":"/tmp"}
{"type":"message","id":"msg_001","timestamp":"2026-01-01T00:00:01.000Z","message":{"role":"assistant","model":"claude-3-5-sonnet","provider":"anthropic","usage":{"input":100,"output":50,"cacheRead":10,"cacheWrite":5,"totalTokens":165}}}Location: ~/.kimi/sessions/{GROUP_ID}/{SESSION_UUID}/wire.jsonl
wire.jsonl format with StatusUpdate messages:
{"type": "metadata", "protocol_version": "1.3"}
{"timestamp": 1770983426.420942, "message": {"type": "StatusUpdate", "payload": {"token_usage": {"input_other": 1562, "output": 2463, "input_cache_read": 0, "input_cache_creation": 0}, "message_id": "chatcmpl-xxx"}}}Location: ~/.kimi-code/sessions/{WORKDIR}/{SESSION_UUID}/agents/{AGENT}/wire.jsonl
{"type":"usage.record","model":"kimi-code/kimi-for-coding","usage":{"inputOther":1163,"output":352,"inputCacheRead":22272,"inputCacheCreation":0},"usageScope":"turn","time":1780410897480}Location: ~/.qwen/projects/{PROJECT_PATH}/chats/{CHAT_ID}.jsonl
Format: JSONL — one JSON object per line, each with type, model, timestamp, sessionId, and usageMetadata fields.
Token fields (from usageMetadata):
promptTokenCount→ input tokenscandidatesTokenCount→ output tokensthoughtsTokenCount→ reasoning/thinking tokenscachedContentTokenCount→ cached input tokens
Location:
- Local:
~/.config/Code/User/globalStorage/rooveterinaryinc.roo-cline/tasks/{TASK_ID}/ui_messages.json - Server (best-effort):
~/.vscode-server/data/User/globalStorage/rooveterinaryinc.roo-cline/tasks/{TASK_ID}/ui_messages.json
Each task directory may also include api_conversation_history.json with <environment_details> blocks used for model/agent metadata.
ui_messages.json is an array of UI events. Token Stats counts only:
type == "say"say == "api_req_started"
The text field is JSON containing token/cost metadata:
{
"type": "say",
"say": "api_req_started",
"ts": "2026-02-18T12:00:00Z",
"text": "{\"cost\":0.12,\"tokensIn\":100,\"tokensOut\":50,\"cacheReads\":20,\"cacheWrites\":5,\"apiProtocol\":\"anthropic\"}"
}Location:
- Local:
~/.config/Code/User/globalStorage/kilocode.kilo-code/tasks/{TASK_ID}/ui_messages.json - Server (best-effort):
~/.vscode-server/data/User/globalStorage/kilocode.kilo-code/tasks/{TASK_ID}/ui_messages.json
Kilo uses the same task log shape as Roo Code. Token Stats applies the same rules:
- count only
say/api_req_startedevents fromui_messages.json - parse
tokensIn,tokensOut,cacheReads,cacheWrites,cost, andapiProtocolfromtextJSON - enrich model/agent metadata from sibling
api_conversation_history.jsonwhen available
Location:
- Linux desktop VS Code:
~/.config/Code/User/globalStorage/saoudrizwan.claude-dev/tasks/{TASK_ID}/ui_messages.json - macOS desktop VS Code:
~/Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/tasks/{TASK_ID}/ui_messages.json - Windows desktop VS Code:
%APPDATA%\Code\User\globalStorage\saoudrizwan.claude-dev\tasks\{TASK_ID}\ui_messages.json - Server (best-effort):
~/.vscode-server/data/User/globalStorage/saoudrizwan.claude-dev/tasks/{TASK_ID}/ui_messages.json
Cline is the upstream project that Roo Code and Kilo forked from, so it uses the same VS Code globalStorage task log shape. Token Stats applies the same rules:
- count only
say/api_req_startedevents fromui_messages.json - parse
tokensIn,tokensOut,cacheReads,cacheWrites,cost, andapiProtocolfromtextJSON - enrich model/agent metadata from sibling
api_conversation_history.jsonwhen available
Location:
~/.mux/sessions/{WORKSPACE_ID}/session-usage.json
Mux stores cumulative per-session token usage in session-usage.json files. Each file contains a byModel map with per-model token breakdowns:
input,cached(cache reads),cacheCreate(cache writes),output,reasoning- Model names use
provider:modelformat (e.g.,anthropic:claude-opus-4-6) — token-stats strips the provider prefix for model identification - Sub-agent usage is automatically rolled up into parent sessions by Mux, so there is no double-counting
Location: ~/.local/share/kilo/kilo.db
Kilo CLI stores session data in a SQLite database similar to OpenCode. Each message row contains per-message token breakdowns (input, output, cache read/write, reasoning) with model and provider attribution.
Location: Project-level SQLite databases discovered via $XDG_DATA_HOME/crush/projects.json (fallback: ~/.local/share/crush/projects.json)
Crush stores usage in per-project SQLite databases (crush.db). Token Stats imports session-level cost totals from root sessions only, because Crush does not expose reliable per-message or per-model token accounting. Records appear as model=session-total with zero token breakdown.
Location: ~/.local/share/goose/sessions/sessions.db (also scans ~/Library/Application Support/goose/, ~/Library/Application Support/Block/goose/, ~/.local/share/Block/goose/; override via GOOSE_PATH_ROOT)
Goose stores per-session usage in a SQLite sessions.db. Token Stats extracts the model from model_config_json, the provider from provider_name, and accumulated input/output token totals per session. Reasoning tokens are inferred when the column is populated.
Location: ~/.config/manicode/projects/<project>/chats/<chatId>/chat-messages.json (also scans manicode-dev and manicode-staging channels; override via CODEBUFF_DATA_DIR)
Codebuff (formerly Manicode) writes per-chat JSON files. Token Stats parses token usage from metadata.usage, metadata.codebuff.usage, and the run-state messageHistory[*].providerOptions fallback, walking the history in reverse so partial newer entries don't shadow earlier entries that carry the actual token counts. Per-message timestamps fall back to the chat-id directory name and finally to file mtime when missing.
Location: ~/.gjc/agent/sessions/<project-slug>/*.jsonl (override the agent dir via GJC_CODING_AGENT_DIR; also resolves GJC_CONFIG_DIR/PI_CONFIG_DIR joined with agent/sessions, and the flattened $XDG_DATA_HOME/gjc/sessions/ redirect on Linux/macOS). Depth-2 per-pass sub-agent transcripts (<slug>/<session>/N-*.jsonl) are discovered too.
JSONL format with a session header and message entries. Token Stats emits only assistant messages and reuses gjc's authoritative per-message usage.cost.total (USD) when present, recomputing from tokens only when it is absent:
{"type":"session","id":"S1","timestamp":"2026-01-01T00:00:00.000Z","cwd":"/work/proj"}
{"type":"message","id":"M1","timestamp":"2026-01-01T00:00:01.000Z","message":{"role":"assistant","model":"claude-sonnet-4","provider":"anthropic","usage":{"input":1000,"output":500,"cacheRead":0,"cacheWrite":0,"totalTokens":1500,"cost":{"input":0.1,"output":0.2,"total":0.3}}}}Messages dedup by <session id>:<message id> (with a deterministic fallback) so replayed depth-1/depth-2 transcripts are counted once. service_tier_change and malformed lines are skipped per line.
Synthetic usage is detected via post-processing of existing agent session files. Messages are re-attributed to synthetic when they use hf: model IDs or synthetic providers (synthetic, glhf, octofriend).
Token Stats also checks Octofriend SQLite at ~/.local/share/octofriend/sqlite.db and parses token-bearing records when available.
Location: ~/.local/share/mimocode/mimocode.db (XDG data directory)
MiMo Code stores session data in a SQLite database. Token Stats queries the message table joined with session for workspace context:
SELECT m.id, m.session_id, m.data, NULLIF(s.directory, '') AS workspace_root
FROM message m
LEFT JOIN session s ON s.id = m.session_id
WHERE json_extract(m.data, '$.role') = 'assistant'
AND json_extract(m.data, '$.tokens') IS NOT NULLThe data column is a JSON blob with the following token-relevant fields:
{
"role": "assistant",
"modelID": "claude-sonnet-4",
"providerID": "anthropic",
"cost": 0.0032,
"tokens": {
"input": 1200,
"output": 450,
"reasoning": 0,
"cache": { "read": 800, "write": 0 }
},
"time": { "created": 1780410897000, "completed": 1780410912000 },
"agent": "micode",
"path": { "root": "/Users/me/project" }
}Token Stats deduplicates messages across forked sessions using a fingerprint of timestamps, model, provider, token counts, cost, and agent name.
Token Stats fetches real-time pricing from LiteLLM's pricing database.
Dynamic Fallback: For models not yet available in LiteLLM (e.g., recently released models), Token Stats automatically fetches pricing from OpenRouter's endpoints API. This ensures you get accurate pricing from the model's author provider (e.g., Z.AI for glm-4.7) without waiting for LiteLLM updates.
Cursor Model Pricing: For very recently released models not yet in either LiteLLM or OpenRouter (e.g., gpt-5.3-codex), Token Stats includes hardcoded pricing sourced from Cursor's model docs. These overrides are checked after all upstream sources but before fuzzy matching, so they automatically yield once real upstream pricing becomes available.
Sakana Fugu Pricing: Fugu Ultra cost is estimated from Sakana's published pay-as-you-go rates; the fugu router model is intentionally left unpriced because its cost is the variable rate of whichever underlying model it orchestrated.
Caching: Pricing data is cached to disk with 1-hour TTL for fast startup:
- LiteLLM cache:
~/.config/tokscale/cache/pricing-litellm.json - OpenRouter cache:
~/.config/tokscale/cache/pricing-openrouter.json(caches author pricing for models from supported providers)
Pricing includes:
- Input tokens
- Output tokens
- Cache read tokens (discounted)
- Cache write tokens
- Reasoning tokens (for models like o1)
- Model-specific tiered pricing (for example, above 200k or 272k tokens)
Contributions are welcome! Please follow these steps:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run tests (
cd packages/core && bun run test:all) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow existing code style
- Add tests for new functionality
- Update documentation as needed
- Keep commits focused and atomic
- ccusage, viberank, and Isometric Contributions for inspiration
- Ratatui for terminal UI framework
- Solid.js for reactive rendering
- LiteLLM for pricing data
- napi-rs for Rust/Node.js bindings
- github-contributions-canvas for 2D graph reference
MIT © Junho Yeo
If you find this project intriguing, please consider starring it ⭐ or follow me on GitHub and join the ride (1.1k+ already aboard). I code around the clock and ship mind-blowing things on a regular basis—your support won't go to waste.


















































