Veilpipe: secrets become $NAME before the model sees them
A mod for Claude Code (and a plugin for opencode). API keys, passwords and tokens in your prompts and tool
output are replaced with names like $STRIPE_KEY on your machine, so the model never sees the value.
65 seconds, captions on screen. Every command in it really runs; every key in it is fake.
The problem
You paste a key
To debug a payment or a login, the key goes into the prompt, and the prompt goes to the model provider.
A tool prints one
The assistant runs cat .env or reads a config file. Its output is sent to the model too.
Hooks can only block
A settings hook can stop a prompt, which stops your work. It can't rewrite the prompt and let you carry on.
How it works
1Catch
Veilpipe hooks every path to the model: what you type or paste, tool output, and text the engine injects.
2Replace
232 patterns (217 of them from the gitleaks ruleset) turn each secret into a stable name. The same value always gets the same name.
3Check
veilpipe doctor --canary sends a fake key through a real session and confirms the model only saw the name.
you type:deploy with sk_test_FAKEDEMO… to postgres://admin:FAKE-demo…@db.example.com/app model sees:deploy with $STRIPE_KEY to postgres://admin:$DB_PASSWORD@db.example.com/app
Limits, plainly. Veilpipe guards what the model sees. It does not clean up what is already on your disk:
- transcripts written before you installed it, or by sessions started without it, are untouched;
- the scrub after each turn covers that session's transcript, its subagents' transcripts and your prompt history; text the model writes itself is stored as written;
veilpipe auditlists secrets already on disk (names and counts, never values);- a prompt-injected command can use every value stored for that project, and a value sent over the network is out of veilpipe's sight; turn auto-save off where that matters.
Its own secret store
A caught value is saved under its name in a local, encrypted store for that project. When the model later
writes a command with $STRIPE_KEY, in the same session or a new one, the value is filled in as the command
runs. The model, the command text and the transcript only ever hold the name.
Encrypted, on your machine
One AES-256-GCM file; its key in the macOS Keychain (a private key file on Linux). Nothing is synced.
Per project
Each project folder has its own $STRIPE_KEY. A staging and a prod password stay apart as $DB_PASSWORD and $DB_PASSWORD_2.
Yours to manage
veilpipe secret ls shows names and lengths, never values. Turn auto-save off with one line.
Install
curl -fsSL https://veilpipe.deemwar.com/install.sh | sh
install.sh sha256 f1bd80d05a6d1a1f98f5db0f5a11b9d7527cc3244cb83d6fd30f7827b06f7773.
Read it first (about 50 lines), or check:
curl -fsSL https://veilpipe.deemwar.com/install.sh | sha256sum
Needs git and Node 22.18+ (nothing to npm install, no sudo). It clones release v0.2.1 to
~/.veilpipe, links the veilpipe CLI into ~/.local/bin, loads the mod into new Claude Code
sessions (and opencode, if you have it), and runs veilpipe doctor. Running sessions keep the code they started
with, so restart them. To undo: veilpipe uninstall.
Transcript of the video
When you work with an AI coding assistant, secrets slip in. You paste a key to debug a payment, or a tool prints a config file. All of it goes to the model. Veilpipe stops that at the door. Here is a prompt with a fake Stripe key and a fake database password. Veilpipe swaps each value for a name: $STRIPE_KEY, $DB_PASSWORD. The values are listed only by name and length, never shown. Now a real Claude session with Veilpipe loaded. We ask it to repeat our message, word for word. It repeats the names. The model never saw the values. You can check this yourself at any time. veilpipe doctor, with the canary option, sends a fake key through a real session and confirms the model only saw the name. One honest limit: Veilpipe guards what the model sees; it does not clean up what is already on your disk. It is open source, Apache 2.0, and installs with one line.