Model or dataset
crwdla/tokentab avatar
crwdla/tokentab

tokentab: a local CLI for costing Claude Code, Codex and Gemini CLI sessions

A CLI that reads Claude Code, Codex, and Gemini CLI session logs and works out how much they cost, by model, project, and day.

1,138 stars215 forksPythonMIT

At a glance

What is it?
tokentab parses the session logs your AI coding tools already write to disk and turns them into token and dollar totals by model, project and day. It runs offline, prices from a hand-kept table, and ships both a terminal view and a small browser dashboard.
Who is it for?
Adopt tokentab if you already run Claude Code, Codex or Gemini CLI and want per-project and per-day cost numbers without sending logs anywhere; the module-per-provider design in tokentab/providers/ also makes it a reasonable base for a custom parser. Skip it if Cursor is your main tool, since that parser is a stub, or if you need a live pricing feed, because prices come from the hand-kept table in tokentab/pricing/prices.py.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 9 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 16, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The bill you cannot itemise

Subscription and API spend on AI coding tools is easy to accumulate and hard to break down. The tools themselves report usage, but not usually in a form that answers the question an engineer actually has: which project, which model, which day, and what kind of work consumed the tokens. tokentab exists to answer that from data already on the machine. It is aimed at individual developers and small teams who run Claude Code, Codex or Gemini CLI locally and want a cost breakdown without forwarding session logs to a hosted analytics service. The README is explicit that it runs entirely locally, with no account and no API key. That positioning matters, because the input is your source code context and your prompts. The tool never leaves the machine, and the dashboard binds to localhost only.

Three parsers behind one UsageRecord shape

The architecture is deliberately flat. Each supported tool has a module under tokentab/providers/ that exposes a collect() function returning a list of UsageRecord objects, defined in tokentab/types.py. Everything downstream (pricing, grouping, the terminal tables, the dashboard) only touches that one shape. Adding a provider means writing the module and registering it in tokentab/providers/__init__.py. The README points at Claude's parser as the simplest template. Token counts are read from the logs rather than estimated, since each tool records its own per-call counts. The one correction applied is caching: Claude reports cache reads and writes separately, while Gemini reports input including the cached portion, so tokentab subtracts cached tokens before pricing to avoid charging twice for the same tokens. Activity labels such as coding, debugging or refactor are inferred deterministically from tool usage and the first message of a session; the README calls this a hint rather than gospel, and that is the right framing for a heuristic with no model calls behind it.

Installing tokentab and reading your first week

The README's install path is a clone plus a pip install into your environment, which puts a tokentab command on your PATH.

bash
git clone https://github.com/crwdla/tokentab
cd tokentab
pip install .
python cli.py

The bare command reports the last 7 days across every tool it can find. If a tool is not installed, it is skipped, so you only see providers you actually use. The README also shows an editable install for running from source, which is the mode you want if you intend to edit a provider.

bash
pip install -e .
tokentab

For a specific window, the flags are --from and --to. To make the output machine-readable, pipe it through jq. This is the fastest way to spot a model that failed to match the pricing table, because those rows come out as $0.00.

bash
python cli.py --from 2026-06-01 --to 2026-06-15
python cli.py --json | jq .

The browser view is a single flag. It opens http://localhost:4747 and lays the same numbers out as a monthly statement, reading from disk on every request rather than caching. Pass --port to change the port or --no-open to stop it launching a browser. It is built on Python's standard-library HTTP server, and the README notes it does not pull fonts from a CDN, so it works with the network unplugged.

bash
python cli.py -web

Where tokentab stops being useful

