tattle reads your past Claude Code and Codex sessions and reports every API key, .env value and personal detail that went to the model provider, or that a tool sent to someone else. Then it watches the next session live.
$ uv tool install tattle-audit
tattle to audit the past, tattle run -- claude to watch the next one“I found my Claude Code exposing personal data in http headers”
tattle retro flags personal data in the User-Agent, headers and query strings of past curl and fetch calls. It escalates the call when a page the agent just read asked who its user is. tattle run catches it as it happens.
Your agents have already read your .env files, run curl with your tokens and pasted your address into a prompt. Run bare tattle and it streams every transcript on disk, then sorts what it finds into two channels.
3.7 GB · 87 sFast, and flat on memory. On a real Mac, tattle read 1,521 transcript files (1,559 sessions) in 87 seconds with a peak of 128 MB. It streams one line at a time and never loads a whole file.
--since 30dScan only recent sessions. Placeholder values such as AKIA…EXAMPLE are kept apart, so the Rotate these list stays short and real.
Honest limitRetro is reconstructed from transcripts. It cannot see what the agent runtime sent by itself, such as telemetry, update checks and feature flags. The live proxy below catches that.
tattle run -- claude puts a local proxy between the agent and the internet, so it also sees the runtime’s own telemetry. When the agent exits, tattle writes a self-contained HTML report: flags first, then each host with what it was sent, then the full request log you can filter. These are real sessions, unedited apart from --share masking.
sent by Claude Code to fetch one page. We ran claude -p "fetch example.com" through tattle on a Mac. The fetch itself was a single 0-byte GET. Everything around it went to five hosts in twelve seconds.
tattle flagged the user's email and home path inside the prompt sent to the model API. No key showed up in a URL, a header or a third-party request.
| Destination | Reqs | Sent |
|---|---|---|
| api.anthropic.commodel API · 2 flags | 19 | 1.2 MB |
| http-intake.logs.us5.datadoghq.comtelemetry | 1 | 146 KB |
| mcp-proxy.anthropic.commodel API | 4 | 979 B |
| registry.npmjs.orgpackages & code | 2 | 0 B |
| example.comweb · the actual task | 1 | 0 B |
Claude Code 2.1, 25 Oct 2026. Request bodies are scanned, never stored.
tattle scans the path, the query string, every header and the decoded body. A key in an Authorization header is marked expected, because that is how the agent signs in. A key anywhere else is a leak.
.env-style assignments *_KEY= *_TOKEN= *_PASSWORD=.env values read from the working directorysk-p…(56 chars)Masked before anything touches disk. The log keeps a key's first four characters and its length, and nothing else.
•••@•••.comtattle report --share drops even those and blanks account IDs in paths, so you can post a report without posting your details.
tattle runs mitmproxy with a small addon. Its CA is created in ~/.tattle and never installed system-wide. Only the process you start with tattle run trusts it, through environment variables:
Your browser and every other app are untouched. A client that pins its certificates shows up in the report as a refused connection instead of silently going missing.
tattle clean # deletes ~/.tattle: the CA key and every session
tattle run -- claude # run any command through it
tattle run --live -- codex # stream requests as they happen
tattle tail # live view from another terminal
tattle report --open # open the latest report
tattle report --share # stricter masking, safe to post
tattle proxy # standalone; prints env exports
tattle ls # list sessions
.env, can slip past the patterns.$ uv tool install tattle-audit