<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Anil Vishwakarma</title>
    <description>The latest articles on DEV Community by Anil Vishwakarma (@anil_vishwakarma_e5874c59).</description>
    <link>https://dev.to/anil_vishwakarma_e5874c59</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4228578%2F9a24c212-91cf-4288-a1fb-a913c29e0e85.png</url>
      <title>DEV Community: Anil Vishwakarma</title>
      <link>https://dev.to/anil_vishwakarma_e5874c59</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anil_vishwakarma_e5874c59"/>
    <language>en</language>
    <item>
      <title>What I learned building a lossless token compressor for Claude Code</title>
      <dc:creator>Anil Vishwakarma</dc:creator>
      <pubDate>Thu, 05 Nov 2026 12:52:55 +0000</pubDate>
      <link>https://dev.to/anil_vishwakarma_e5874c59/what-i-learned-building-a-lossless-token-compressor-for-claude-code-421j</link>
      <guid>https://dev.to/anil_vishwakarma_e5874c59/what-i-learned-building-a-lossless-token-compressor-for-claude-code-421j</guid>
      <description>&lt;p&gt;In a long Claude Code session, most of what gets sent to the API isn't your prompts. It's tool output: JSON from APIs, command logs, grep results, the same file read twice. And because the whole conversation is resent on every turn, that output is paid for again and again.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://github.com/an21an21/tokentrimmer" rel="noopener noreferrer"&gt;TokenTrimmer&lt;/a&gt;, a small local proxy that compresses tool output before it reaches the API, and spent most of the time measuring what actually works. Here's what I learned.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Synthetic benchmarks flatter compression tools
&lt;/h2&gt;

&lt;p&gt;On synthetic payloads (big JSON arrays, repetitive logs), TokenTrimmer cuts 50% or more. On 9 of my own real Claude Code sessions (1,237 requests), the lossless mode saved &lt;strong&gt;7.2%&lt;/strong&gt; on the final request.&lt;/p&gt;

&lt;p&gt;The gap is simple: synthetic tests are made of exactly the shapes a compressor is built for. Real sessions are mixed: plenty of prose, file reads and short outputs where there's nothing to squeeze. So the README leads with the real-session number, and &lt;code&gt;compare/&lt;/code&gt; lets anyone reproduce it on their own sessions.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Prompt caching changes the maths
&lt;/h2&gt;

&lt;p&gt;With Anthropic's pricing, reading a cached prefix costs 10% of the normal input price, and writing the cache costs 125%. The cache matches on the exact bytes at the start of the request.&lt;/p&gt;

&lt;p&gt;That means a compressor that edits &lt;em&gt;earlier&lt;/em&gt; turns pays twice: every edit invalidates the cached prefix from that point on, and everything after it is billed again at the write price. In my replay, a mode from another tool that made each request &lt;strong&gt;5.8% smaller&lt;/strong&gt; ended up making the session &lt;strong&gt;11% more expensive&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So TokenTrimmer has one hard rule: it only ever appends. A message's compressed form depends only on that message and the ones before it, and the same input always gives the same bytes. The prefix stays byte-identical from turn to turn, and cache hits continue. (It also matters for Claude's signed thinking blocks, which are rejected if earlier history changes.)&lt;/p&gt;

&lt;p&gt;The lesson: judge compression by &lt;strong&gt;cache-weighted cost&lt;/strong&gt;, not by how much smaller one request gets. Lossless mode came out &lt;strong&gt;5.3% cheaper&lt;/strong&gt; on that measure.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Verify every change, and fail open
&lt;/h2&gt;

&lt;p&gt;Every encoding in the default mode has a decoder: JSON arrays of objects become compact tables, log lines sharing a pattern store it once, grep output is grouped by directory. Before each request is sent, a verifier decodes every rewritten tool result and checks it against the original. If anything doesn't match, the original request goes out unchanged.&lt;/p&gt;

&lt;p&gt;To check that the model loses nothing, I asked Claude Opus 5.5 to recall exact lines of old tool output from the compressed conversations. Lossless mode scored &lt;strong&gt;140/140&lt;/strong&gt;, the same as the uncompressed original, plus 38/38 on questions whose answer sat behind a reference.&lt;/p&gt;

&lt;p&gt;It also leaves alone what it shouldn't touch: system prompts, your messages, tool definitions, and results from file tools like Read and Edit, so edits still match the file exactly.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. The biggest win wasn't clever encoding
&lt;/h2&gt;

&lt;p&gt;Agents re-read the same lines constantly: the same file section, the same test output after a small change. Replacing lines the model already has with a short reference, such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[same as message 175 lines 16-19]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;nearly doubled the savings compared with the encodings alone. It's about 12 tokens instead of the whole block, and it's still lossless: the verifier expands each reference against the request being sent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mode&lt;/th&gt;
&lt;th&gt;Lossless&lt;/th&gt;
&lt;th&gt;Final request&lt;/th&gt;
&lt;th&gt;Cost with caching&lt;/th&gt;
&lt;th&gt;Added latency&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;TokenTrimmer safe (default)&lt;/td&gt;
&lt;td&gt;yes, every request verified&lt;/td&gt;
&lt;td&gt;7.2% smaller&lt;/td&gt;
&lt;td&gt;5.3% cheaper&lt;/td&gt;
&lt;td&gt;~9 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TokenTrimmer aggressive&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;14.3% smaller&lt;/td&gt;
&lt;td&gt;11.6% cheaper&lt;/td&gt;
&lt;td&gt;~9 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TokenTrimmer stale10&lt;/td&gt;
&lt;td&gt;no&lt;/td&gt;
&lt;td&gt;29.8% smaller&lt;/td&gt;
&lt;td&gt;16.4% cheaper&lt;/td&gt;
&lt;td&gt;~9 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The lossy modes are opt-in, and the README lists their measured accuracy cost.&lt;/p&gt;

&lt;p&gt;It also works with Codex (&lt;code&gt;tokentrimmer codex&lt;/code&gt;, with a ChatGPT login or an API key). Expect less there: on 78 of my Codex sessions the lossless mode saved 3.8% per request on average, because Codex already trims long command output.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; tokentrimmer
tokentrimmer claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That starts the proxy in the background and runs Claude Code through it. &lt;code&gt;tokentrimmer savings&lt;/code&gt; shows what it has saved, and a local dashboard shows the before and after text of every changed request. To measure without changing anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tokentrimmer &lt;span class="nt"&gt;--dry-run&lt;/span&gt; claude
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your number will differ from mine: sessions heavy on API responses and logs save more, sessions that are mostly file edits save less.&lt;/p&gt;

&lt;p&gt;It's MIT-licensed, has zero dependencies, and runs entirely on your machine: &lt;a href="https://github.com/an21an21/tokentrimmer" rel="noopener noreferrer"&gt;https://github.com/an21an21/tokentrimmer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd love to hear what numbers you get, and any criticism of the measurement method.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>opensource</category>
      <category>llm</category>
    </item>
  </channel>
</rss>