The pricing table in tokentab/pricing/prices.py is maintained by hand, in dollars per million tokens. The README defends this as a deliberate trade: the tool never reaches out to the network to price anything, and a slightly stale number beats a crash when a vendor renames a model. The cost of that choice lands on you. When a model name does not match the table, the row reports $0.00, and the CLI says so rather than silently counting it as free. Model matching is fuzzy, so claude-opus-4-6-20260514 still resolves to claude-opus-4-6, but a genuinely new model needs a one-line edit before its cost is real. Two other boundaries are worth stating plainly. Cursor is described as a stub that is wired up but not finished, so anyone whose spend is mostly in Cursor gets an incomplete total. And the activity breakdown is a deterministic guess based on tool usage and the first message of a session; it is fast and inspectable, but it is not a classification you should put in a report without checking. The README's own reading guide treats patterns like a cache hit rate under 80% as starting points, not verdicts, and that is the correct level of confidence to place in the derived fields.

How it compares with hosted usage dashboards

The obvious alternative is a vendor dashboard or a hosted observability product for LLM spend. Those usually work by instrumenting your application or routing calls through a proxy, which gives near-real-time numbers and alerting, and works for any provider you configure. tokentab takes the opposite route: it reads logs that already exist on disk, so there is nothing to instrument and no traffic to reroute, but the numbers arrive only after a session has been written and only for the three tools whose log formats it implements. The practical difference shows up in two places. A hosted tool can price a model the day the vendor announces it; tokentab cannot until someone edits prices.py or opens a one-line PR. Conversely, a hosted tool requires your prompts and file context to leave the machine, which tokentab is specifically built to avoid. If you need per-request latency and error tracking alongside cost, tokentab is the wrong shape entirely, because it only knows what the session logs record.

Maintenance, dependencies and the MIT licence

The dependency surface is small: rich for terminal tables, everything else from the Python standard library, including the web server and the JSON handling. That keeps the upgrade cost low, and it means a Python 3.10 or newer interpreter is the main environmental requirement, per pyproject.toml. The project is MIT licensed, so redistribution and modification are permitted; the usual caveat applies that this is a description of the licence text, not legal advice, and the pricing table you maintain is your own problem either way. On cadence: the repository is not archived, and the last push was on 2026-09-07. There are no retrieved releases, and the version in pyproject.toml is 0.1.0, so the README's clone-and-install instructions are the supported path rather than a package index. The README invites stale-price fixes as a one-line PR or an issue. If you extend a provider, note that the README does not document rollback or migration for changes to the UsageRecord shape, so treat tokentab/types.py as a stable interface if you have written your own parser against it.

Editorial conclusion

Adopt tokentab if you already run Claude Code, Codex or Gemini CLI and want per-project and per-day cost numbers without sending logs anywhere; the module-per-provider design in tokentab/providers/ also makes it a reasonable base for a custom parser. Skip it if Cursor is your main tool, since that parser is a stub, or if you need a live pricing feed, because prices come from the hand-kept table in tokentab/pricing/prices.py. Before trusting a total, run python cli.py --json and check whether any model reports $0.00, which means the model name did not match that table.

Frequently asked questions

How much text is 1000 tokens?

The README does not give a characters-per-token ratio. tokentab does not estimate tokens from text at all; it reads the per-call token counts that Claude Code, Codex and Gemini CLI record in their own session logs.

What is token count?

In tokentab, the token count is the figure each supported tool writes into its session log for every call, split so that cached tokens are not priced twice. Claude reports cache reads and writes separately, and Gemini reports input including the cached part, so tokentab subtracts the cached tokens before pricing.

What is token used for?

tokentab uses token counts to produce cost totals by model, project and day, plus an activity breakdown such as coding, debugging or testing. The activity label is inferred from which tools were used and the wording of the first message in a session, and the README describes it as a hint rather than a verdict.

Is there a token calculator?

tokentab is one, but it calculates from logs rather than from pasted text. It matches model names against the hand-kept table in tokentab/pricing/prices.py, and a model that does not match shows up as $0.00 with a note from the CLI.

Official sources

  1. crwdla/tokentab on GitHub
  2. Issues
  3. License: MIT
  4. README
Community notes

Community notes