Local-first secrets manager for developers and AI agents. Keep your API keys in one encrypted store, use them without pasting them everywhere, and let agents use secrets without ever seeing them.
- Copy-paste sprawl. The same API key gets duplicated across projects,
prototypes, and
.envfiles. Rotating it means hunting down every copy. - Secrets leak everywhere. Keys end up in AI-agent transcripts, shell
history, committed
.envfiles, and chat messages. Once a value is seen, it's hard to un-see.
lockit stores each secret once, injects it into the commands that need it (so it never hits your history or a committed file), and keeps agent-facing output value-free — names and structure only, never a value.
curl -fsSL https://raw.githubusercontent.com/Ishaannarang22/lockit/v0.11.1/install.sh | sh
# installs the verified CLI + completion + Claude/Codex skills
# global store
printf 'sk-live-abc123' | lockit set stripe/prod STRIPE_KEY # value via stdin only
lockit ls --vars # see what you have, value-free
# per-project keys (same name can differ per project)
lockit init # mark this dir a project
printf 'postgres://a' | lockit set DATABASE_URL # project-local key
lockit admit stripe/prod#STRIPE_KEY # admit a shared secret (prompts to confirm)
lockit run -- npm start # inject THIS project's admitted keys, masked
lockit install # tab-completion + global Claude/Codex skills
lockit help # full reference (agents: read this)
# ongoing team environment (ciphertext-only relay)
lockit team create hackathon
lockit team add hackathon @alex @sam
lockit team share hackathon stripe/prod # human-gated; agent never sees value
lockit team join # teammates download ciphertext
lockit team admit hackathon stripe/prod # each teammate authorizes project useNo setup. The first command creates an encrypted store at ~/.lockit with a
machine-local key — nothing to export. Full usage, configuration, and honest
security limits are in packages/cli/README.md (also
shown on the npm page).
- Secret — a typed bag of fields, identified by a slug (e.g.
stripe/prod) plus a schema. One Stripe key is a field; a Supabase backend is three fields under one slug. - Global store — where secrets live, keyed by slug, encrypted at rest in
~/.lockit. - Project — a directory with a
.lockit/. It tracks its own keys (so the same name can hold different values per project) and can only use keys admitted to it. The binding map (.lockit/vault.json) is value-free and committable. - Admission — binding an existing/shared secret into a project, gated by a human presence confirmation. On macOS this is a Touch ID / account-password dialog (LocalAuthentication); on other platforms, or when no GUI/biometric is available, it falls back to a terminal prompt. An agent can request admission but can't satisfy the gate itself.
Early (0.x), under active development.
Works today (0.11.1): encrypted local store; per-project keys + admission +
sandbox (init / set / admit / status / run); import / pull; shell
tab-completion (install / completion); help; a Claude Code plugin in
plugin/; zero-setup keyfile so no passphrase needs exporting.
Admission is gated by a real macOS Touch ID / account-password dialog (0.4.5).
Personal-device enrollment bootstraps a fresh device through the existing public
relay (or an offline file exchange), using two short comparison codes and a human
authorization gate. Enrolled devices continuously reconcile signed, end-to-end
encrypted changes; the relay stores ciphertext only. Local mutations sync
automatically when reachable, and lockit sync catches up after offline work.
Exact bindings already human-admitted on that machine in default-mode projects
are refreshed directly in .env; cloned or edited bindings are not authorization.
Ongoing team environments support create/add/remove/join/share/set/admit/sync/status.
Updates are signed and encrypted client-side; the relay retains ciphertext until
every current member has durably saved and acknowledged it. Team download is
pull-based (team join / team sync), not background push while Lockit is closed.
Downloaded keys still require human-gated team admit before a project can use
them; later syncs refresh only bindings already authorized on that machine.
The store key is protected by default (0.5.1, macOS): it is created in the
keychain behind Touch ID on first use and never written as a plaintext file —
~/.lockit/key holds only a value-free marker, so reading it yields nothing usable and
store access needs your fingerprint or password. One unlock lasts ~90s by default
(LOCKIT_UNLOCK_TTL; lockit lock clears it), so a short run of commands prompts once,
not every time. Set LOCKIT_PASSPHRASE to manage your own key instead. See
ADR-0010.
Honest limits (and the cloud plan): Personal devices currently share one
encrypted-vault identity, so per-device revocation is not available yet. A lost
enrolled device requires rotating affected secrets and re-enrolling trusted devices.
The relay can observe recipient ids, timing, and message sizes, but not secret values.
protect is a real, opt-in improvement, but
it is an authorization gate, not a hardware key release — true Secure Enclave /
non-extractable keys require an Apple Developer signing identity + notarization, which
an npm-distributed CLI invoking the system swift cannot have (ADR-0010
documents the tested errSecMissingEntitlement wall). The hardware-bound version, and
a website-login-gated unlock for a future authenticated team cloud service, are the next steps —
documented, not hidden.
This is a pnpm workspace monorepo (TypeScript / Node).
| Path | What it is |
|---|---|
packages/cli |
the lockit binary — what you install |
packages/core |
vault, encrypted store, admission layer |
packages/crypto |
pure, no-I/O cryptographic trust root |
Dependencies flow upward: crypto → core → cli.
Client-side encryption with modern primitives (XChaCha20-Poly1305, Argon2id; the
crypto package also ships X25519/Ed25519/HPKE for future sharing). Store and key
files are 0600. Honest limits — including "the child process holds the real value
while using it" and "no recovery if you lose a passphrase you set" — are documented
in packages/cli/README.md and
docs/threat-model.md, not hidden.
pnpm install
pnpm -r build # build all packages in dependency order
pnpm -r typecheck
pnpm lint
pnpm test # unit tests
pnpm test:e2e # black-box tests against the built binarySee AGENTS.md and docs/ for architecture, data model, threat model, and the design ADRs.