Inside the Pi Harness: The Agent That Shows You the Meter
Every coding agent bills you through a mechanism you cannot see: the prompt cache. Pi, the coding agent from Earendil, is the only mainstream harness I have found that treats that invisible meter as a user interface. Reading its source (pinned at commit bf4a90d8) is a course in what a harness actually is: a machine for keeping token prefixes stable.
A twenty-line system prompt
Pi's entire default system prompt is about twenty lines: an identity sentence, a list of one-line tool snippets, a few guidelines, pointers to its own docs on disk, project instructions, a skills index, and the working directory as the last line. No timestamp, no date, no random values. That is not minimalism for taste; it is cache discipline. Anything dynamic near the top of the prompt invalidates every cached token after it, and Pi's own engineering writing lists dynamic system prompts as one of the eight canonical causes of cache misses. The prompt loads AGENTS.md (or CLAUDE.md) from global config down through ancestor directories, and even handles the case where a git worktree would double-load the same file.
Sessions are trees, not lists
Pi stores a session as JSONL where every entry has an id and a parentId. The transcript is a tree. /tree moves the active leaf anywhere in the file; a rewind is just moving the leaf, nothing is deleted; abandoned branches get an LLM-written summary attached at the common ancestor. Newer compactions carry a materialized retainedTail, which makes each one a self-contained checkpoint you can branch from. Most harnesses treat history as an append-only log and rewinding as truncation. Pi treats history as version control.
Click any entry to move the active leaf, exactly what /tree does. The path from root to leaf is the prompt the model sees. Watch the file on the right: it only ever grows.
The refusal to prune
The counterintuitive position at the center of Pi: it does not prune old tool results, and the reason is arithmetic. Deleting content from the middle of a transcript changes the token prefix at the deletion point, so every surviving token after it gets re-billed at the uncached rate. Their break-even, quoted from the caching post:
one-time rewrite cost ≈ surviving tokens × (uncached price − cache-read price)
future savings per turn ≈ pruned tokens × cache-read price
For a long session the rewrite usually loses. So Pi compacts only under real context pressure (default: within 16,384 tokens of the window), keeps roughly the last 20,000 tokens verbatim, summarizes the rest with a fixed structured template, and appends the compaction as a new entry rather than rewriting history. One detail I admire: the summarization request itself is sent with caching disabled and a fresh session id, because a cache write for a one-shot summary is a write that can never be reused.
The meter
Pi's footer shows cumulative cache reads and writes and the latest request's hit rate. /session goes further and prints a line no other harness prints: Cache Re-billed: $0.73 (161,744 tokens, 2 misses). It computes misses conservatively, attributes causes where it can observe them ("cache miss after model switch", "cache miss after 12m idle"), and deliberately does not count compaction as a miss, because a compaction is a chosen cache reset, not a failure. Model switches do count, because they re-bill the full prompt whether you meant to or not. When a five-minute provider TTL expires while you review a diff, Pi is the harness that tells you what that coffee break cost.
Tools that load without breaking the cache
Tool definitions sit near the front of the prompt, so adding a tool mid-session normally invalidates the entire cached conversation behind it. Pi implements additive loading: an extension keeps a search tool active, activates new tools during a tool call, and Pi records the additions on that tool result. On models that support it, the new definitions attach at that point in the transcript, and the old prefix survives. On Anthropic that is defer_loading plus a tool_reference block; on OpenAI, fabricated tool-search items; everywhere else, a fallback that sends the full list and may eat the cache. The mechanism exists precisely because a few saved schema tokens can cost tens of thousands of re-billed conversation tokens.
The anti-features
Pi's README lists what it refuses to build: no MCP, no sub-agents, no permission popups, no plan mode, no built-in todos, no background shell. Everything is an extension, a skill, or your terminal multiplexer. There is no permission system at all; the boundary is the container you run it in. You can disagree with any of these choices, and I do with a couple, but they are coherent: every feature the harness owns is prompt surface it must keep stable, and Pi's bet is that a small, stable core plus user-owned extensions beats a large surface it would have to defend.
A harness is a machine for keeping prefixes stable. Pi is what you get when you take that sentence literally.
Two things to watch with appropriate skepticism: the remote-session stack (CBOR protocol, server package) is explicitly experimental, and Pi's relationship with subscription providers is complicated enough that you should read their own writing on session portability rather than my summary. But as a study object, no harness teaches faster. The meter is visible. Sources: the pi repo, and Earendil's posts on prompt caching and session portability.