pii-hole
A Pi-hole for your AI prompts. Local proxy that strips PII and secrets from your LLM API requests before they leave your machine, and puts them back in the responses. Anthropic Messages API first.

The recording is real: the middle line is printed by the upstream from the
request body it actually received. Reproduce it with docs/demo/run.sh.
Quick start
make install models
piihole serve
ANTHROPIC_BASE_URL=http://127.0.0.1:8055 claude
Dashboard: http://127.0.0.1:8055/dashboard
Docker
Always bind the published port to loopback. The image listens on 0.0.0.0
inside the container, and the dashboard and audit API (/api/events) expose
the real detected values. Publishing the port on all interfaces would hand
them to your whole network:
docker run -d --name piihole --restart unless-stopped \
-p 127.0.0.1:8055:8055 -v piihole-data:/data ghcr.io/jeremiesamson/pii-hole
The bundled docker-compose.yml already uses 127.0.0.1:8055:8055.
Allowlist
pii-hole ships a built-in allowlist of technical terms that NER models commonly mistake for person names (Docker, Token, Skill, ...). You can extend it with your own file, Pi-hole style:
# ~/.config/piihole/allowlist.txt — one term per line
Hugo
Claude
- Matching is exact and case-insensitive on the detected value. A model that widens a span beyond the term ("de Marie Dubois est prêt") will not match, so the allowlist helps most on terms detected on their own.
- Applies to every entity type except SECRET: API keys and passwords are never allowlistable, even if listed.
- The built-in list deliberately excludes terms that collide with real first names (Hugo, Claude). Add them yourself if you accept the trade-off.
- Override the file location with
PIIHOLE_ALLOWLIST. In Docker, mount the file and point the variable at it. - The list is loaded at startup: restart the proxy after editing.
PERSON spans containing characters impossible in a real name
(| ` < > = { } [ ] ( ) # * _ @ / \ +, digits, newlines) are also
dropped, which removes most markdown/code false positives.
Security caveats
- The audit database contains real PII and secrets. Every masked value is
stored in clear in the SQLite file (
/data/piihole.dbin Docker,./piihole.dbotherwise) so you can review what was sent. The file is createdchmod 600; keep the/datavolume private, exclude it from backups you share, and wipe it when you no longer need the trail. - pii-hole reduces exposure, it does not guarantee zero leakage. Detection relies on NER models and regex patterns; false negatives happen, especially on unusual names, formats, or languages other than French and English. Treat it as a safety net, not as a compliance boundary.
Claude Code plugin
The repo ships a Claude Code plugin that wraps the proxy:
/piihole:start— launch the proxy and print theANTHROPIC_BASE_URLto export./piihole:status— show whether the proxy is up and how much it has masked./piihole:log— show the recent values that were redacted from your prompts (PII shown in full, secrets truncated so they are not re-exposed).- A DLP guard-rail hook: if you paste a plaintext secret (API key, token, JWT, password) into a prompt while the proxy is not running, the prompt is blocked with an explanation. When the proxy is up, the hook stays silent — the proxy is already anonymizing.
- A session-start line telling you whether pii-hole is protecting the session.
If
ANTHROPIC_BASE_URLpoints at the proxy and it is not running, the hook starts it for you (existing Docker container,piihole serve, or a freshdocker run) and waits up to 15 s for it to come up. SetPIIHOLE_AUTOSTART=0to disable the auto-start. - While the proxy is configured but unreachable (still loading models, Docker daemon down), your prompts are blocked with an explanation instead of failing with a connection error, so nothing leaves unprotected.
Install:
claude plugin marketplace add JeremieSamson/pii-hole
claude plugin install piihole
The guard-rail is a safety net for accidental paste, not a replacement for the proxy: it matches high-confidence secret patterns only (not names/emails), and it sees only your prompt text, not files Claude later reads — the proxy is what covers those.