Local-first · Open source · Agent-safe
lockit
Secrets your agents can use. Never see.
Store each key once. lockit injects it into the process that needs it—without putting the value in a .env, shell history, or agent transcript.
curl -fsSL https://raw.githubusercontent.com/Ishaannarang22/lockit/v0.11.1/install.sh | sh
Installs the CLI, shell completion, and Claude + Codex skills. No account required.
agent> starting the app with admitted secrets $ lockit run -- npm start → STRIPE_KEY hasValue → DATABASE_URL hasValue server ready ✓
60-second start
Your first protected run.
Install the CLI and agent skills, store one value through stdin, admit its reference to a project, then run. No account or service setup.
-
01 / Install
Get the CLI.
curl -fsSL https://raw.githubusercontent.com/Ishaannarang22/lockit/v0.11.1/install.sh | sh -
02 / Store
Enter a value once.
Paste the value via stdin; it never enters argv.lockit set stripe/prod STRIPE_KEY -
03 / Admit
Choose this project’s access.
lockit init
lockit admit stripe/prod#STRIPE_KEY -
04 / Run
Start the process.
lockit run -- npm start
The project-world sandbox
The agent can ask.
Only you can admit.
Every project starts with an empty, value-free vault. An agent may request a secret by name, but crossing into that project requires human confirmation and local authentication.
An interactive demonstration of a secret moving from the protected store, through a human authentication gate, into the project world and child process. The agent sees metadata only.
Names and structure, never values.
Human presence is required at the boundary.
Exact match or a hard error. lockit never guesses.
Sets + Slots
Rotate once.
Every project follows.
lockit stores secrets by portable slug—not by environment-variable name. Projects commit value-free Slots that reference the right Set locally.
supabase/acme
schema supabase
- urlhasValue
- anonKeyhasValue
- servicehasValue
dashboard
url→SUPABASE_URL
url→NEXT_PUBLIC_SUPABASE_URL
admin
url→VITE_SUPABASE_URL
References, not copies.
Rotate the source once. Every admitted consumer follows.
Collisions stop the run.
Duplicate injected environment names are a hard error—never last-write-wins.
From vault to process
Four commands.
One controlled path.
# value enters through stdin, not command history $ lockit set stripe/prod STRIPE_KEY paste value via stdin · press Ctrl-D ✓ stored · stripe/prod → STRIPE_KEY
The value is encrypted into your local store. It is never included in argv.

Optional self-hosted sync
The relay carries it.
The relay cannot read it.
lockit seals a share to the recipient’s public key before it leaves your device. The optional server stores ciphertext and access metadata—never plaintext or an operator master key.
- Encrypted on your device
- Signed sender envelopes
- Decrypted on the recipient’s device
Designed around constraints
Security is the architecture,
not a badge.
Pure cryptographic core
packages/crypto performs no filesystem, network, or environment I/O.
Strict project boundary
A project can use only secrets admitted to its project world.
Exact resolution
Zero means missing; one resolves; many return a value-free hard error.
Ciphertext-only server
Encryption and decryption remain client-side. No operator master key exists.
Honest limits
Containment is not omnipotence.
- 01
A child process holds the real value while it runs. A malicious command can still exfiltrate it.
- 02
Node’s garbage collector means lockit minimizes plaintext lifetime, but cannot promise a guaranteed memory wipe.
- 03
Lose your passphrase and every enrolled device, and your encrypted data cannot be recovered.
Start local
Set it once.
Run anywhere it belongs.
Open source. Local-first. No account or server required for local use.
curl -fsSL https://raw.githubusercontent.com/Ishaannarang22/lockit/v0.11.1/install.sh | sh