Announcing the ACE sidecar: observability for coding-agent sessions
A local proxy that sits in front of your coding agent and tells you what each session actually cost, where the time went, and which optimisations would be worth anything on your traffic. Runs on your machine, uploads nothing. Beta opening now.
Announcing the ACE sidecar
Coding agents are the least observable expensive thing most engineering orgs now run.
You know your monthly API bill. You do not know which sessions produced it, how much of it was context re-read for the twentieth time, how long your agents spent parked waiting on an approval nobody was there to give, or whether any of the optimisations on your roadmap would be worth a dollar on your traffic.
We spent five weeks measuring one developer's Claude Code sessions request by request, and published what we found: 4.2 billion prompt tokens, $3,035 at list price, 90.5% of it input that had already been sent, and — more usefully — a string of levers that looked large in theory and collapsed under measurement.
The instrument we built to do that is now a thing you can run.
The ACE sidecar is a local reverse proxy that sits between your coding agent and the model
provider. It relays your traffic unchanged, prices every request, reads your existing transcripts
off disk, and renders the whole picture on a dashboard at 127.0.0.1. No account. No upload. No
change to how you work beyond one environment variable.
// sidecar_beta
Get beta access
The sidecar runs entirely on your machine and uploads nothing. Leave an address and we'll send you the build and the quickstart when the beta opens — or just to stay in the loop.
We use it to send you the beta and nothing else. Unsubscribe in one click.
What it shows you
Everything below is a real dashboard, rendered from real session data. Paths, project names, prompts and session identifiers have been replaced with synthetic equivalents — the aggregate numbers are untouched.
The eleven numbers that describe your fleet

Tokens in and out, requests, handbacks to the user, cost per turn, cost per session, commits per session, tokens per commit. The distribution table underneath is the one that usually lands: the p25 request already carries 100k+ tokens of context. There is no cheap quartile — which is why per-request payload tuning loses to context-size work, every time.
Commit attribution is time-window based and says so on the page. A commit that landed inside a session's window was not necessarily produced by that session, and the dashboard will not pretend otherwise.
The shape of the work

Daily tokens, daily commits, idle days. On this corpus the day-over-day median change is −12.2% with an interquartile range of −48% to +76% — volume routinely halves or doubles between consecutive days.
That single chart kills a category of work. Any alert or budget built on a rate of change will fire constantly and mean nothing. Only a cumulative cap against a period budget survives this shape, and it is much easier to believe that when you are looking at your own week.
Where the money goes, with the rate card attached

Cost, cache savings, cache hit ratio, peak context — then the rate card and the actual formula, because a page that tells you what something cost owes you the arithmetic. Every rate is read from a versioned catalog and links to the vendor's pricing page with the date it was checked.
Two things people usually notice here. Cache savings are larger than the bill — 6.1× on this corpus — and that saving is the provider's, already banked before any tool of ours arrives; the dashboard labels it that way rather than claiming it. And cache reads are ~98% of prompt volume, which is the fact the rest of the page is about.
What optimisation would actually be worth, on your traffic

This is the section we most wanted to exist. Two scorecards, because they are two different problems:
- Enterprise — minimise dollars. Accounting levers count, because they change nothing the model sees.
- User — maximise headroom under a token cap. Accounting levers are excluded, because they convert price without removing a single token.
The per-lever table carries a risk column, and the ordering it produces is uncomfortable: the
largest lever on this corpus (ttl_keepalive, 6.4% of cost) removes zero tokens, while the
levers that actually remove tokens are small. Everything simulated is badged SIMULATED. We would
rather ship a scorecard that says "this is a model with stated assumptions" than one that quietly
implies measurement.
Your sessions, on disk, read and never written

The transcripts the numbers came from — main sessions and the subagent runs they spawned, with turn counts, sizes and the first prompt of each. Working directory is read from the transcript itself rather than reconstructed from the directory name, because a project whose name contains a dash cannot be recovered from Claude Code's slug.
The other axis: where the clock went

