Token Meter
The Token Meter reads the transcripts that Claude Code, Codex, Gemini CLI and omp write to disk and totals them in the title bar. It can also show your plan limits and, for six API providers, the balance, quota or spend on your account. Plan limits and live Codex limits have their own switches; account providers start when you save a key. The popover lists every provider you set up, with the one you pin first.
The title bar chip
The title bar shows one chip. Click it to open a popover with one row for each provider that has something to show: Claude Code, Codex and Gemini when their transcript folders are found on this machine, Other agents when omp billed an account that is none of those in the last 30 days, and each account provider you have saved a key for (Kimi also appears when the Kimi Code CLI is signed in on this machine). Rows keep a fixed order: Claude Code, Codex, Gemini, Other agents, DeepSeek, Moonshot, Kimi, MiniMax, OpenRouter, Z.ai, except that the provider you pin goes first (see the section on pinning below).
The chip speaks for whichever provider is closest to a limit. What it shows depends on what is actually known:
- A percentage when any provider has published a quota window: the most constrained one across all of them. The provider's icon sits beside it, and hovering the chip names the window and when it resets.
- A token count when no provider publishes a quota: the tokens used in the last 5 hours, read from transcripts on this machine, for the first of Claude Code, Codex, Gemini and Other agents that has a row.
- The lowest balance when there are no local transcript rows (Claude Code, Codex, Gemini, Other agents), no provider publishes a quota, and at least one provider reports a balance in US dollars: the smallest one, as money (for example
$12.34), with that provider's icon. A balance has no ceiling, so it is never turned into a percentage, and a balance in yuan is never converted to dollars for the comparison. - No figure at all when there are no local transcript rows and the providers you set up report only a spend, or only balances in yuan. The chip then shows a plain gauge icon.
A percentage is neutral below 60%, amber from 60% and red from 85%. That colouring is only ever applied to a percentage a provider published, never to a token count or a balance.
The chip is hidden entirely when there is nothing to say: no agent transcript folder on this machine and no provider key saved. The first scan starts 8 seconds after launch, and the first numbers appear when it finishes.
Where the numbers come from
| Agent | Folder | Files read |
|---|---|---|
| Claude Code | ~/.claude/projects | .jsonl transcripts in the folder and its subfolders |
| Codex | ~/.codex | .jsonl session files in the folder and its subfolders |
| Gemini CLI | ~/.gemini/tmp | .jsonl chat files in the folder and its subfolders |
| omp | ~/.omp/agent/sessions | .jsonl session files in the folder and its subfolders |
Usage is counted per turn and grouped by hour and model. Files not modified in the last 30 days are skipped, and data older than 30 days is dropped. omp works across several providers, so each omp turn goes to the row of the account it was billed to: Anthropic to Claude Code, OpenAI to Codex, Google to Gemini, anything else (DeepSeek, MiniMax and so on) to Other agents. A turn that omp imported from a Claude Code or Codex session is not counted twice. OpenCode and other agents are not counted: the app reads only the four folders above.
~/.codex/config.toml to connect Codex to its MCP server (see Coding agents and Control Room, formerly War Room), which creates the ~/.codex folder. From the next launch a Codex row showing 0 can appear in the popover even if Codex is not installed.HOME when it is set, otherwise USERPROFILE, otherwise HOMEDRIVE plus HOMEPATH. A Windows app started from Explorer usually has only USERPROFILE. The Windows build is unsigned, and the transcript scan is verified on macOS only.The popover: one row per provider
Each row carries that provider's headline: up to three small bars (5h, wk, and a third that is mo, Quota or the name of a model-specific limit) for the windows it publishes, or, for a balance or spend, a line of text. The first line of a row names the reset of the window closest to its limit: Resets in … for the 5-hour window, or for example Week resets in … for another. A window whose reset time has passed with no fresh reading since shows an empty bar and a dash instead of a stale number (Reset — no reading since in the expanded detail and on hover). The Claude Code row also says Couldn't refresh · last reading when its plan-limits reading is more than 15 minutes old.
Each row is tagged with whose numbers it shows. Account means the provider reports it for your whole account, including use on other machines: plan-limit bars, balances and an account's spend. This Mac means it was counted from the transcripts on this computer only: a row with no limits shows Today spend and tokens, for example $1.20 today · 3.4M tokens. Gemini and Other agents rows always show that local line, because the app reads no quota for them.
The popover lists every provider that has a row, the pinned one first and the rest in their fixed order. The chip can speak for a provider that is not first.
Account providers you have not set up are listed after the rows as Set up in Settings; from two upwards they collapse into one More providers… line with their icons, which you click to show them. Any set-up row opens Settings → Token Meter.
Click a Claude Code, Codex, Gemini or Other agents row to expand its detail. The provider's own limits come first under an Account tag, then what was counted here under This Mac:
- Session and Week bars, plus any per-model limits the provider reports, each with its reset time. Only for Claude Code and Codex, and only when those limits are available — see the two sections below.
- Tokens: used in the last 5 hours, the last 7 days and the last 30 days. The 5-hour and 7-day windows are counted in whole-hour buckets, so each can include part of one extra hour.
- Cost: estimated for today, the last 7 days and the last 30 days. A figure that could not be priced reads no price yet, and one that leaves out some unpriced tokens starts with ≥.
- Last 24 hours: one bar per hour.
- Last 30 days: one bar per day. Switch between Tokens and Cost, and hover or focus a day to see its total and its top three models by tokens.
- Last 7 days split into Fresh input, Output, Cache writes, Cache reads and Turns.
- How long ago the numbers were computed, and the line Read from each agent's own transcripts on this Mac. Nothing is sent anywhere.
At the bottom of the popover, an All agents row adds up every agent's Today, Last 7 days and Last 30 days, tokens over cost. It appears once two or more agents have used tokens in the last 30 days, and clicking it shows the split by agent.
Pinning a provider to the top
The provider listed first in the popover is Claude Code by default. To change it, open Settings → Token Meter and pick another provider under Pinned to the top, or pick None (fixed order).
A pin only moves a row. Every provider you have set up is still listed, and the chip still follows the limit closest to running out. If the pinned provider has no row (Codex not found, no key saved), nothing moves.
Cost figures
Cost is the token count priced at each model's public API rates, using a price table built into the app. When omp recorded its own cost for a turn, that figure is used for those tokens instead. The popover labels it At API rates, not what a subscription was billed and shows the date of that table. If you pay for a subscription plan, it is not what you were charged.
- Today starts at local midnight. Last 7 days and Last 30 days are rolling windows; only 30 days of history are kept.
- Models the price table does not list count toward tokens but not cost. The figure then says it is a floor, names those models, and shows what share of tokens was priced.
- A cost shows
—when nothing in the window has a known price. - The price table has not been checked against OpenAI's own price page for the OpenAI models, so treat Codex costs as an estimate.
How it updates
- The first scan starts 8 seconds after launch. With large transcripts it can take a while.
- After that the app rescans every 60 seconds and reads only what was appended to each file since the last scan.
- The title bar picks up the latest transcript result every 30 seconds, and asks for the Claude plan limits, live Codex limits and account readings every 60 seconds. Each of those providers still applies its own 5-minute floor.
- The refresh button at the top of the popover (Re-check every provider) pulls the latest reading of every provider at once instead of waiting for that pick-up. It does not start a new transcript scan and does not shorten the 5-minute floor on Anthropic, live Codex limits and the account providers: a provider asked more recently than that answers with its last reading.
- Scan progress is saved to
token-meter-cache.jsonin the app's config folder (on macOS,~/Library/Application Support/com.mxterm.desktop), so after a restart the app reads only what changed while it was closed.
Real plan limits for Claude
Claude Code's transcripts do not record your plan's limits, so by default the meter shows tokens rather than a percentage. To see the percentages Anthropic reports, open Settings → Token Meter, find Plan limits and switch on Show real limit percentages for Claude. It is off by default and covers Claude Code only.
When you switch it on:
- The app reads Claude Code's keychain item,
Claude Code-credentials, through the macOSsecuritytool. Claude Code writes that item with the same tool, so macOS does not normally show a prompt. - The app takes Claude Code's sign-in token from that item and calls
GET https://api.anthropic.com/api/oauth/usagewith it. The token is kept in the app's memory until it expires or Anthropic rejects it, so the keychain is read once per token. It is never written to disk or logged. - The chip and popover show your 5-hour and weekly percentages and when they reset.
The app calls the endpoint at most once every 300 seconds and shows the last reading in between. After a rate-limit response (HTTP 429) it waits 900 seconds before the next attempt. If Anthropic cannot be reached, the last reading stays on screen.
claude to sign in. Plan limits work only on macOS; on other systems the credential cannot be read and the panel shows the same not-signed-in message. To forbid the keychain reads on a managed Mac (Claude Code's item and the account keys saved by MXterm Pro), start MXterm Pro with the environment variable MXTERM_DISABLE_KEYCHAIN=1.Codex limits, from disk or live
Codex needs no switch and no network for its limits. It writes the rate-limit headers the server sent it into its own session files, so the 5-hour and weekly percentages the Codex UI shows are already in the files the Token Meter scans. The expanded Codex row notes As reported by Codex … ago, because a figure is only as current as your last Codex turn on this machine.
If you want a number that is current now, Settings → Token Meter has Live Codex limits. It is off by default. When you switch it on, the app reads Codex's own ChatGPT sign-in from ~/.codex/auth.json and sends it only to chatgpt.com to fetch your current limits; it never changes or refreshes that sign-in. The check runs at most once every 5 minutes. A live reading less than 15 minutes old replaces the one read from disk, and the row then reads Live from OpenAI, updated … ago.
~/.codex/auth.json is not read: the panel then says No Codex ChatGPT sign-in in ~/.codex/auth.json. Run `codex login`. If OpenAI rate-limits the check, the app waits 15 minutes before trying again.Account balances from your API keys
Six providers can report the state of your account: a balance, a quota, or what has been spent. Each is read with an API key you paste in Settings → Token Meter, under Account providers. With no key saved the app makes no keychain call and, except for Kimi when the Kimi Code CLI is signed in on this machine (see the note below), no network call.
| Provider | The key it wants | What the row shows |
|---|---|---|
| DeepSeek | An API key from the DeepSeek platform (API keys page) | Balance, split into paid and granted |
| Moonshot | An API key from the Moonshot / Kimi Open Platform, with a Region of International or China | Balance |
| Kimi | A Kimi Code API key | Quota: the 7-day window and the 5-hour rate-limit window |
| MiniMax | A MiniMax Coding Plan key, which starts with sk-cp-, with a Region of Global or China | Quota used on the plan, as a percentage |
| OpenRouter | An API key from openrouter.ai/keys — not a management key | Quota when the key has a spend limit, otherwise spend so far |
| Z.ai | Your Z.ai / BigModel coding-plan API key, with a Region of Global or China | Quota on the GLM coding plan |
Each key is stored in your system's credential store (the macOS Keychain; on Windows the build uses Credential Manager, which has not been checked) and sent only to that provider's own API, with the two exceptions described under What leaves your machine. The panel says so, in words that name the macOS Keychain on both systems: Keys are stored in the macOS Keychain and only sent to that provider. Nothing secret is written to the app's own files — only whether a provider is configured, its region, and the last four characters of the key, so the panel can show Key saved · …abcd. If macOS refuses Keychain access, the rows of providers you have set up read macOS Keychain access blocked until you save or remove a key or restart the app, instead of waiting for a reading that will not come.
The response formats of these six providers have not been checked against real responses, so a row can show no figure, or a wrong one, until they are. Treat these readings as unverified.
A provider is refreshed at most once every 5 minutes. A rate-limited provider is parked for 15 minutes; one that answers Key rejected — update it in Settings is parked until you change the key. When a refresh fails because the provider cannot be reached or is rate limiting, after a good reading, the row keeps the old figure and marks it Couldn't refresh · last reading. A rejected key or an unreadable reply drops the old figure.
~/.kimi-code/credentials/kimi-code.json and sends it to api.kimi.com to read your quota, with no switch to turn on. It only ever reads that file and never refreshes the token, and a key you paste takes precedence.In panes and on tabs
A pane's own token figure is on its row in the left sidebar, not in the pane header or on the tab. The row's second line shows the agent and what that pane's conversation used on this Mac (up to the last 30 days), such as Claude Code · 1.7M · $0.41, at list prices and not what you were billed. A workspace row shows the total for its panes whose conversation is known. A pane whose conversation is not known shows nothing, and so does a Gemini pane: no figure is guessed.
On a pane running Claude Code or Codex, a notice appears when the plan's own published percentage reaches 80% (you may want to wrap up) and again at 95% (better to stop). It comes only from a real percentage, so it needs the limits described above to be available; other agents never get one. The notice is information only: it closes with its ✕, and it does not pause the agent or type into the pane. When Claude Code's last line in a conversation is a plan limit with a reset time still ahead, the pane header reads Waiting for the plan to reset with that time.
What leaves your machine
Token counts and costs are computed on your machine, and transcripts are never sent anywhere. Codex's limits read from disk are local too. A paired phone can read your plan percentages from this Mac, never balances. Three things can make a network request, and each goes only to its own provider:
- Show real limit percentages for Claude →
api.anthropic.com, with Claude Code's own sign-in token. - Live Codex limits →
chatgpt.com, with Codex's own sign-in. - Account providers → that provider's own API, with the key you saved for it. Two cases go beyond that. For Kimi, if you saved no key and the Kimi Code CLI is signed in on this machine, the app sends the CLI's token to
api.kimi.com, with no key and no switch. A MiniMax key rejected in the Global region is retried on MiniMax's China host,api.minimaxi.com. A redirect is refused outright, so a key can only ever reach a host of the provider it was saved for.
For the app's other network traffic, see Telemetry: what the app sends.