Aggregate and analyze AI coding assistant token consumption (Claude, Codex, Cursor, Kiro, Gemini)
Project description
tokstat
CLI toolkit to aggregate and analyze AI coding assistant token consumption. Each tool scans local data, estimates costs using live LiteLLM pricing, and prints color-coded terminal tables.
On our test account, Tokstat’s estimation of Claude Code usage matched Anthropic billing with approximately 95% accuracy over 30 days. Accuracy varies by tool — Claude Code, Codex, Gemini CLI and opencode read exact token counts; Cursor reads exact counts where they're recorded locally and flags the rest as
⚠ no data; Kiro exposes no token counts at all (activity only); the web exports are estimated from text length. Tokstat provides estimates only, and we disclaim any responsibility or liability for differences between estimated and actual billing.
Changelog
- 1.8.1 —
--impact: add a prefill/context energy term. EcoLogits' formula bills energy from output tokens only (decode phase), which badly undercounts cache-heavy agentic use where output is ~0.4% of token traffic. Input + cache writes are now counted at a reduced prefill rate and cache reads at a small memory-movement rate (physics-grounded fractions of a decode token, widening the ± band). Typically lifts the headline ~2–4×. The frugality verdict stays decode-only so the mascot still grades model choice, not context volume. - 1.8.0 —
--impactmode: energy (kWh) and CO₂e estimate of the observed activity, reusing the EcoLogits methodology and model database (fetched + cached locally, no dependency). Usage phase only, with a single headline figure + ±% uncertainty and a configurable electricity mix (--impact eu,france, …). Includes a mascot-graded frugality verdict (Wh per 1k output tokens), a per-bucket Trend table (Δ vs previous day/week/month), a plain-language Analysis, and per-tool / per-model breakdowns with measurable data spans. Large swings (> ~5×) are described ("ramping up", "rose sharply") rather than quoted as misleading percentages. An energy/CO₂ line also appears on--activity. - 1.7.0 —
--totalmode: a compact badge of total tokens + cost for the selected period/tool, with the data's actual date span and a per-tool breakdown (each tool's own date range). New--periodoptions:1 month,2 months,3 months,6 months(unquoted--period 3 monthsworks too).--activityshows the year on its own row above the months. - 1.6.0 —
--activitymode: a GitHub-style contribution calendar of daily activity over the period, colored by prompts/day, with the year shown at year boundaries and a summary of total prompts / turns / tokens and the busiest day. Reads directly from the scanned exchanges (history depth is limited by what each tool keeps on disk — see each tool's retention, e.g. Claude Code'scleanupPeriodDays, default 30). - 1.5.1 — Codex token accounting fixed (cached input and reasoning tokens no longer double-counted); Cursor rewritten onto its SQLite store (exact counts where recorded,
⚠ no dataotherwise — never estimated); Kiro rewritten onto its per-session format (activity only);⚠ no dataflag for rows without reliable token data; per-tool anomaly thresholds; per-provider plan recommendations. codex / cursor / kiro promoted to stable. - 1.5.0 — Unified
tokstatcommand across all tools;--watchlive mode; Prompts / Turns / API columns + GRAND TOTAL block; addedopencode-token-usage,claude-web-token-usage,chatgpt-web-token-usage(official-export import). - 1.4.x —
--versionflag; subagent sessions included in the Claude Code scan; update-check fix.
Installation
pip install tokstat
Requires Python 3.7+. No dependencies. MIT License.
Tools
| Command | Agent | Data source | Tokens | Cost | Status |
|---|---|---|---|---|---|
tokstat |
all of the below | combined | all of the below | ✓ | stable |
claude-token-usage |
Claude Code | ~/.claude/projects/ |
✓ exact | ✓ | stable |
codex-token-usage |
Codex (OpenAI) | ~/.codex/sessions/ |
✓ exact | ✓ | stable |
cursor-token-usage |
Cursor | globalStorage/state.vscdb |
n.a. | n.a. | stable |
kiro-token-usage |
Kiro | Kiro/.../workspace-sessions/ |
n.a. | n.a. | stable |
gemini-token-usage |
Gemini CLI | ~/.gemini/tmp/ |
✓ exact | ✓ | experimental |
opencode-token-usage |
opencode | ~/.local/share/opencode/ |
✓ exact | ✓ | experimental |
claude-web-token-usage |
claude.ai (web export) | --import of official ZIP |
~ estimated | ~ | experimental |
chatgpt-web-token-usage |
chatgpt.com (web export) | --import of official ZIP |
~ estimated | ~ | experimental |
tokstat runs all scanners and aggregates their records into a single overview. Use --tool <name> to scope to one tool, or stick with the per-tool commands for detail.
Experimental tools parse undocumented local formats that may change without notice. Data may be incomplete or inaccurate.
Cursor note: tokstat reads Cursor's local SQLite store (
globalStorage/state.vscdb). Some sessions have token counts recorded locally — these are reported exactly ([exact]). Others store no token counts (the local values are zero); those are tagged[no tokens], counted as activity (prompts/turns), and never estimated — their cost shows⚠ no data. For authoritative totals use the Cursor dashboard.Kiro note: Kiro stores no usable token counts locally (its token log is always zero), so
kiro-token-usagereports activity only — prompts and turns — with tokens and cost left blank. It does not estimate.No-data flag: any row whose tool/session has activity but no reliable local token data shows
⚠ no datain the cost column (instead of a misleading$0.00). This is normal for Kiro and recent Cursor sessions.
Web exports (claude.ai / chatgpt.com)
The two web tools work from the official data export each provider lets you request from your account settings. There is no live scraping — past attempts ran into 30-second per-request rate limits, anti-bot filters, and gray-area ToS questions. Stick to the export and tokstat reads it locally.
- Request the export
- claude.ai: Settings → Privacy → Export Data
- chatgpt.com: Settings → Data controls → Export data
- Wait for the email with the ZIP download link.
- Import:
claude-web-token-usage --import path/to/claude-export.zip chatgpt-web-token-usage --import path/to/chatgpt-export.zip
- Run normally; the cache under
~/.cache/tokstat/web/<service>/is now the source of truth:claude-web-token-usage --period all chatgpt-web-token-usage --prompts --period "30 days" tokstat --tool chatgpt
Multiple accounts (perso + work) can coexist — add --account <name> on each --import. Each shows up as a separate row under CONSUMPTION BY PROJECT.
Cache management for the web tools:
claude-web-token-usage --list-accounts # show imported accounts
chatgpt-web-token-usage --clear-imports # drop all imported conversations
chatgpt-web-token-usage --clear-imports --account work
chatgpt-web-token-usage --clean-cache # drop legacy pre-import cache files
Token counts are estimated from message text length (chars / 4); models shown carry a [est] suffix. Real billing may differ.
Modes
All tools support the same modes:
<tool> # Aggregated overview (period, project, model, speed)
<tool> --prompts [-p] # Per-exchange detail (text, turns, tokens, tools, cost)
<tool> --anomalies # Technical anomaly detection
<tool> --activity # GitHub-style activity calendar (by day) + tokens
<tool> --total # Compact totals (tokens + cost + data span)
<tool> --impact [region] # Energy & CO₂ estimate (EcoLogits); region = world (default), eu, …
<tool> --plan # Cost breakdown + per-provider plan recommendation
<tool> --export [file.json] # Export all exchanges to JSON
<tool> --version [-V] # Print version
<tool> --help [-h] # Usage
The overview, project, and model tables include Prompts (user inputs),
Turns (assistant turns per exchange), and API (raw API calls) columns,
plus a GRAND TOTAL block with the rolling-hour token rate and the active
agents. Rows that have activity but no reliable local token data show
⚠ no data in the cost column rather than a misleading $0.00.
tokstat additionally supports a live mode:
tokstat --watch [-w] # Refresh the overview in place (default 5s)
tokstat --watch 10 # ...every 10 seconds
Changed rows are flagged with a ◆ between refreshes; press Ctrl+C to stop.
Default — aggregated overview
claude-token-usage
claude-token-usage --period all
codex-token-usage --period "7 days"
cursor-token-usage --period "30 days"
--prompts — per-exchange detail
Per-exchange breakdown: user text, model, turns, tokens (input/output/cache), tool calls, cost.
claude-token-usage --prompts
claude-token-usage -p --period "7 days"
--anomalies — technical anomaly detection
Detects unusual patterns in per-exchange token data. Results grouped by project.
claude-token-usage --anomalies
claude-token-usage --anomalies --period "30 days"
| Anomaly | Trigger | Severity |
|---|---|---|
| Runaway cost | Prompt costs 10x+ the tool's P90 | HIGH |
| High cost | Prompt costs 5x+ the tool's P90 | MEDIUM |
| Tool storm | 30+ tool calls in a single prompt | HIGH >60, MEDIUM >30 |
| Turn spiral | API turns 5x+ the tool's P90 | HIGH >10x, MEDIUM >5x |
| Cache thrashing | High cache writes with <50% read-back | MEDIUM |
| Context bloat | Input/output ratio 2x+ the tool's P90 (min 50:1) | LOW |
| Empty exchange | 5+ turns but <100 output tokens | MEDIUM |
Thresholds are computed dynamically per tool (median, P90) — a costly Codex prompt is judged against Codex, not against the whole fleet — so structurally input-heavy or expensive tools don't drown the report in false positives.
--activity — activity calendar
A GitHub-style contribution calendar: one cell per day, colored by prompts/day,
with a summary of total prompts / turns / tokens, the busiest day, and a
one-line energy & CO₂ estimate (see --impact for the detailed breakdown).
tokstat --activity --period all
tokstat --activity --tool claude --period "30 days"
⚠️ History depth depends on each tool's retention. tokstat can only show days whose transcripts are still on disk. Claude Code prunes its transcripts after
cleanupPeriodDays(default 30 days) — so by default the Claude activity calendar goes back ~30 days only, and older days are gone for good. To keep more, raise the limit in~/.claude/settings.json, e.g.{ "cleanupPeriodDays": 365 }. Codex, by contrast, keeps all sessions (no automatic cleanup).
--total — compact totals
A one-glance summary of total tokens and cost for the selected period/tool, with the actual date span the data covers and a per-tool breakdown.
tokstat --total --period "30 days"
tokstat --total --tool codex --period all
╭───────────────────────────────────────────────╮
│ TOTAL · Last 30 days │
│ │
│ $697.03 953.1M tokens │
│ in 9.4M · out 2.4M · cache 922.6M/18.7M │
│ │
│ 577 prompts · 2614 turns · 25 active day(s) │
│ 2026-05-19 → 2026-06-18 │
╰───────────────────────────────────────────────╯
By tool:
Claude Code $517.32 717.8M tokens · 422 prompts · 2026-05-19 → 2026-06-18
Codex $179.70 235.3M tokens · 147 prompts · 2026-05-23 → 2026-06-15
--impact — energy & CO₂ estimate
Estimates the environmental impact of the observed activity, reusing the EcoLogits methodology and model database (fetched and cached locally, like the pricing data — no extra dependency).
tokstat --impact --period "30 days"
tokstat --impact --tool claude --period all
╭───────────────────────────────────────────╮
│ ENERGY & CO₂ · Last 30 days │
│ │
│ 🐘 ~11.5 kWh · ~4.8 kg CO₂e heavy │
│ ± 31% · 4.8 Wh/1k · trend ↗ growing (+12%) │
│ │
│ ≈ 40 km by car · 955 phone charges │
│ mix: world (0.418 kgCO₂e/kWh) · PUE 1.2 │
╰───────────────────────────────────────────╯
Trend (per week) — Δ vs previous week:
bucket tokens energy Δ CO₂e Wh/1k Δ
2026-04-13 42.1M 0.58kWh — 0.24kg 4.6 —
2026-04-20 38.7M 0.52kWh -11% 0.22kg 4.9 +12%
...
Analysis (first vs second half of the period)
• Electricity use rose sharply (0.26 → 2.63 kWh per week).
• CO₂ followed the same path — ~8.4 kg CO₂e total over the window.
• Frugality worsened 18% (heavier model mix): 4.1 → 4.8 Wh per 1k output tokens.
By tool (data span used):
Claude Code 9.82 kWh · 4.10 kg CO₂e 2026-04-14 → 2026-06-19
Codex 9.61 kWh · 4.02 kg CO₂e 2026-01-21 → 2026-06-15
...
By model (measurable span):
gpt-5.5 [xhigh] 8.74 kWh · 3.65 kg CO₂e 2026-01-21 → 2026-06-15
claude-opus-4-7 4.98 kWh · 2.08 kg CO₂e 2026-04-14 → 2026-06-19
...
The Trend section buckets the period by day (≤ ~1 month), week
(≤ ~6 months) or month (longer) — granularity follows --period — and
shows the period-over-period change (Δ %) for both consumption (energy) and
frugality (Wh per 1000 output tokens). Green = down/better, red = a sharp
increase, so you can see whether you're consuming more and whether your model
mix is getting lighter or heavier. A short Analysis then spells out the
trajectory in plain language (electricity, CO₂, frugality), comparing the first
half of the period to the second. When a swing is larger than ~5×, the baseline
is too small for a percentage to mean anything (e.g. an adoption ramp over
--period all), so the wording becomes descriptive — "rose/dropped sharply" in
the Analysis, "ramping up"/"winding down" on the badge — instead of a misleading
number like "+99041%".
The per-model span is the measurable period — the union of the data spans of every tool that carries that model (e.g. a model used in both opencode and Claude Code spans the union of both), since that's how far back its usage could be observed.
The badge headline carries a mascot animal for the footprint weight and a trend arrow (↘ shrinking / → stable / ↗ growing, first half vs second half of the period). The animal grades your frugality — Wh per 1k output tokens, weighted across your whole model mix — so it's comparable across users regardless of volume:
| Wh / 1k output | verdict | typical models |
|---|---|---|
| < 1 | 🐜 very light | haiku, gpt-4o-mini |
| < 2.5 | 🦥 frugal | sonnet, gpt-4o |
| < 4 | 🦊 moderate | light mixes |
| < 10 | 🐘 heavy | current frontier: opus-4-7/4-8, gpt-5.x (~5–6) |
| ≥ 10 | 🦣 very heavy | legacy dense giants: opus-4-1, gemini-2.5-pro (~25) |
The thresholds are anchored to EcoLogits' active-parameter estimates: a mostly-Opus diet reads heavy, and "very heavy" is the old dense-600B-class tier. Because closed-model parameter counts are estimated, the exact band can shift as EcoLogits updates its database. (The verdict uses decode-only energy — energy per generated token — so it grades your model choice, not how much context you feed; the headline kWh/CO₂ figure does include the context.)
Prefill / context energy
EcoLogits' published formula bills energy from output tokens only — it
models the decode phase, which is fine for chat (output ≈ input) but badly
undercounts agentic/cache-heavy use, where each generated token rides on orders
of magnitude more context (for Claude Code, cache reads alone are often 95 %+ of
all token traffic). tokstat adds an approximate prefill term: fresh input +
cache writes, and cache reads, each counted at a fraction of a decode token's
energy. The fractions are grounded in transformer physics — prefill does the
same ~2·N_active FLOPs per token as decode but at far higher hardware
utilization (≈ 0.03–0.12×), and a cache-read token skips the FFN recompute
entirely (≈ 0.0005–0.006×). These are deliberately wide ranges that widen the
± band rather than feign precision; override them in impact.json if you have
better numbers. Typically this lifts the headline ~2–4× versus decode-only.
⚠️ Order-of-magnitude estimate, usage phase only. Energy is derived from token counts × the model's (estimated) active parameters — output tokens at the decode rate, plus input/cache at the reduced prefill rates above. For closed models like Claude/GPT, EcoLogits estimates the parameter count, hence the min–max range. It excludes hardware manufacturing (the embodied phase needs per-request GPU data tokstat doesn't have). Models absent from the EcoLogits database are excluded and reported.
Choose the electricity mix by passing a region to --impact (default world):
tokstat --impact eu
tokstat --impact france --period "30 days"
Presets: world (default, 0.418), eu (0.250), france (0.056), us (0.369),
green (0.040) kgCO₂e/kWh — or pass an explicit factor (--impact 0.3). To make
it permanent, set it in ~/.config/tokstat/impact.json:
{ "region": "france", "pue": 1.2 }
--plan — plan & optimization recommendations
Cost breakdown by model, a plan recommendation per upstream provider
(Anthropic, OpenAI, Google — local/no-cost models are ignored), and
data-driven optimization advice. With tokstat this spans every tool; with a
per-tool command it's scoped to that one.
tokstat --plan --period "30 days"
claude-token-usage --plan --period all
Last 30 days — 21 active days / 30
Model Calls Cost Avg/day Projected/mo Cache Share
───────────────── ───── ─────── ──────── ──────────── ───── ─────
gpt-5.5 [xhigh] 1132 $783.28 $26.11/d $783.28/mo 98% 51%
claude-opus-4-7 298 $277.99 $9.27/d $277.99/mo 98% 18%
...
TOTAL 1176 $1290.51 $44.50/d $1335.01/mo 98%
Plan (based on Last 30 days)
OpenAI (GPT) — ChatGPT Pro ($200/mo) for chat, API direct for Codex. $1056.32/mo projected
Anthropic (Claude) — Max 20x ($200/mo) strongly recommended. $277.99/mo projected
--export — conversation export
Exports all exchanges to a JSON file.
claude-token-usage --export
claude-token-usage --export out.json --period "7 days"
{
"tool": "Claude Code",
"model": "claude-opus-4-6",
"timestamp": "2026-04-08T...",
"user": "the user prompt text",
"assistant": ["response 1", "response 2"],
"turns": 25,
"tools_used": {"Bash": 3, "Read": 7, "Edit": 2},
"tool_errors": ["error message"]
}
Filters
All modes support --period:
--period <period> all, hour, "5 hours", today, yesterday, "7 days", "30 days",
"1 month", "2 months", "3 months", "6 months", year
default: today — partial match works ("7" = "Last 7 days")
With --period all, the CONSUMPTION BY PERIOD table shows every window from
Last hour through Last year, plus a Forever row aggregating the entire
available history.
Pricing
Model pricing is fetched from LiteLLM's model pricing database and cached at ~/.cache/token-usage/litellm_prices.json for 24 hours. Falls back to stale cache if fetch fails.
Credits
Environmental-impact estimates (--impact) use the methodology and model database of EcoLogits (MPL-2.0), fetched and cached locally.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tokstat-1.8.1.tar.gz.
File metadata
- Download URL: tokstat-1.8.1.tar.gz
- Upload date:
- Size: 70.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
71323194fbb30500654b0eed482a07058f10e405171461dfd8cb1e46aa6d89d4
|
|
| MD5 |
e9c6fd6ba9c6d26d4310279af04e7954
|
|
| BLAKE2b-256 |
b564d9cd864efb462d8904169e2dc631a391e0eff0e9fbafed00007d0702b2d5
|
Provenance
The following attestation bundles were made for tokstat-1.8.1.tar.gz:
Publisher:
publish.yml on thiga-co/tokstat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tokstat-1.8.1.tar.gz -
Subject digest:
71323194fbb30500654b0eed482a07058f10e405171461dfd8cb1e46aa6d89d4 - Sigstore transparency entry: 1915676000
- Sigstore integration time:
-
Permalink:
thiga-co/tokstat@7501d23a2ed7b52ecff991c8a9155de6832f6c5f -
Branch / Tag:
refs/tags/v1.8.1 - Owner: https://github.com/thiga-co
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7501d23a2ed7b52ecff991c8a9155de6832f6c5f -
Trigger Event:
release
-
Statement type:
File details
Details for the file tokstat-1.8.1-py3-none-any.whl.
File metadata
- Download URL: tokstat-1.8.1-py3-none-any.whl
- Upload date:
- Size: 85.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b8268ba879c68b1a180c5c29d1bd5934df22cdfe7cf3d83ce9c1f2a931a9ff8f
|
|
| MD5 |
a18c58e4d935fa7d9ec2e7dd369eaa35
|
|
| BLAKE2b-256 |
d200a65fcd645245b6cc94ba1b5090d909b7a64ba8be54b3b5e48bd649ecdf1f
|
Provenance
The following attestation bundles were made for tokstat-1.8.1-py3-none-any.whl:
Publisher:
publish.yml on thiga-co/tokstat
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tokstat-1.8.1-py3-none-any.whl -
Subject digest:
b8268ba879c68b1a180c5c29d1bd5934df22cdfe7cf3d83ce9c1f2a931a9ff8f - Sigstore transparency entry: 1915676243
- Sigstore integration time:
-
Permalink:
thiga-co/tokstat@7501d23a2ed7b52ecff991c8a9155de6832f6c5f -
Branch / Tag:
refs/tags/v1.8.1 - Owner: https://github.com/thiga-co
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7501d23a2ed7b52ecff991c8a9155de6832f6c5f -
Trigger Event:
release
-
Statement type: