Open Cursor, Claude Code, or any MCP-enabled agent in your project and ask it to "fix the failing test." To do that, it reads files. Lots of them. And nothing stops it from reading this one:
.env
It doesn't matter that .env is in your .gitignore. .gitignore keeps it out of git — it does nothing about a read_file('.env') tool call dropping STRIPE_SECRET_KEY=sk_live_... straight into a model's context window. The same file that boots your dev server is sitting in plaintext, on disk, readable by every agent you've invited into your editor.
I stared at that for a while and realized the fix isn't "scope the agent down." The fix is: don't have a plaintext secrets file at all.
The idea: inject secrets at runtime, never write them to disk
Instead of a .env, you wrap your command:
klavex init # pick your project + environment once
klavex run -- npm start # that's it — no flags after this
The CLI pulls that environment's variables from an encrypted vault and injects them into the child process only. Your shell never sees them. Nothing is written to disk. So when the agent goes looking:
$ cat .env
cat: .env: No such file or directory
There's nothing to read, because the keys only ever existed inside the npm start process. That's the whole pitch in one screenshot.
It also quietly fixes the boring team problems: no more "ping six people on Slack for the right keys," no more stale .env after someone rotates a credential — rotate it once, every machine picks it up on the next klavex run.
Getting started
pip install klavex # Python 3.10+, macOS/Linux/WSL
klavex login # opens the browser once, token goes in your OS keychain
klavex init
klavex run -- npm start
That's the entire surface area. I deliberately kept it small — most secrets tools turn into a platform you have to administer. This is three commands.
Letting an agent have some secrets — on purpose
"No .env" handles accidental leakage. But sometimes you genuinely want an agent or a CI runner to use real secrets. For that you mint it its own token, scoped to exactly the environments you pick:
# In the dashboard: New agent → name it → tick the environments it may read → copy the token (shown once).
# On the agent / CI machine — no browser, no interactive login:
export KLAVEX_TOKEN=kx_agent_xxxxxxxx
klavex run -e env_dev_abc123 -- npm test
That token is read-only (it can read its scoped secrets, but can't create, change, or delete anything) and the backend refuses to decrypt any environment it wasn't granted. Grant it dev, and a request for prod comes back 403. Every fetch lands in an audit log, and revoking the token kills it everywhere.
What this does not do (because someone will ask)
Let me be honest about the boundary, since this is a security tool and overclaiming is how you lose a dev audience:
Klavex is not a sandbox. Anything that can execute arbitrary commands as you can still reach the secrets at runtime — it can read /proc/<pid>/environ, or just wrap klavex run itself. What this removes is the persistent, plaintext-on-disk footprint: the .env that lives in your repo for the project's whole life and gets caught by a casual file read, an accidental git add -f, a broad "scan the repo" agent pass, a backup, or a screen-share. It shrinks the exposure window from "always, on disk" to "only inside the one process you launched." That's a real, meaningful reduction — not airtight magic.
Other honest notes: the CLI isn't open source yet, and the encryption is standard envelope encryption (a per-secret data key wrapped by a KMS master key, with an encryption context bound to {team, project} so a stolen token can't cross-decrypt another tenant's data) — nothing I'm claiming is novel crypto.
Try it / tell me I'm wrong
It's early (v0.1.x). Solo is free forever.
pip install klavex
Docs: https://klavex.dev/docs.html
App: https://app.klavex.dev
I'd genuinely like feedback on two things:
- Is
klavex runin front of every command worth it, or is that friction too high? - Is "your agent can read your .env" a real problem you've felt — or am I solving something nobody cares about?
- Should i also provide a typescript CLI?
Rip it apart in the comments.
Top comments (0)