Quick answer
OpenCode stores token counts per assistant message in its local SQLite database, usually `opencode.db` inside the data directory. Each message keeps input, output, reasoning, and cache read and write counts plus a cost value. Run `opencode debug paths db` to print the exact file on your machine before you query it.
Tokens are attached to messages, not sessions
OpenCode does not keep one running counter that says what a session cost. It writes a record for every assistant response, and the usage numbers travel inside that record. A session total is something you compute by adding those records together. That is why the same session can show one figure in the interface and a different figure in a spreadsheet.
| Field | What it counts | Common mistake |
|---|---|---|
| input | Everything sent to the model, cached prefix included | Adding it to cache.read double counts |
| output | Tokens generated, reasoning included on most providers | Adding reasoning again inflates the total |
| reasoning | Thinking tokens, reported separately but billed as output | Summing it with output for a bill estimate |
| cache.read | Input served from the provider's prompt cache | Treating it as free when it is billed at a lower rate |
| cache.write | Tokens written into the cache for later turns | Ignoring it on providers that charge for writes |
| cost | A per-message estimate from the provider or model rates | Assuming it matches your invoice exactly |
Read the columns in the right order. input already includes the cached tokens the provider served, so fresh input is input minus cache read. If your provider bills cached input at a discount, keep the two apart rather than collapsing them into one number.
Reasoning is the second trap. Providers that bill internal thinking as output usually report it inside output and also expose it as reasoning. Adding both inflates the estimate. Check a single message against the provider's invoice before you trust any total built from these fields.
Find the file before you write a query
Guessing the path wastes more time than the query. OpenCode ships a command that resolves the location for the current install after environment variables and the release channel are applied.
opencode debug paths db
opencode debug paths data
opencode debug paths- Linux:
~/.local/share/opencode/opencode.db, unlessXDG_DATA_HOMEis set - macOS: often
~/.local/share/opencode, though some builds use~/Library/Application Support/opencode - Windows:
%APPDATA%\opencode, which expands toC:\Users\<you>\AppData\Roaming\opencode - Any platform:
OPENCODE_DBoverrides the filename or path, so trust the printed result
A path ending in opencode.db is a SQLite file. Older or differently configured builds may keep a storage folder of JSON files instead, with a similar message shape spread across many files. Your install may use one or the other, which is another reason to print the path first. The database location guide covers both layouts in more detail.
Build a total you can trust
A useful total answers a specific question. Daily spend, cost per model, and cost per session are three different queries, and mixing them produces a number nobody can act on.
- Filter to assistant messages, since user turns carry no usage.
- Sum each token column separately so you can recompute cost when rates change.
- Subtract cache read from input when you want fresh input, and label the column accordingly.
- Group by day, model, or session depending on the question you are answering.
- Store the raw counts in a CSV so a future price change does not rewrite history.
Doing this by hand once is instructive. Doing it every week is not. UsageAtlas reads the same database locally and totals tokens by session, model, and day across 7, 30, or 90 days, with alerts when a window runs low. It also keeps the per-message records available through the cost field guide, so you can audit any total it shows.
Questions, answered
Does OpenCode show token usage in the terminal?
Some builds surface context size or a per-message cost in the interface. The durable record is the message store. Run `opencode debug paths db` to find it, and check `opencode --help` for a stats command in your version.
Are OpenCode token counts the same as my provider bill?
They come from the usage the provider returns, but a bill can differ because of cached-token discounts, minimum charges, or rounding. Compare totals over the same date range rather than per request.
Why do extra small-model messages appear in my OpenCode usage?
OpenCode uses a low-cost model to generate session titles, and those requests are recorded like any other. They are usually small but they are real usage, so filter by model before you blame a session.