Menu ▾ ▴

#67 llmslim wrap claude: cache-safe tool-output compression for coding agents

closed
nobody
None
2026-10-18
2026-10-17
Anonymous
No

Originally created by: Thanatos9404

Why

The 17 Oct demand research ranked these developer pains highest, by GitHub reactions and HN points:

  1. Long agent sessions lose work to context rot and compaction: Claude Code and Codex issues with 100–156 reactions.
  2. Prompt-cache breakage drives cost: Claude Code [#46829] has 341 reactions.
  3. Tool-output bloat.

Headroom, a tool-output compressor with a wrap command, has 75k stars and 293k PyPI downloads a month. This is LLMSlim's version, built around the two things a naive compressor breaks: prompt caching and Claude's preserved thinking.

How it works

pip install "llmslim[proxy]", then llmslim wrap claude. The command:

  • starts a local proxy on a free loopback port;
  • runs Claude Code with ANTHROPIC_BASE_URL pointing at it;
  • prints the session's savings at the end.

The proxy itself:

  • First sight: tool_result text after the last assistant turn is output the model hasn't seen yet. If it comes from Bash, PowerShell, Grep, Glob, WebFetch, WebSearch or Monitor and is over 1,500 tokens, it is compressed.
  • MCP tools are opt-in (--tool mcp__github__list_issues or --mcp). Some return live state the agent acts on: a shortened Playwright snapshot with no query dropped most of a page's buttons, which the agent needs to click. LLMSlim's line-aware selection keeps errors and the lines related to the command, collapses runs of similar lines, and adds a one-line note.
  • Claude Code appends a system message after tool results, so "new output" can't mean "the last message". Real Claude Code traffic showed this.
  • Replay: the decision is stored under sha256(tool_use_id, text), and every later request sends the stored bytes. Nothing the model has already seen ever changes, so the prefix stays cacheable and thinking signatures stay valid.
  • Never touched:
  • Read, Edit and Write output, and any unlisted or new tool;
  • output from before the proxy started;
  • system prompts, tools, assistant turns, thinking, cache_control and headers.

Responses, including SSE, are relayed chunk by chunk.

  • Safety:
  • It listens on loopback only (--allow-remote to override).
  • Credentials, including a subscription login, are forwarded and never stored or logged.
  • A failed rewrite forwards the original.
  • It refuses an upstream that points back at itself.

Evidence

Check Result
Anthropic API, Claude Haiku 5.5, adaptive thinking, Claude Code's cache layout 7 requests with thinking in the history, all 200. Cache reads grew every turn (8,554 → 9,739). A 10,545-token pytest log went out as 156 tokens, 5 times over: 62,334 input tokens not sent
Control: the same final request sent directly with the original log HTTP 400: "Invalid signature in thinking block. The block is bound to a different conversation." The byte-for-byte replay is load-bearing
Real Claude Code 2.1.296 via llmslim wrap claude -p ... A 6,045-token log reached the model as 156 tokens. The answer named the failing test, its assertion and the pass count correctly

Spend for all live checks: a few cents on Haiku 5.5. The key was read into environment variables inside each command and never printed.

Honest limit: Claude Code already saves output over about 30 KB to a file and shows the model a 2 KB preview. The proxy sees only that preview, so it works on output the model gets in full (about 1.5k–7.5k tokens) and on MCP and web results. This is documented in docs/PROXY.md.

Smarter JSON handling (keep every item of a list, prune verbose fields) is a follow-up. Today a list result keeps the window around the items related to the call.

Tests

  • tests/test_proxy.py: the pure rewrite. It covers:
  • first sight and replay;
  • untouched old output;
  • non-listed tools, including future ones;
  • Claude Code's trailing system message;
  • images and cache_control kept;
  • input never mutated;
  • determinism, first decision wins, and the stats.
  • tests/test_proxy_http.py: the HTTP layer against a fake API that binds "thinking" to the exact prefix and rejects a changed replay, as Anthropic does. It covers:
  • header forwarding and query strings;
  • the full agent loop;
  • SSE and other paths (/v1/models, HEAD /api/hello);
  • count_tokens rewritten but not double-counted;
  • 429 with retry-after passed through;
  • gzip bytes;
  • fail-open;
  • 502 when the upstream is unreachable;
  • wrap running an agent against a live proxy;
  • the CLI guards.
  • Full suite: 1,804 passed, 8 skipped, coverage 93.71% (proxy modules 90–93%). Ruff is clean. mypy shows no errors in the new modules.

Not in this PR

  • Codex and OpenAI-format agents.
  • An expand tool to fetch the full original. The originals are already stored for it.
  • Team savings dashboards: a candidate paid feature, per the research.

Related

Tickets: #22
Tickets: #68
Tickets: #69

Discussion

  • Anonymous

    Anonymous - 2026-10-17

    Originally posted by: vercel[bot]

    The latest updates on your projects. Learn more about Vercel for GitHub.

    Project Deployment Actions Updated
    llmslim Ready Ready Preview <relative-time datetime="2026-10-17T10:10:21.761Z">Oct 17, 2026 10:10am UTC</relative-time>
     
  • Anonymous

    Anonymous - 2026-10-17

    Ticket changed by: Thanatos9404

    • status: open --> closed
     

Log in to post a comment.