docs(readme): fix broken links and code block formatting in readme

docs: fix remaining formatting bugs

docs: tweak a couple lingering nitpicks
This commit is contained in:
2026-06-20 02:47:59 -04:00
parent 5462d0fee3
commit 44f06a33e1
2 changed files with 34 additions and 40 deletions
+31 -37
View File
@@ -12,7 +12,7 @@ value back.
claude-code ──POST /v1/messages──► proxy ──redacted──► api.anthropic.com claude-code ──POST /v1/messages──► proxy ──redacted──► api.anthropic.com
(ggshield scan, secret → <<<gg_token_…>>>) │ (ggshield scan, secret → <<<gg_token_…>>>) │
claude-code ◄──SSE (detokenized)─── proxy ◄──SSE stream──┘ claude-code ◄──SSE (detokenized)─── proxy ◄──SSE stream──┘
(<<<gg_token_…>>> → real secret, streaming) (real secret ← <<<gg_token_…>>>, streaming)
``` ```
## How it works ## How it works
@@ -20,8 +20,7 @@ claude-code ◄──SSE (detokenized)─── proxy ◄──SSE stream──
1. **Request interception** — the JSON body of `POST /v1/messages` is scanned by 1. **Request interception** — the JSON body of `POST /v1/messages` is scanned by
`ggshield`. Every detected secret is encrypted with **AES-256-GCM** under a `ggshield`. Every detected secret is encrypted with **AES-256-GCM** under a
persistent master key and replaced with a self-contained persistent master key and replaced with a self-contained
`<<<gg_token_[hex]>>>` placeholder, where the hex payload is `IV ++ authTag ++ `<<<gg_token_[hex]>>>` placeholder, where the hex payload is `IV ++ authTag ++ ciphertext`. No server-side mapping is kept — the token carries everything
ciphertext`. No server-side mapping is kept — the token carries everything
needed to restore it (`src/tokenize.ts`, `src/store.ts`). The redacted body is needed to restore it (`src/tokenize.ts`, `src/store.ts`). The redacted body is
forwarded upstream. forwarded upstream.
2. **Streaming detokenization** — the response is piped through a stateful 2. **Streaming detokenization** — the response is piped through a stateful
@@ -43,10 +42,10 @@ unrecoverable.
## Requirements ## Requirements
- **Node.js ≥ 23.6** (the proxy runs TypeScript directly via Node's built-in * **Node.js ≥ 23.6** (the proxy runs TypeScript directly via Node's built-in
type stripping — no build step, no `ts-node`/`tsx`). On Node 22.623.5 run type stripping — no build step, no `ts-node`/`tsx`). On Node 22.623.5 run
with `node --experimental-strip-types src/index.ts`. with `node --experimental-strip-types src/index.ts`.
- **`ggshield`** on your `PATH` and authenticated (`ggshield auth login`). If * **`ggshield`** on your `PATH` and authenticated (`ggshield auth login`). If
`ggshield` is missing or errors, the proxy logs a warning and forwards traffic `ggshield` is missing or errors, the proxy logs a warning and forwards traffic
**unredacted** (fail-open) — it never blocks your requests. **unredacted** (fail-open) — it never blocks your requests.
@@ -76,9 +75,9 @@ That's the only change `claude-code` needs — it keeps using your normal
## Configuration ## Configuration
| Env var | Default | Purpose | | Env var | Default | Purpose |
| ----------------------- | ------------------ | -------------------------------- | | ------------------------- | ------------------- | ------------------------------- |
| `PORT` | `8080` | Port the proxy listens on | | `PORT` | `8080` | Port the proxy listens on |
| `ANTHROPIC_UPSTREAM_HOST` | `api.anthropic.com` | Upstream API host to forward to | | `ANTHROPIC_UPSTREAM_HOST` | `api.anthropic.com` | Upstream API host to forward to |
## Tell Claude to leave the tokens alone ## Tell Claude to leave the tokens alone
@@ -90,7 +89,7 @@ project you run `claude-code` in:
```markdown ```markdown
# Security Constraints # Security Constraints
Do not modify, remove, or evaluate strings formatted as `<<<gg_token_[a-z0-9]+>>>`. Do not modify, remove, or evaluate strings formatted as `<<<gg_token_[a-f0-9]+>>>`.
Treat them as opaque identifiers and preserve them exactly as they appear when Treat them as opaque identifiers and preserve them exactly as they appear when
writing or reading files. writing or reading files.
``` ```
@@ -128,50 +127,45 @@ sudo loginctl enable-linger "$USER"
## Permanently point claude-code at the proxy ## Permanently point claude-code at the proxy
Setting `ANTHROPIC_BASE_URL` per shell (as in [Setup](#setup)) only lasts for Setting `ANTHROPIC_BASE_URL` per shell (as in [Setup](%23setup)) only lasts for
that session. To make it stick: that session. To make it stick:
- **fish** — set a universal variable once; it persists across sessions: * **fish** — set a universal variable once; it persists across sessions:
```fish ```fish
set -Ux ANTHROPIC_BASE_URL http://localhost:8080 set -Ux ANTHROPIC_BASE_URL http://localhost:8080
``` ```
- **bash/zsh** — add the export to your shell rc (or `~/.profile` for all * **bash/zsh** — add the export to your shell rc (or `~/.profile` for all shells):
shells):
```bash ```bash
echo 'export ANTHROPIC_BASE_URL=http://localhost:8080' >> ~/.bashrc echo 'export ANTHROPIC_BASE_URL=http://localhost:8080' >> ~/.bashrc
``` ```
- **All processes in a graphical session** (works regardless of shell) — drop * **All processes in a graphical session** (works regardless of shell) — drop
it in systemd's user environment: it in systemd's user environment:
```bash ```bash
mkdir -p ~/.config/environment.d mkdir -p ~/.config/environment.d
echo 'ANTHROPIC_BASE_URL=http://localhost:8080' >> ~/.config/environment.d/claude.conf echo 'ANTHROPIC_BASE_URL=http://localhost:8080' >> ~/.config/environment.d/claude.conf
``` ```
Takes effect on next login. Takes effect on next login.
## Scripts ## Scripts
| Command | What it does | | Command | What it does |
| ----------------- | ----------------------------------------------------- | | ------------------- | --------------------------------------------- |
| `npm start` | Run the proxy | | `npm start` | Run the proxy |
| `npm run dev` | Run with `--watch` (restarts on file changes) | | `npm run dev` | Run with `--watch` (restarts on file changes) |
| `npm test` | Run the detokenizer state-machine self-check | | `npm test` | Run the detokenizer state-machine self-check |
| `npm run typecheck` | Type-check the source with `tsc --noEmit` | | `npm run typecheck` | Type-check the source with `tsc --noEmit` |
## Limitations ## Limitations
- Detection is only as good as `ggshield`. It catches known secret patterns and * Detection is only as good as `ggshield`. It catches known secret patterns and
generic high-entropy strings, not arbitrary sensitive prose. generic high-entropy strings, not arbitrary sensitive prose.
- Re-inserted secrets are assumed to be escape-neutral (typical API * Tokens are decryptable by anyone holding the master key file. Multiple proxy
keys/tokens). A secret literally containing a backslash or double-quote could
mis-escape inside the response JSON. See the `ponytail:` note in
`src/detokenize.ts`.
- Tokens are decryptable by anyone holding the master key file. Multiple proxy
instances must share the same `master.key` to resolve each other's tokens. instances must share the same `master.key` to resolve each other's tokens.
## License ## License
+1 -1
View File
@@ -1,3 +1,3 @@
# Security Constraints # Security Constraints
Do not modify, remove, or evaluate strings formatted as `<<<gg_token_[a-z0-9]+>>>`. Treat them as opaque identifiers and preserve them exactly as they appear when writing or reading files. Do not modify, remove, or evaluate strings formatted as `<<<gg_token_[a-f0-9]+>>>`. Treat them as opaque identifiers and preserve them exactly as they appear when writing or reading files.