tokenstat
tokenstat
Sync and profiles

What leaves your machine when you sync

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

tokenstat works completely offline. You never have to create an account, and with no account nothing is ever uploaded.

Syncing exists for one reason: a local CLI cannot add up a work laptop, a personal machine, and a desktop into one picture. If that is not a problem you have, you can stop reading and keep using the tool exactly as it is.

If it is, this page is the full account of what crosses the wire.

Read it yourself first

Before any of the explanation below, there is a command that makes it unnecessary:

tokenstat sync --dry-run

That prints the exact canonical JSON that would be uploaded, then exits without uploading anything. Nothing on this page can be more convincing than reading your own payload, and if a future version ever starts sending something new, this is where you would see it.

The payload, field by field

{
  "v": 1,
  "machine": "m_7f3a9c21b4e85d06",
  "salt_id": "s_1a2b3c4d",
  "tz": "Europe/Budapest",
  "generated_at": "2026-07-29T09:12:44Z",
  "window": { "from": "2026-07-01", "to": "2026-07-29" },
  "rows": [
    {
      "d": "2026-07-14",
      "src": "claude_code",
      "model": "claude-opus-4-6",
      "proj": "p_9f2ad41c7b03",
      "in": 12043, "out": 3901, "cr": 88210, "cw": 4102,
      "ev": 37, "plan": true, "conf": "high"
    }
  ]
}
Field What it is Why it is safe
machine A random id made on first sync Not a hardware id, MAC hash, or hostname hash. It carries no fingerprint and cannot be correlated across users. Your readable machine label is set in the web UI and never sent by the client
proj HMAC-SHA256(local salt, project path), truncated The salt never leaves your machine, so projects can be grouped without anyone, me included, being able to name one
salt_id Which local salt made those hashes Rotating your salt starts a new namespace instead of silently merging rows under wrong keys
model The vendor's public model id Needed for pricing. Not sensitive
src Which tool it came from A closed list of supported tools, not free text
d, in, out, cr, cw, ev A date and six counters Numbers
plan Whether a subscription covered it Keeps plan-covered usage out of the money column
conf How confident that row's count is The same confidence the CLI already shows you locally
tz An IANA timezone, e.g. Europe/Budapest The day boundary is your local one and the server must not re-bucket it. A timezone, never a city and never coordinates

Read the list for what is missing, which is the point: there is no field for a file path, a prompt, a repository name, a hostname, an email, or an IP. Not "we promise not to fill them in". They do not exist.

Why a new field cannot appear quietly

Two things enforce that, neither of which is a policy.

The payload is built from types where a free-text field does not compile. Adding one is not a small careless change, it is a visible change to a type.

The server rejects unknown fields rather than ignoring them. A client that started sending something extra would fail, loudly, instead of having the extra quietly stored. The accepted schema is published at /api/v1/schema, and a change to it means a version bump you can see.

What the server stores

One row per day, per tool, per model, per opaque project key. That is the same shape as the payload, because the server has nothing else to work with.

Your profile is private until you claim a handle and turn publishing on. Private means private: an account that never publishes still contributes to nothing but its own dashboard, and the platform stats page carries grand totals only, with no way to derive an individual from it.

Turning it off

  • Do not sync at all. The CLI never contacts the network unless you ask it to. There is no telemetry to disable, because there is none.
  • Unlink a machine from your settings, and its rows go with it.
  • Export everything as JSON, or delete the account outright, both from /settings/data. Deletion is a real cascade, not a flag on a row.

Deleting the hosted account does not touch your local archive. That is yours, it was always yours, and it stays on your disk.

  • Is tokenstat safe to run? covers the local half: what it reads, and the boundary that keeps conversation text out of the database.
  • The privacy notice is the formal version, covering sessions, cookies, and OAuth.