Kerstel
Local-first secrets for Node and Bun projects. Your .env holds references. The values never touch disk in the clear.
OPENAI_API_KEY=kerstel://global/OPENAI_API_KEY
curl -fsSL https://kerstel.dev/install.sh | bash
macOS and Linux. Installs kerstel and its shorthand, ks. No account, no cloud, no telemetry.
Plaintext .env files leak
Anything that can read files can read your secrets: AI coding agents, editor plugins, backup tools, and the commit you did not mean to make. Other tools fix this with a cloud account and a wrapper command you type on every run. Kerstel needs no account, and writes its wrapper into your scripts once, so npm run dev is still npm run dev.
The whole flow in 37 seconds
A plaintext key becomes a reference, kerstel init migrates the project, and the same wiring runs under npm, Bun, pnpm, and Yarn.
Store once. Reference everywhere.
Run ks set global/OPENAI_API_KEY once (ks is short for kerstel). From then on your project file holds kerstel://global/OPENAI_API_KEY and your code still reads the real value from process.env. ks init does the whole project at once, and wires your scripts for you.
Vault
Values are encrypted at rest with AES-256-GCM. The data key lives in your OS credential store, or in a 0600 file where there is none.
Daemon
A per-user resolver unlocks the vault once and answers lookups over a local socket. Nothing leaves your machine.
Hook
A small preload intercepts reads of process.env and swaps each reference for its value. The file on disk never changes.
Clear about what is protected
- No plaintext secret ever sits in a project file. Reading, grepping, or committing
.envyields only references. - Each value is encrypted with its own random nonce. The key that unlocks them is held by the macOS Keychain or Linux's Secret Service.
- Code that runs inside your project can still read resolved values. That is the boundary Kerstel draws today, and per-process approval is the next step.