dotmask
mask secrets before they leave your machine.
dotmask runs a local HTTPS proxy for Claude Code, Codex CLI, and similar tools. it replaces real secrets with format-preserving fakes on the way out, then restores them locally on the way back — so the AI sees fake keys while your tools keep working with the real ones.
try it
one session, nothing installed — no daemon, no system cert trust, no settings changes:
npx @ducnmm/dotmask exec -- claude
the proxy starts on a free port, wraps that one command, and disappears when it exits.
works with Codex CLI too (>= 0.129.0, via CODEX_CA_CERTIFICATE):
npx @ducnmm/dotmask exec -- codex
if your Codex uses a custom model provider (model_providers in
~/.codex/config.toml), allow its host first so dotmask masks that traffic:
dotmask allow your-gateway.example.com
Codex streams the model over a WebSocket by default, which is an opaque
binary channel dotmask can't mask. So for masked hosts dotmask declines the
WebSocket upgrade, and Codex transparently falls back to an HTTP transport
whose request body dotmask masks (it also decompresses zstd/gzip/brotli
bodies to reach the secrets). If you'd rather tunnel WebSocket traffic
through unmasked, set DOTMASK_WS_TUNNEL=1.
install
npm install -g @ducnmm/dotmask
dotmask install
restart Claude Code after install.
use
use Claude Code like normal. dotmask runs automatically after install.
dotmask install also wires up Codex CLI: it adds a small wrapper function
to your shell rc (~/.zshrc / ~/.bashrc) that routes codex through the
proxy, scoped to that command (no global env changes). Restart your shell — or
source ~/.zshrc — after install, then run codex as usual. dotmask uninstall removes it.
supported providers
api.anthropic.com- Anthropic (Claude)api.openai.com- OpenAI (GPT)chatgpt.com- Codex CLI (ChatGPT backend)openrouter.ai,api.openrouter.ai- OpenRoutergenerativelanguage.googleapis.com- Google AI (Gemini)api.deepseek.com- DeepSeekapi.groq.com- Groqapi.moonshot.ai- Moonshot (Kimi)api.together.ai- Together AIapi.fireworks.ai- Fireworks AIapi.cerebras.ai- Cerebrasapi.x.ai- xAI (Grok)api.inference.huggingface.co- Hugging Faceapi.minimax.io,api.minimax.chat- MiniMax
~/.dotmask/config.json controls the allowed host list.
add a custom host with:
dotmask allow chat.trollllm.xyz
commands
dotmask exec -- <command>- run one command behind dotmask (no install)dotmask install- install proxydotmask install --port 18788- custom portdotmask allow <host>- add allowed hostdotmask disallow <host>- remove hostdotmask hosts- list allowed hostsdotmask status- show statusdotmask doctor- diagnose issuesdotmask uninstall- remove everything
how it works
- your prompt with API keys goes to Claude Code
- dotmask intercepts and replaces real keys with fakes
- fake keys go to the AI API - API thinks its valid
- response comes back with fake keys
- dotmask swaps fakes back to real keys
- Claude Code sees the real response
your secrets never leave your machine.
supported secrets
- Anthropic keys:
sk-ant-api03-... - OpenAI keys:
sk-proj-...,sk-... - Stripe:
sk_live_...,sk_test_... - AWS:
AKIA... - Google AI:
AIza... - GitHub PATs:
ghp_...,gho_...,github_pat_... - Slack:
xoxb-...,xoxp-...,xoxs-...,xapp-1-... - JWT tokens
- Database URLs:
postgres://user:pass@... - EVM private keys:
0x...(64 chars) - GitLab:
glpat-...,glrt-... - npm:
npm_..., PyPI:pypi-... - Hugging Face:
hf_... - SendGrid:
SG...., Twilio:SK... - DigitalOcean:
dop_v1_..., Shopify:shpat_... - Telegram bot tokens, Postman:
PMAK-... - Notion:
secret_...,ntn_..., Linear:lin_api_... - Databricks:
dapi..., Grafana:glc_...,glsa_... - HashiCorp Vault:
hvs...., Fly.io:fo1_... - age keys:
AGE-SECRET-KEY-1...
token patterns are curated from the gitleaks default ruleset (MIT) — only strongly-prefixed, low-false-positive rules, since dotmask rewrites matches in place.
debugging
# view logs
tail -f ~/.dotmask/proxy.err.log
# run manually with debug
DOTMASK_DEBUG=1 node dist/proxy/server.js --port 18787
notes
- macOS only
- Node.js 18+
opensslrequired- secrets stored in macOS Keychain
license
MIT