Pseudonymize customer PII before prompts reach OpenAI/Anthropic; restored in the reply. Docker.
1.7K
Pseudonymize your customers' data before it reaches OpenAI or Anthropic — and restore it in the reply.
Set it up by hand, or let your AI coding agent (Claude Code, Codex, Cursor, Claude/ChatGPT desktop) do it through penname's built-in MCP server.
penname is an OpenAI/Anthropic-compatible proxy. On the way out it swaps real values — names, emails, phone numbers, ID numbers — for stable pen names like PERSON_7K3Q2M9XAB. On the way back it puts the real values in again. The model provider never sees the real thing. The gateway runs on your own machine and reads your database; nothing sensitive leaves your network. Nothing about your app changes except one base URL.
Website & dashboard: https://penname.io
This is the whole point, so it's exact:
PENNAME_CONTROL_PLANE_URL unset and the gateway talks to nothing but your own database and your own model provider — no calls to penname at all.1. Get a key (free, no payment) — sign up at https://penname.io/signup and copy your pk_….
2. Run the gateway in a new folder. Docker is the only thing you install:
docker run -it -v ${PWD}/penname:/setup pennameio/gateway init
cd penname && docker compose up -d
init asks for your key and (optionally) a read-only database URL, generates your master key, and writes .env, secrets.env and docker-compose.yml for you.
3. Point your model client at it — keep your provider API key exactly as-is:
# OpenAI-compatible
client = OpenAI(base_url="http://localhost:8088/v1", api_key=YOUR_OPENAI_KEY,
default_headers={"X-Penname-Scope": f"user={user_id}"})
# Anthropic
client = Anthropic(base_url="http://localhost:8088", api_key=YOUR_ANTHROPIC_KEY)
The X-Penname-Scope header tells the gateway whose records a request is about — without it, names reach the model in the clear (emails and phones are still protected, because they have a shape; names do not). Run curl localhost:8088/scope for the exact keys from your schema.
penname runs an MCP server, so your coding agent can do the whole thing — read your schema, mark what's sensitive, and troubleshoot. The signup page hands you a ready prompt with your key in it, or add the MCP directly:
claude mcp add --transport http penname https://penname.io/mcp \
--header "Authorization: Bearer pk_your_key"
| Port | Purpose |
|---|---|
8088 | the gateway's HTTP API (OpenAI at /v1, Anthropic at /). The generated compose publishes it to 127.0.0.1:8088 only — it holds your master key and reads your DB, so it must not be public. |
| Variable | Default | Purpose |
|---|---|---|
PENNAME_MASTER_KEY | — (required) | secret your pen names derive from; never leaves your machine |
PENNAME_API_KEY | — | your pk_…, signs the gateway in to the dashboard |
PENNAME_DB_URL | — | read-only database URL the gateway reads names from |
PENNAME_UPSTREAM_BASE_URL | https://api.openai.com/v1 | OpenAI-compatible upstream |
PENNAME_ANTHROPIC_BASE_URL | https://api.anthropic.com/v1 | Anthropic upstream |
PENNAME_CONTROL_PLANE_URL | — | hosted dashboard base URL; leave unset to run fully offline |
PENNAME_PORT | 8088 | host port the container is published on |
ENABLE_LOGGING | true | one log line per request (values masked) |
PENNAME_MASTER_KEY_FILE / PENNAME_API_KEY_FILE / PENNAME_DB_URL_FILE | — | read a secret from a file (Docker secrets, Kubernetes, cloud secret managers) |
init sets all of these for you — you normally never touch them by hand.
latest, 0.1.4 — current, multi-arch (linux/amd64 + linux/arm64)0.1.x) are immutable — pin one in production.Dashboard, usage, and managing what's sensitive: https://penname.io
Proprietary. © penname.
Content type
Image
Digest
sha256:bf5c8be90…
Size
70.1 MB
Last updated
about 1 month ago
docker pull pennameio/gateway