tokenstat
tokenstat
Getting started

Is tokenstat safe to run?

György
Reviewed by
György
Updated Jul 30, 2026 6 min

It is a fair question, and the honest answer starts with an uncomfortable fact: tokenstat opens files that contain your prompts and your source code. It has to. Your coding tools write their session logs to disk, the token counts live inside those logs, and there is no way to add up numbers in a file without reading the file.

Any usage tracker that tells you it "never reads your prompts" is describing something its own file access contradicts. So the promise here is not about the read. It is about the boundary: what survives the read, where it is allowed to go, and what stops it going anywhere else.

The short version

  • Everything runs on your machine. There is no account required, and nothing is uploaded unless you deliberately set up sync.
  • Conversation text is dropped at the parser. It never reaches the local database.
  • The part of the code that reads your logs cannot open a network connection, because it does not link a network stack at all.
  • No API keys. tokenstat never proxies a request, never holds a credential for a model vendor, and never asks a vendor about your account.
  • The source is GPL-3.0 and public, so none of the above has to be taken on trust.

What actually gets kept

When tokenstat parses a session log it is looking for a small set of counters: how many input tokens, output tokens, cache reads and cache writes, against which model, on which day, from which tool. Those numbers go into a local SQLite database. The prompt text, the file contents, the model's replies and everything else are discarded as the parser walks past them.

The practical test is this: if your tokenstat.db leaked tomorrow, it would expose numbers, not conversations. That is a much smaller blast radius than the log files it was built from, and those log files were already sitting on your disk before tokenstat existed.

Locally, your reports show real project names and real model names, because that is genuinely useful and it stays on your machine. Nothing is anonymised for your own eyes.

What leaves your machine

By default, nothing at all. tokenstat with no account is a local tool that reads local files and prints tables in your terminal.

If you choose to sync a machine to a profile on tokenstat.ai, the payload is deliberately narrow: dates, token counts, model identifiers, and opaque keys. Project names are replaced with salted hashes, and the salt never leaves your machine, which means the hashes cannot be reversed by anyone, including me.

There is nowhere in that payload for a file path, a prompt, a repository name, or a hostname to hide. You do not have to believe that:

tokenstat sync --dry-run

That prints the exact canonical JSON that would be uploaded, and exits without uploading it. Read it before you ever run a real sync. If a future version starts sending something new, this command is where you would see it.

The schema the server accepts is strict: unknown fields are rejected rather than ignored. A future version cannot quietly start sending a file path and have the server quietly accept it.

Why the boundary holds

Policies are promises. This one is structural instead.

The code is split into separate crates, and the split is the point:

Crate What it does Can it reach the network?
tokenstat-core Parsing, normalisation, pricing, aggregation No. It does not link a network stack
tokenstat-cli The command line you actually run No
tokenstat-sync Uploads the aggregate payload Yes, and only this one
tokenstat-mcp Lets an agent query its own spend No

The crate that reads your logs has no ability to send them anywhere, because the capability is absent rather than merely unused. That separation is checked in CI, so it cannot be eroded by a careless change later. And the sync payload is built from types where a free-text field does not compile, which is a stronger guarantee than a code review that remembers to look.

The parts I will not oversell

Being straight about the limits is the whole reason the rest is credible.

  • tokenstat reads files with sensitive content in them. If your machine is already compromised, tokenstat is not your problem, but it is also not a defence. It reduces what a leak of its own database would reveal, but it cannot un-write the logs your tools created.
  • Some tools need more than a file read. Cursor records no token counts on disk (every usage counter in its local state reads zero), so covering it means reading a credential the app already left on your machine, or one you paste, and asking its API for aggregate usage. That is a genuinely bigger ask than reading a log file, which is why it is a separate, deliberate step rather than something that happens on first run.
  • Antigravity IDE sessions need the app open so tokenstat can talk to its local language server. CLI conversations under ~/.gemini/antigravity-cli/ are read offline like everything else.
  • Where usage is genuinely unavailable, tokenstat says so rather than reporting a confident zero. A zero you cannot distinguish from "no data" is worse than an honest gap.

Checking any of this yourself

  • Read the source. It is GPL-3.0, and the licence means it stays that way: a fork can change it, but a fork cannot close it.
  • Run tokenstat sync --dry-run and read the payload.
  • Watch it with your own tools. lsof, Little Snitch, or any firewall will show you that a plain tokenstat scan opens no sockets.

Reporting something

If you find a security issue, report it privately through GitHub Security Advisories on the repository, under the Security tab, rather than opening a public issue. The things most worth reporting are log data being written somewhere it should not go, any network transmission that is not an explicit sync you asked for, path traversal or symlink handling when discovering log directories, credentials ending up in output or crash reports, and any parser that can be made to execute content from a log file.