pxpipe cuts Claude Code’s token bill 60% by sending context as pictures
A local proxy renders bulky context as images because a model reads them by gist, which is cheaper and, for exact strings, quietly wrong
In about ~4 minutes you’ll know what pxpipe swaps text for, why the swap saves money, where it quietly breaks, and how to tell if it pays on your own traffic.
pxpipe is a local proxy that cuts Claude Code’s input tokens by rendering the bulky parts of a request, the system prompt, tool docs, and older history, into PNG images before they reach the model. On a 13,709 request production snapshot it cut the end to end bill by 59%, from about $100 to $41. A later denser trace measured closer to 70%. It runs behind Claude with two lines and streams responses normally because it compresses the request only, not the output.
The saving comes from a pricing quirk. An image costs a fixed number of vision tokens set by its pixel area, so a page holding 150 characters and a page holding 15,000 cost the same, while text is billed per character, which means you can pack a wall of dense tool output onto one page and pay a flat image rate instead of a per character bill.

Setup is two commands
Setup is two commands. Start the proxy then point Claude Code at it.
npx pxpipe-proxy # proxy on 127.0.0.1:47821 ANTHROPIC_BASE_URL=http://127.0.0.1:47821 claude # point Claude Code at itThe proxy intercepts /v1/messages and runs each bulky block through a profitability gate before deciding to image it. That gate matters because the trade only pays on dense content. Claude Code traffic runs about 1.9 characters per token and pxpipe’s dense renders hold roughly 3.1 characters per image token, so the picture wins by around 3x. English prose runs near 3.5 characters per token, where the image loses money, prose stays as text. Recent turns stay text too. Only the static prompt slab and older collapsed history get imaged.
Why the gist survives and exact strings don’t
A vision encoder does not read the page character by character. It builds a rough summary of what the image holds, a code block here, some hex-looking tokens there and the model works off that summary. Decisions, values, paths, and names are distinctive enough to survive the pass but a random 12-character hex string is not, so it drops.
The maintainer measured both sides of that line with an A/B harness that plants facts in synthetic sessions and grades by exact string match without a model acting as judge.
The misses are something to watch, you can easily catch a blank, but a confident wrong hex you cannot, and nothing downstream will flag it for you. This happened once in weeks of real use. The model pulled a person’s name from imaged history and stated the wrong one without any hint it wasn’t sure. Coding sessions mostly absorb it, since the agent re-reads files before it edits and catches its own slip, whereas plain recall has no such backstop. That is why the gate keeps bulk history as images and holds anything exact like IDs, hashes, numbers, back as text.
Does the bug still get fixed?
Passing recall tests doesn’t mean the actual work still gets done, so two SWE-bench pilots checked exactly that. On SWE-bench Lite both versions resolved 10 of 10 while the imaged one ran on 65% smaller requests, and on the harder SWE-bench Pro imaging scored 14 of 19 against 15 of 19 without it, with the two agreeing on 18 of 19 outcomes. The one case they split on re-resolved 3 of 3 when run again, which points at normal run to run variance rather than a compression penalty, though the samples are small and the writeup says so.
Opus 4.7 and 4.8 misread about 7% of renders, so the default allowlist is Fable 5 and GPT 5.6 only, with everything else passing through as plain text. PNG encoding also adds latency to a big request before it leaves and the guard that would make byte-exact blocks safe on their own does not exist yet, which the maintainer lists as the main missing piece.

What this actually changes
What the numbers describe is a way to think about model memory. An image holds the meaning of old context and loses the spelling. So put the skimmable stuff in pixels, the task so far, the decisions, the files already opened and keep the exact stuff like IDs and hashes in text. Most context trimming tools leave you guessing what got dropped. Here you know the shape of the loss going in. Whether it nets out on your workload depends on how dense your traffic is and how often your agent re-reads before it acts. The events log lets you check that against your own bill rather than take the 60% on faith. Try it on one real session
To see it on your own numbers:
Point Claude Code at the proxy for a single dense coding session.
Open ~/.pxpipe/events.jsonl and compare the free count_tokens counterfactual against what you were actually billed.
If your traffic is dense, the math is already settled. If it’s mostly prose, the gate leaves it as text and you’ve lost nothing but the two lines it took to try.
Sources
• pxpipe on GitHub, README, benchmarks, and FAQ
• FINDINGS.md, the recall and legibility analysis
• TRANSFORM_INFO.md, how the static slab is cached
• SWE-bench receipts in the eval directory
The newsletter 300,000+ developers read to keep up with AI. We rank the top models, repos, and papers so you don’t have to. Subscribe at alphasignal.ai/newsletter



