Skip to content

Commit c8f7bb8

Browse files
docs(readme): answer the trust question before asking for the install (cnighswonger#299)
A reader's agent publicly declined to recommend this project on two grounds: its cache was already healthy, and it disliked that the proxy rewrites every request. Both objections were already answered in the README — 480-610 lines below where they arise. Reading order defeated the content. Adds above Quick Start: what the proxy does to your traffic (including that it is idempotent, the sentence that answers the rewriting objection); who does not need this; and a command to check whether you do. Nothing removed — Security model stays complete and is linked from the new block, and the access disclosure is kept verbatim. The measurement runs on stock Claude Code with nothing installed, and dedups by requestId because CC writes a varying number of transcript rows per request. Verified by extracting the command from the file and running it against a no-usage transcript, a real session, and a nonexistent path. Codex round 1 caught two real defects: the command divided by zero on an empty transcript, and the trust block claimed 'no other outbound calls' when two opt-in paths perform their own egress. Both fixed; round 2 confirmed no third egress path exists. Closes cnighswonger#298
1 parent 23346ac commit c8f7bb8

3 files changed

Lines changed: 152 additions & 0 deletions

File tree

README.md

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,89 @@ English | [中文](./README.zh.md) | [한국어](./README.ko.md) | [Português](
66

77
Cache optimization proxy for [Claude Code](https://github.com/anthropics/claude-code). Fixes prompt cache bugs that cause excessive quota burn, stabilizes the request prefix, and monitors for silent regressions. Works with all CC versions including the v2.1.113+ Bun binary.
88

9+
*This README documents current `main`; release availability is noted per feature.*
10+
11+
## What it does to your traffic
12+
13+
A local proxy sits between Claude Code and Anthropic. Before you read further,
14+
here is exactly what that means — the full treatment is in
15+
[Security model](#security-model).
16+
17+
- **Binds to `127.0.0.1`** by default.
18+
- **Forwards Claude Code traffic to Anthropic. On the default path it makes no
19+
other outbound calls** — telemetry is written to local files under
20+
`~/.claude/`, never sent anywhere. Two opt-in features do perform their own
21+
egress, both off unless you enable them: OAuth refresh
22+
(`CACHE_FIX_OAUTH_REFRESH=on`) posts to Anthropic's token endpoint, and
23+
forward-proxy download acceleration re-issues release downloads to
24+
`downloads.claude.ai` / `storage.googleapis.com`.
25+
- **Can read and rewrite `POST /v1/messages`.** That capability *is* the cache
26+
repair — there is no version of this that works without it.
27+
- **It is idempotent: if nothing needs fixing, the request passes through
28+
unmodified.** It normalizes request structure (block order, fingerprint, TTL);
29+
it does not modify your conversation.
30+
- **Each transform is one file** in `proxy/extensions/`, readable in isolation.
31+
- [Independently assessed as a legitimate tool](https://github.com/anthropics/claude-code/issues/38335#issuecomment-4244413605)
32+
by @TheAuditorTool (2026-04-14).
33+
34+
Forward-proxy mode (`--remote-control`) additionally terminates TLS for
35+
`api.anthropic.com` using a locally-generated CA, which your client must trust.
36+
Everything else is blind-tunnelled. That mode is opt-in and off by default.
37+
38+
## Do you need this?
39+
40+
**Install or test it if:** resumed or long-running sessions show repeated
41+
`cache_creation_input_tokens` spikes; your cache-read ratio is low or unstable;
42+
you see unexpected TTL 5m downgrades, thinking-desync `400`s, or image-retry
43+
storms; or one of the non-cache surfaces documented below applies.
44+
45+
**You can skip it if:** your sessions already hold a stable high cache-read
46+
ratio; you rarely resume long sessions; you are not under quota pressure; or you
47+
would rather not place a local proxy in the API path. **All four are good
48+
reasons not to install this.**
49+
50+
If you are not sure which applies, measure it — you do not need this project
51+
installed to find out.
52+
53+
## Check whether you have this problem
54+
55+
Claude Code already records per-request cache accounting in its own session
56+
transcripts, so you can measure your cache health right now, before installing
57+
anything.
58+
59+
```bash
60+
# Replace <session-uuid>, or use a glob to pick your most recent session.
61+
jq -r 'select(.message.usage.cache_read_input_tokens != null) |
62+
"\(.requestId)\t\(.message.usage.cache_read_input_tokens) \(.message.usage.cache_creation_input_tokens)"' \
63+
~/.claude/projects/*/<session-uuid>.jsonl |
64+
sort -u -k1,1 | cut -f2 |
65+
awk '{n++; r+=$1; c+=$2}
66+
END {if (n==0) print "no usage rows found — check the session path";
67+
else printf "requests=%d cache_read=%d creation=%d read-ratio=%.0f%%\n", n, r, c, 100*r/(r+c)}'
68+
```
69+
70+
`sort -u -k1,1` counts each API call once — Claude Code writes multiple
71+
transcript rows per request, and **not always the same number of times per
72+
request** ([ArkNill's analysis](https://github.com/ArkNill/claude-code-hidden-problem-analysis)).
73+
Summing raw rows weights each call by its own duplicate count. Two independent
74+
sweeps of the local transcripts on one machine (2026-08-02) agreed on the shape:
75+
**short sessions are where this bites** — over half of sessions under 20 requests
76+
shifted by a point or more without the dedup, worst case **41 points**, while
77+
long sessions were almost all sub-point (3 of ~37). Short sessions are exactly
78+
what a first-time reader will run this against.
79+
80+
Reading the result:
81+
82+
- **Fewer than ~20 requests: the number is meaningless.** A cold start has
83+
nothing to read yet, so creation dominates and every healthy session looks
84+
broken. Use a long or resumed session.
85+
- **Sustained low ratio on a long session, or `creation` spiking on every
86+
`--resume`** — that is the problem this project exists to fix.
87+
- **High ratio on a long session** — you do not need this. See *Do you need
88+
this?* above.
89+
90+
## Current advisories
91+
992
> **v4.0.0** — Local HTTP proxy with a pipeline of cost-impact and observability extensions. Two long-standing defaults flipped: `thinking-block-sanitize` v1 is on by default (mitigates the thinking-desync `400` wedge — [#63147](https://github.com/anthropics/claude-code/issues/63147)) and in-process extension hot-reload is opt-in (`CACHE_FIX_HOT_RELOAD=on`). A/B baseline (v3.0.0 on v2.1.117): **95.5% cache hit rate through proxy vs 82.3% direct** on first warm turn. [Full release notes →](https://github.com/cnighswonger/claude-code-cache-fix/releases/tag/v4.0.0)
1093
1194
> **Opus 4.7 advisory:** Metered data shows 4.7 burns Q5h quota at **~2.4x the rate of 4.6** for equivalent visible token counts ([independently confirmed by @ArkNill](https://github.com/ArkNill/claude-code-hidden-problem-analysis/blob/main/16_OPUS-47-ADVISORY.md)). Two factors: a new tokenizer (up to 35% more tokens, [documented](https://platform.claude.com/docs/en/about-claude/models/whats-new-claude-4-7)) and adaptive thinking overhead (~105%, not documented in usage response). The Q5h impact compounds into **Q7d** — the weekly quota ceiling that most heavy users will hit first. Workaround: `CLAUDE_CODE_DISABLE_ADAPTIVE_THINKING=1` reduces burn by ~3.3x but may reduce quality on complex tasks. See [Discussion #25](https://github.com/cnighswonger/claude-code-cache-fix/discussions/25) (initial observation) and [Discussion #42](https://github.com/cnighswonger/claude-code-cache-fix/discussions/42) (controlled A/B data + Q7d analysis).
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# Review: PR #299 README trust reorder
2+
3+
Date: 2026-08-02
4+
Reviewed: `README.md` at `9ef96c6a33bf2424030b8dad15e6107bd92bfafc`
5+
Round: 1
6+
Label applied: changes-requested
7+
8+
## What Is Correct
9+
- [Measured] Line 7 is byte-identical to `origin/main`. Command: `node ... compare README line 7``"equal": true`.
10+
- [Read] The access disclosure remains verbatim and `## Security model` still exists later in the file at `README.md:667-677`; the new summary links to `#security-model` from `README.md:15`.
11+
- [Read] The default bind claim is supported by code: `proxy/config.mjs:27-29` defaults `bind` to `127.0.0.1`, and `proxy/server.mjs:531-599` listens on that bind.
12+
- [Read] The "`POST /v1/messages` can be read and rewritten" claim is supported by `proxy/server.mjs:466` routing that path into `handleMessages`, whose pre-forward pipeline mutates `ctx.body` / `ctx.headers` before forwarding (`proxy/server.mjs:82-119`, `148-157`).
13+
- [Read] The "stock Claude Code already writes the transcript fields" premise holds up. In the extension tree, the only `projects/` reference is a comment in `proxy/extensions/usage-log.mjs:47-49`; no extension writes under `~/.claude/projects/`. Writes go to other `~/.claude/*` paths such as `usage.jsonl`, `quota-status`, and session mirrors (`proxy/extensions/usage-log.mjs:279-287`, `proxy/extensions/cache-telemetry.mjs:292-333`, `proxy/session-mirror-writer.mjs:6-23`).
14+
15+
## Blockers
16+
- [Measured] `README.md:54-60` says the one-liner can be run before installing anything, but the exact command as written exits non-zero on a real transcript that has no usage rows. Command run verbatim from the fenced block with only `<session-uuid>` replaced: `jq ... ~/.claude/projects/*/c8e70b6e-7ef4-40b6-9762-33b1e8a64236.jsonl | sort -u -k1,1 | cut -f2 | awk ...``status=2`, `awk: cmd. line:1: fatal: division by zero attempted`. This was the highest-risk item called out for the review, and in the new trust-earning section it needs to fail safe.
17+
- [Read] `README.md:18-19` overstates the code with “makes no other outbound calls.” That is not true across the shipped code paths. Opt-in OAuth refresh does a direct `fetch(..., { method: "POST" })` in `proxy/oauth/refresher.mjs:223-228`, and forward-proxy download rewrite re-issues requests to `storage.googleapis.com` / `downloads.claude.ai` in `proxy/forward-proxy.mjs:337-375` and `437-463`. The existing late security section already says “No network calls,” but this PR duplicates that claim into the prominent top trust block where readers are asked to rely on it. It needs a qualifier such as “by default” or a narrower statement about unsolicited/self-initiated calls.
18+
19+
## What Needs Attention
20+
- [Measured] I did not reproduce the README’s exact “183 local sessions / 90% of short sessions” statistic with an independent sweep over the current top-level local transcripts. Command: a line-by-line Node pass over `~/.claude/projects/*/*.jsonl`, top-level sessions only, valid JSONL only, dedup by `requestId` per file. Result: `total=276`, `short(<20)=240`, `short |delta|>=1pt = 128 (53%)`, `long(>=20)=36`, `long |delta|>=1pt = 3 (8%)`, `worst=41.106...`. The worst-case and long-session shape line up, but the population size and short-session percentage do not. That does not prove the README number is wrong; it does show the sample boundary is underspecified enough that an independent measurement on the same host later the same day lands elsewhere.
21+
- [Measured] The executable command does work on a real session with usage rows, and the placeholder is clearly a placeholder. Command extracted from `README.md:54-60` with only `<session-uuid>` replaced by `a27d470e-2b89-4077-9475-6de4fc347c14` ran successfully and returned `cache_read=4942913870 creation=51231243 read-ratio=99%`. The placeholder clarity comes from the literal angle-bracket token in `README.md:55,58`; the problem is the zero-row case above, not placeholder ambiguity.
22+
23+
## Bloat / Non-Functional
24+
- [Measured] Proportionate. Diff size is `+75/-0` in `README.md` only. Production LOC: `0`. Test:prod ratio: not applicable. New files / exports / env vars / on-disk paths: `0`. Comment:code ratio: not applicable for a docs-only PR.
25+
26+
## Recommendations
27+
- Guard the `awk` denominator so a transcript with zero matching rows prints an explanatory message and exits cleanly instead of failing. This needs to be fixed in the exact command readers are told to run first.
28+
- Soften the outbound-call bullet to match code reality. The safest version is to scope it to the default reverse-proxy path and explicitly exclude opt-in features that perform their own egress.
29+
- If the short-session dedup statistic stays in the README, state the sample boundary precisely enough that another reviewer can reproduce the same population.
30+
31+
## Bottom Line
32+
The reordering itself is directionally right and the acceptance criteria about line 7, the access disclosure, and the retained security section are met. I am not approving this pass because the new “measure before install” command still breaks on a real no-usage transcript, and the new top-level trust summary currently makes a stronger outbound-traffic claim than the code supports. Fix those two items and this should be ready for a quick re-review.
33+
34+
— Codex review
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Review: PR #299 README trust reorder
2+
3+
Date: 2026-08-02
4+
Reviewed: `README.md`, `proxy/config.mjs`, `proxy/forward-proxy.mjs`, `proxy/oauth/refresher.mjs` at `1b776d9`
5+
Round: 2
6+
Label applied: approved-by-codex-agent
7+
8+
## What Is Correct
9+
10+
- [Measured] The README's published cache-health command now handles the no-usage case cleanly. Extracting the command block from `README.md:59-67`, replacing `<session-uuid>` with `c8e70b6e-7ef4-40b6-9762-33b1e8a64236`, and executing it returned `no usage rows found — check the session path` with `EXIT=0`.
11+
- [Measured] The same extracted command still works on a session with usage rows. Replacing `<session-uuid>` with `a27d470e-2b89-4077-9475-6de4fc347c14` returned `requests=11733 cache_read=4942913870 creation=51231243 read-ratio=99%` with `EXIT=0`. Independently counting unique `requestId` values in that transcript also produced `11733`, so the new `requests=` field is accurate for the "fewer than ~20 requests" guidance in `README.md:75-83`.
12+
- [Read] The top trust block no longer overstates the outbound-traffic claim. It now scopes the statement to the default path and names the two opt-in exceptions in `README.md:18-24`. Both exceptions are default-off in code: OAuth refresh is gated by `process.env.CACHE_FIX_OAUTH_REFRESH === "on"` in `proxy/config.mjs:46-49`, and download rewrite is gated by `process.env.CACHE_FIX_DOWNLOAD_REWRITE === "on"` plus bucket discovery in `proxy/config.mjs:65-79` and `proxy/forward-proxy.mjs:38-44,482-486`.
13+
- [Read] I did not find a third shipped egress path beyond Claude Code traffic to Anthropic and the two named opt-in exceptions. The only proxy-local outbound network initiators in `proxy/` are the OAuth refresh POST in `proxy/oauth/refresher.mjs:223-228`, the forward-proxy tunnel / relay path for normal upstream traffic in `proxy/forward-proxy.mjs:266,298,371,437`, and the download-rewrite path guarded by `downloadRewriteActive()` in `proxy/forward-proxy.mjs:42-44,482-486`.
14+
- [Measured] The softened duplicate-row statistic is supported by my round-1 sweep. The surviving README claim in `README.md:75-77` matches the earlier measured shape: short sessions over half at `128/240 = 53%`, worst case `41.106...`, and long sessions `3/36`, which the README rounds to `3 of ~37`.
15+
- [Measured] The round-1 invariants remain intact. `README.md:7` is byte-identical to `origin/main`, the access disclosure at `README.md:25-26` is unchanged, the `## Security model` section at `README.md:675-685` is byte-identical to `origin/main`, and the anchor target remains the literal `## Security model` heading (`#security-model`).
16+
17+
## Blockers
18+
19+
None.
20+
21+
## What Needs Attention
22+
23+
None.
24+
25+
## Bloat / Non-Functional
26+
27+
None. Documentation-only PR; no production code added.
28+
29+
## Recommendations
30+
31+
Approve PR #299.
32+
33+
## Bottom Line
34+
35+
Round-1 blockers are closed. The executable README command now fails soft on empty transcripts, the trust block's outbound-traffic statement is aligned with the shipped gates, and the surviving statistics are within the bounds of the independently measured data. This is ready to merge.

0 commit comments

Comments
 (0)