Command overview
beacon token-usage reads Beacon runtime events from the JSONL log and summarizes token usage, cost, users, models, sessions, runs, harnesses, and repositories.
Command syntax
In Beacon
v0.0.70, token reporting moved from beacon endpoint tokens to the top-level beacon token-usage command. Update scripts, CI jobs, and runbooks that still invoke the old endpoint subcommand.How token attribution works
Beacon normalizes token telemetry from every runtime into one canonicalgen_ai.usage representation, then aggregates it locally from the runtime JSONL log. There are no per-harness token fields, so a report over mixed runtimes uses the same vocabulary throughout.
A few rules shape how the numbers read:
- Counts are kept disjoint.
input_tokens,output_tokens,cache_read, andcache_creationdo not overlap, so a total isinput + output + cache_read + cache_creationwithout double-counting. Codex reports input inclusive of both cache reads and cache writes, so Beacon subtracts both before storing uncached input. - Cost is runtime-reported only.
cost_usdreflects what the runtime emits. Beacon never derives cost from local pricing tables, so cost appears only for runtimes that report it. - Attribution depends on the metadata a runtime attaches. Model, harness, repository, and run grouping work whenever those fields are present. Per-session grouping (
--session, the session step tree) requires a session or conversation id on the usage signal. Per-user grouping uses the event user directly or a matching session context event from a local hook. - Duplicate channels are de-duplicated. When a runtime emits the same usage on more than one signal (Claude Code reports it on both logs and metrics), Beacon counts it once.
Per-runtime coverage
Token coverage is not uniform, and the reason is almost always the runtime rather than Beacon: most agent runtimes do not report usage on the surface Beacon collects from. A turn with no token attribution is a turn whose runtime never reported any. Collected and verified against captured payloads:
Cline reports usage once per task rather than per model call, because Beacon’s rollups sum
gen_ai.usage across events and reporting at both granularities would count every token twice. fx reports cumulative totals, which Beacon differences into per-turn deltas for the same reason.
Collected through the generic OpenTelemetry path, not yet verified against captured payloads:
This table records what Beacon is built to read, not what your machine actually produced. A runtime can be listed here and still contribute nothing, because it was never run, or because its build reports no usage.
Context occupancy
Some runtimes report how full the model’s context window was without reporting what a turn cost. That is a different measurement from spend, and it is recorded in a different place:gen_ai.context, holding used_tokens and limit_tokens.
The distinction is not cosmetic. Everything in gen_ai.usage is additive — every total on this page sums it. Occupancy is a level at one moment: a session whose window was 92% full ten times did not spend ten windows. So context is never summed, never added to a total, and never counted as a runtime reporting its spend. It feeds the utilization view, where a reported window also replaces the model table’s default, because a reported limit reflects the tier a call actually ran under.
Both runtimes also report the ratio of the two (
context_usage_percent, context_usage). It is derivable from the pair, so it stays in raw rather than being stored a second time in different units.
A runtime that reports occupancy and no spend still shows as not_instrumented in the coverage report below. That is deliberate: it has not told Beacon what it cost.
Not collected:
Legacy metric-only Codex rows written before the turn trace existed remain visible in historical totals, but cannot be assigned to a session or user. See the Codex CLI and Claude Code runtime pages for details.
Cost estimates are separate
Beacon does not turn Codex token counts intocost_usd. A future report may show a separately labeled estimate with the pricing source, effective date, model, and service tier. Unknown models must remain unknown rather than reading as zero cost, and reasoning tokens must not be charged a second time because they are already included in output.
Checking coverage
A usage report answers “what did I spend”. It cannot answer “is this all of it”, and that is the question to settle before treating a number as a bill. A runtime whose telemetry never arrives looks exactly like a runtime nobody used: both are simply absent from every rollup, so a total can omit an entire agent and still look complete.Check which runtimes are contributing token telemetry
The
not_instrumented distinction is what makes the report worth reading. Without it Cursor would appear as a problem on every run, and a column that always shows a problem is a column people stop reading.
The INSTALLED column means “Asymptote configured this runtime”, not “this product is on the machine”. Only configuration Asymptote wrote counts — a hook command, a managed plugin marker, or a local OTLP endpoint it set. That is the population where silence is informative: Asymptote wired it up, so it should be reporting. A runtime present but configured by hand would not be reporting through Asymptote either way, so it appears only if it actually emits events.
Coverage applies the --since, --until and --harness scopes, and deliberately ignores --session, --model, --repository and --run-id. Those filters select usage-bearing events almost by definition — an event carries no model unless it carried a model call — so a coverage report computed over them would find every runtime covered and prove nothing.
Add --json for the machine-readable form, which carries the same per-runtime rows plus silent, covered and total_events counts. A silent count above zero is the alertable condition.
The local dashboard serves the same report at GET /api/tokens/coverage, with the same body as --coverage --json. It honors since, until and harness and ignores the rest, for the reason the command does. Both read one join and one expectation table, so the two cannot reach different conclusions about the same log.
Examples
Show token usage from the default per-user endpoint log:Show local token usage
Print JSON
Filter by session
Bucket usage over time
Inspect a CI run
Filters
Filters can be combined to narrow the report to a time range, model, agent harness, repository, session, or CI run.Runtime log selection
By default, the command reads the per-user endpoint runtime log. Use--system for a system-mode endpoint, or --log-path when reading a copied runtime log or a CI session artifact.
Related
Endpoint dashboard
Explore endpoint runtime logs locally in a browser.
Endpoint inventory
See configured, detected, hook, and observed endpoint inventory.