Cost is one measure of efficiency. Elapsed time is the one developers actually feel, and it decomposes completely differently: 87.7% of wall clock is idle, and 233.8 hours of that — 204 occurrences, 69 minutes each — was an agent holding a pending tool call.
Nothing else in the stack tells you your agent has been waiting on you for an hour. The dashboard raises it as a live alarm, and it needs no classifier to be correct, so it cannot be wrong in a way that costs anything.
It is labelled a ceiling, not a saving, and that label is load-bearing. A transcript cannot distinguish a human who would have come back sooner from one who was away regardless. We report the upper bound and say so.
What it does not do
Shorter than the list above, and more important.
It does not upload anything. Not prompts, not paths, not code, not session identifiers, not
telemetry. The sidecar reads ~/.claude/projects and writes a local SQLite file. There is no
account, no API key of ours, and no network destination other than the model provider you were
already calling. "Never uploaded" is the property the whole design rests on, not a setting.
It does not change your traffic. This release is measurement only — it relays requests
unchanged and reports "levers": [] on its health endpoint. Every optimisation lever ships behind
a later phase, and shadow mode before enforcement. We are not going to start mutating your prompts
in the release whose job is to establish a baseline.
It does not hold your credentials. ace up --no-key stores nothing and relays whatever the
caller sends, which is exactly what a subscription client does. It binds to loopback and refuses
anything carrying proxy headers, so pointing it at a non-loopback address produces 403s rather than
an open relay.
It does not claim the provider's savings as ours. Prompt caching had already banked a 6.1× saving on this corpus before we arrived. The dashboard shows it, labels it, and does not put it in any scorecard.
It does not auto-approve tool calls. We looked hard at this and concluded the sidecar
structurally cannot: permission decisions never traverse the API. The model emits a tool_use
block and the client decides locally whether to prompt — a proxy on /v1/messages is not in that
loop. Claude Code also already ships an auto-approver in auto mode. What is genuinely missing is
measurement of it — auto mode reports no number, not what it approved, not what it blocked,
not what it saved. That gap is what the time section fills.
Running it
Two commands, and one environment variable.
uv pip install -e . # installs the `ace` console script
ace up --no-key # subscription (OAuth) clients — the common case
The banner prints where everything lives:
ACE sidecar → https://api.anthropic.com
auth: loopback-trust · credential: caller-supplied · levers: none (Phase 0)
Point your agent at it:
export ANTHROPIC_BASE_URL=http://127.0.0.1:8787
Dashboard: http://127.0.0.1:8787/dashboard
Health: http://127.0.0.1:8787/healthz
Telemetry: ~/.ace/telemetry.db (local SQLite, never uploaded)
Then, in the shell where you run your agent:
eval "$(ace env)"
claude
The dashboard fills in immediately — the historical sections read the transcripts you already have on disk, so you get your fleet metrics, your spend and your time budget before the sidecar has relayed a single request. Live turns appear as they land.
There is also GET /api/report, which returns a scrubbed, shareable JSON summary: aggregates only,
no per-session detail, no prompts, no paths, no identifiers. It is what you send your platform lead
when they ask what agents are costing.
What ships next
In order, and the ordering is the point — everything before the last item is read-only.
| # | Work | Why it is where it is |
|---|---|---|
| 1 | shipped — the data was already in hand | |
| 2 | shipped — 233.8h; needs no classifier to be correct | |
| 3 | Per-turn risk colouring, in shadow | read-only; accumulates real refusals to validate against |
| 4 | Shell segment parser | the 44.5% of calls no classifier can currently read |
| 5 | Allowlist rule generator | deterministic; complements auto mode rather than duplicating it |
| 6 | Context-exhaustion forecast + local checkpoint | zero wire impact; survives the session |
| 7 | Bash truncation with head+tail retention |
the first lever that changes a byte — measured at ~1.7% of cost, low risk |
Item 6 is worth a note, because the corpus changed our mind about it. We assumed the trigger was usage-limit exhaustion; across 162 sessions there were 3 rate-limit errors. Context exhaustion is the real event, and auto-compaction already handles it in-band. The actual gap is durability: compaction produces a lossy in-context summary that dies with the session. A resume brief on disk does not. That is a narrower and much better feature than "summarise before the limit", and we only found it by counting.
Item 7 is the one lever we are confident enough to ship, and it arrived there by being demoted
then promoted. It was rated high-risk on the reasonable objection that Bash output is the signal —
stack traces, test failures. Splitting the recovered value by whether the output carries a
diagnostic showed 90% of it is sed/cat dumps, grep roll-ups and git diffs the agent
skimmed once and never read again. Keep head and tail, exempt the diagnostic class, and most of the
value is available at close to zero risk.
Meanwhile the lever we were going to ship first — collapsing duplicate file reads — turned out to be worth $0.33 across 36 days, because 97.6% of "repeat reads" request a different line range and are not duplicates at all. We dropped it. That story is in the analysis post, and it is the best argument we have for why an instrument should exist before an optimiser does.
The beta
The sidecar runs on your machine, uploads nothing, and works with Claude Code today. We are opening it in batches so we can actually read the feedback.
What we would most like from beta users is a second corpus. Every finding above comes from one developer on one machine over 36 days. The cost structure should generalise; the magnitudes are one fleet's, and we would rather know where they break than assume they hold.
Leave an address below and we will send you the build and the quickstart when your batch opens.
// sidecar_beta
Get beta access
The sidecar runs entirely on your machine and uploads nothing. Leave an address and we'll send you the build and the quickstart when the beta opens — or just to stay in the loop.
We use it to send you the beta and nothing else. Unsubscribe in one click.
Questions, or want it deployed across a team rather than a laptop — contact@acefleet.dev.