Look inside your agent's context window.
mado is a coding agent in Go that accounts for its own context window, call by call. Here, a real session from its log: mado reads its own README and reviews itself on DeepSeek v4.1 Flash, 6 calls, $0.0091.
The same session, in mado's terminal.
Replayed from the log with mado -r f45e4764, no new calls. Every answer ends with its line, a miss gets a line of its own under the call that paid for it, and the footer keeps the window and what the session has cost so far.
The session, call by call, as mado printed it.
These lines are mado's profiler run on its own log, verbatim. The first number is what entered the window on that call: In(N+1) − In(N) − Out(N), exact, from reported numbers only. Two ends, like +4,024…+5,094, mean the reasoning of the call before may have stayed in the prompt or left it; net means something also left the window between the two calls, the earlier reasoning or a changed system prompt, so the number is what entered minus what left. The seconds are the time to the first token; the cost is the rate frozen in the log when the call was made.
| cache share | call | time | entered | mado's line |
|---|---|---|---|---|
| run 1 | ||||
| 1·1 | 10:30 | your message | +8,791 · cache 0/8,791 · out 55 (55 reasoning) · 1.3s · $0.00085 | |
| 1·2 | 10:30 | read result | +6,512…+6,567 · cache 0/15,358 · out 549 (80 reasoning) · 1.0s · $0.0016miss: served by Baidu, not Wafer · 8.8k rewritten · ~$0.00034 | |
| run 2 | ||||
| 2·1 | 10:31 | your message | +44 net · cache 8,704/15,951 · out 1,070 (1,070 reasoning) · 0.7s · $0.0018miss: served by Wafer, not Baidu · 6.7k rewritten · ~$0.00026 | |
| 2·2 | 10:31 | bash result, read result | +4,024…+5,094 · cache 16,896/21,045 · out 1,617 (1,617 reasoning) · 0.5s · $0.0022 | |
| 2·3 | 10:31 | grep result, bash result | +248 · cache 22,400/22,910 · out 212 (212 reasoning) · 0.7s · $0.00053 | |
| 2·4 | 10:31 | bash result | +80 · cache 22,912/23,202 · out 1,832 (620 reasoning) · 0.5s · $0.0021 | |
Every number carries its state. Unknown is never zero.
A provider that doesn't report a number gets n/a, not 0; a number mado computed says how. The examples are from the session above.
The provider's usage, untouched.
Arithmetic over the reported numbers of each call, with no estimate and no extra request.
When the reasoning before may have stayed or left, both ends, until the session settles which.
Not reported, or not priced. Every call above was both; a local server without usage reads n/a, never 0.
The fixed prefix, system prompt and tools, measured once per hash with count_tokens.
The share of a file or a paste inside one increment, by bytes, marked with ~.
$0.00 spent and 0% used with no data behind them: OpenCode printed both in our September 2026 survey. mado prints what it knows.
We logged what actually crossed the wire.
Single observations from development sessions in September 2026, read back from mado's log. They are not benchmarks; they are why mado exists.
The same 3.7 KB Go file, read by two models. Haiku 4.5 and Opus 5.5 count it differently: the tokenizers differ.
One Anthropic web search. The encrypted result stays in the history and is paid again on every later turn.
No cache breakpoints on Anthropic. cached=0 on every turn: one read of our own project guide entered at full price.
gpt-5-mini output was hidden reasoning, 73%. On Chat Completions it never comes back.
gpt-oss-20b on llama-server. First token with a cold cache, then with a 5k-token prefix cached.
A negative increment. The chat template dropped earlier reasoning, and nothing in the payload said so.
Reads failed on guessed file names by a model exploring a repo with only read: it needed a tool that lists files.
Of thirteen harnesses surveyed, none showed what entered the window on a call.
What four of them tell you about the context window, as of September 2026. The most-voted cost complaints are caches that break with no stated reason, like claude-code#46829. The cause is in the request, and the harness owns the request.
| Tokens entered per call | Why the cache missed | Unknown shown as unknown | |
|---|---|---|---|
| Claude Code | — | a likely cause, last miss only | partly |
| Codex CLI | — | — | no: "100% context left" with no data |
| OpenCode | — | — | no: $0.00 spent, 0% used |
| Pi | — | idle time or a model switch, off by default | no: an unknown price shown as 0 |
| mado | every call | every miss: the cause from the request, or unknown | yes, n/a |
A whole agent, not a viewer bolted onto one.
The profiler isn't watching from outside: it reads the request mado is about to send and the usage that came back, so what you find you can change in the harness itself, then measure again. It isn't the only thing you get; here is what works today and what comes with the first release, and the whole roadmap, surface by surface.
- Any model, your keyAnthropic Messages, OpenAI, and every Chat Completions endpoint: OpenRouter, DeepSeek, Groq, llama.cpp, Ollama, LM Studio, vLLM. No subscription login, ever.
- Seven tools, sized for a window
read,list,grep,bash,write,edit,fetch, behind permission prompts, with a redactor on every result before the model sees it. - The window, managedA system prompt in named sections that never changes mid-session,
AGENTS.md, Agent Skills on demand, and compaction you can see in the transcript. - Everything on disk, nothing in your repoEvery session in one SQLite file;
-cand-rresume;-pfor scripts, with exit codes. - A library firstThe TUI is a client of the same packages you import:
agent,event,tool,provider,store,client.
mado profileThe whole session as one report, and/profilelive.- The prefix, countedSystem prompt and tools, once per hash.
- Claude Code's logsThe same report from another harness's session.
- Signed releasesNotarized binaries, a cask,
mado upgrade.
- MCPWith OAuth, and each server's cost in the report.
- SubagentsChild sessions with their cost on the tree.
- RollbackFiles, conversation, or both.
The benchmark lands with the release. Until then, no numbers.
One task in a real Go repository, the same model, Claude Code, Codex, OpenCode, Pi and mado at their defaults, medians of five runs. The scripts live in bench/, so you can run the same comparison on your own repo.
tokens entered · cost · peak RAM (PSS) · wall clock: pending until the release
Questions worth asking first.
My harness already shows a context bar. What is this?
A bar is the state of the window: how full it is now. mado shows what entered it on a given call, by difference of reported numbers, and why the cache missed, from the hashes of the system prompt and the tools in the request that was actually sent. The bar is the state; the call is what you paid for.
Does the profiler cost extra calls or tokens?
No. It measures bytes already sent: nothing goes into the payload, and profiler on or off produces the same sequence of request hashes. The fixed prefix will be counted once per hash with count_tokens, as a separate request, never one per tool.
Where does my code go?
To the provider you configured, and nowhere else: no telemetry, no account, no proxy of ours. Sessions live in one SQLite file in your data folder, and a redactor turns a secret read from a file into a stable placeholder before it enters the window.
Where do the prices come from?
The models.dev catalog, cached for a day, with an override in the config; on OpenRouter, the cost it reports. The rate is frozen in the log, so an old call keeps the price it was paid at. Without a price there is no cost, and mado says $n/a instead of $0.00.
What does "served by Wafer, not Baidu" mean?
OpenRouter sends a model to several upstream providers, and each keeps its own cache. In the session above it sent call 1·2 to Baidu instead of Wafer, then the next run back to Wafer: 8.8k and 6.7k tokens written again, about $0.0006 more. A timer would have guessed an expired cache; the response names the upstream, so mado says which.
Windows?
macOS and Linux at launch, amd64 and arm64; Windows runs it from WSL2.
Why Go?
One binary, no cgo, no runtime to install, and a target of tens of megabytes of RAM, measured with the release and published with the method. And mado is a library first: the profiler is a client of the same packages you import, not a special case in the core.
What doesn't it do?
No sandbox: bash runs as you, and the boundary is the permission prompt, which a shell can walk around. Run it in a container for real isolation. No telemetry, no hosted service, no subscription login.
License?
Planned: AGPL-3.0, plus a commercial license for uses that can't meet its terms, and a contributor agreement.
One binary, your key, and the folder you're already in.
The first release is planned for December 2026: signed binaries for macOS (notarized) and Linux, amd64 and arm64, and nothing else to install. Until then, follow the release; when it's out, this is all it takes.
An Atom feed for any feed reader: one entry for each release, and nothing collected.
- 1 · install, from December 2026$brew install Mediacom99/or
tap/mado $go install github.com/Mediacom99/mado/cmd/mado@latest - 2 · a key, once$export ANTHROPIC_API_KEY=sk-ant-…or
/loginin the TUI - 3 · in your project$mado
Any server that speaks Chat Completions (llama.cpp, Ollama, LM Studio, vLLM) is one entry, typed in the TUI. When a server doesn't report a number, the profiler says n/a instead of guessing.