Show my usage and my leaks
Tokens by session, worker and model, the bytes crush kept off the wire, and the habits that waste them.
Prompt#
Show me what this workspace is spending, and where I'm leaking context.
What the Chair does#
Reads the local ledger — no provider call — and prints spend by seat, then the leak telemetry that names the wasteful habit.
MCP calls#
usage_status({ "recent": 10 })
usage_status({ "view": "leaks" })
usage_status({ "view": "governance" })
usage_status({ "view": "workers" })
CLI, for the human-readable version:
orch usage # table: by session, by worker, by model
orch usage --format json --limit 10
orch usage --leaks # rereads, repeated calls, oversized results, silent streaks
orch usage --leaks --format json
orch usage --governance # conflict_rate / duplicate_rate per session
orch usage --workers # wall time, status, files, guardrails, tool calls, tokens, cost by session
orch usage --export jsonl # one gen_ai.*-keyed JSON line per session and per tool row
orch gateway status # live/cooldown, ring position, rotations per provider
Expected response#
usage_status takes an optional view: summary (default), leaks,
governance, workers or perf; an unknown value errors with view must be summary|leaks|governance|workers|perf. Those five are the whole list — the
per-tool counters live in the cli_tool_usage table, which view: workers
reads; cli_tool_usage is not itself a view.
view: summary(or omitted) returnssummary,saved_pct,total_bytes_saved,by_session[],by_worker[],by_model[],agents[],counters[]. Every breakdown row is{key, attempts, prompt_tokens, completion_tokens, bytes_saved}. Agraphblock carries whatcode_snippetandtrace_pathreturned against the size of the files they stood in for.- It also returns
by_worker_cli[]: tokens read straight out of a worker CLI's own output — agy and claude's--output-format jsonresult, cursor-agent's ownusageblock, or copilot'sTokens ↑/↓summary line — for a CLI that never crosses the gateway at all. Once parsed, these same tokens are folded intosummary,agents[],counters[]andby_session[]too — a BYO-auth CLI worker shows up in the headline numbers, not only inby_worker_cli.cli_usage_unavailable[]lists every session that has no parsed row, and why (usage block emptyfor a known CLI,no parser for this agent/CLIotherwise) — a parser that reads every counter as zero is treated as no row at all, never printed as a measurement. view: leaksreturns the same content-free rows asorch usage --leaks, keyed by session (reread_files,repeated_calls,large_results,silent_streaks).view: governancereturns{sessions[], pairs[]}— the same conflict/duplicate metrics asorch usage --governance, plus pairwise conflicts.view: workersreturns{sessions[], tools[]}: one row per session naming every dimension worker statistics get rolled up by —session_id,agent_id(worker),task_id,project,day, plusstatus,duration_ms,files_changed,guardrails,tool_calls/tool_errors/tool_time_ms, measured tokens (input_tokens,output_tokens,cache_read_tokens,cache_write_tokens),cost_usdandsource(which CLI's log the tokens came from, or""when none was ever parsed for that session — never shown as zero tokens).tools[]is the per-tool breakdown across every session:session_id,tool_name,call_count,success_count,error_count,total_time_ms— this is how you find which tool ate the budget, counted by theorchMCP server itself for everytools/callit serves, independent of what the calling CLI prints.
Daily budgets#
orch.yaml can cap measured tokens per local day, optional and off unless set:
budget:
workspace_tokens_per_day: 2000000 # whole project, all seats — 0/unset = unlimited
seat_tokens_per_day: 500000 # one dispatching agent id — 0/unset = unlimited
warn_at: 0.8 # fraction of the cap that adds a note instead of denying (default 0.8)
Both caps sum today's (local day) cli_session_usage — input + output +
cache-write tokens — the same measured numbers orch usage --workers prints.
A dispatch at or over either cap is denied before the agent ever starts, from
both orch dispatch and the dispatch_worker MCP tool:
budget: seat exhausted (used 512000 of 500000 tokens today) — raise budget.* in orch.yaml or wait for the daily reset
Short of the cap but past warn_at, the dispatch still runs and the reply
carries a budget_note (MCP) or prints the note before the run (CLI) instead
of silently spending past it. orch budget status [--project P] [--format json]
prints today's used/cap for the workspace and for every seat that spent
tokens today, with no dispatch involved.
Gotchas#
- It is content-free, so you can paste it to a human. The gateway ledger stores
counts, never prompts.
orch gateway statusis content-free too: no keys, no bodies. - Leaks and governance are also over MCP.
usage_status({ "view": "leaks" })andusage_status({ "view": "governance" })return the same rows as the CLI flags — no shell needed. cache_hitsis spend avoided, not spend. A request the gateway answered from its exact-match cache carriesX-Orchemax-Cache: hitand is not counted as an upstream attempt. Read saved and spent as two columns, never as one net number.- The cache is off by default.
gateway.cache.ttl_secis0unless you set it, and streaming is never cached — socache_hits: 0usually means "not enabled", not "never hit". - Only traffic through the gateway is counted in
summary/by_session/by_worker/by_model. A preset onagents.auth.<preset>: account— Claude Code on its own plan login,codexandcursorby default — routes no model traffic here, so it shows attempts but not provider tokens.by_worker_cli[]is how those same BYO-auth workers still show measured tokens: read from the CLI's own log instead of the gateway. by_worker_clinumbers are as precise as the CLI that printed them. agy, claude and cursor-agent report exact counts; copilot's terminal summary is rounded to one decimal on a "k" suffix (168.1k→168100), so treat it as approximate, never as an exact count. A rounded measurement is still a measurement, not a claim.token_coverage.statusismeasured,partialorunavailable, never a guess.measuredonce every session with a known CLI has a non-zero usage row;partialwhile some do and some don't —token_coverage.unmeasured[]names which sessions and why;unavailablewhen nothing has ever been measured at all (no gateway attempt, no transcript hook, no parsed CLI log).recent(MCP) and--limit(CLI) are the same idea: attach the N most recent attempts. Leave it out for the aggregate only.by_worker_cli/workersnow carrycache_write_tokensnext tocache_read_tokens. claude's--output-format jsonalready printedcache_creation_input_tokens; it is now parsed and stored, not discarded. agy and copilot do not report a cache-write figure, so their rows keep it at0— not measured, not estimated.orch usage --export jsonlis stdlib-only, no OTel dependency. One JSON line per session (orch.source: "session") and one per session/tool pair (orch.source: "tool"), keyedgen_ai.usage.input_tokens,gen_ai.usage.output_tokens,gen_ai.usage.cache_read.input_tokens,gen_ai.usage.cache_write.input_tokens,gen_ai.tool.name,gen_ai.agent.name,orch.session,orch.project,orch.cli,orch.source— every key present on every line, numbers only from what was actually measured. Any OTLP-HTTP/JSONL collector ingests it as-is.- What the leak columns mean: rereading a file you already read, calling the same tool with the same arguments, returning results too big to be useful, and long silent streaks. Each one has a cheaper move in Stop reading whole files.