Every project I open has one. A .env file sitting in a folder, holding a database password, a Stripe key, maybe an AWS secret — in plain text, on disk, one git add . away from a bad day. I've done this for years. Most of us have. It's not that we don't know better; it's that the alternative always felt like overkill.
The gap nobody's Mac tool fills
If you go looking for "how do I stop doing this," the answers you find are built for teams: Doppler, Infisical, dotenv-vault. Real tools, but they all assume the same shape of problem — multiple people, a shared source of truth, a network round-trip every time you need a value, and a monthly bill. That's the right answer if you're coordinating secrets across a team. It's a lot of infrastructure for a single developer juggling four side projects and a day job, which is most of us most of the time.
Meanwhile, macOS has had a legitimately good answer to "where should a secret live" for over a decade: the Keychain. Hardware-backed by the Secure Enclave, encrypted at rest, gated behind Touch ID. It's already there, already secure, and almost nobody uses it for .env-shaped secrets, because the UI for it is a developer tool from 2005 (Keychain Access.app) that has no concept of "project," "environment," or "this key needs rotating."
So I built the missing UI layer instead of reinventing the storage layer.
What I actually built: KeyStack
KeyStack is a native macOS app that stores every environment variable in the system Keychain — never in a plain text file — and gives it the organization a .env file structurally can't have:
-
Projects and environments. Tag each variable Development, Staging, Production, or Custom, and link a shared value (say,
DATABASE_URL) across multiple projects instead of copy-pasting it into three different.envfiles that will inevitably drift. -
Import from existing
.envfiles. Point it at a project folder and it scans for.env,.env.local,.env.staging, etc., flags duplicates, and lets you review before anything gets imported. - A diff view across environments. This is the one I didn't know I needed until I had it: side-by-side comparison that shows you a key exists in Development but is missing from Production, before that gap becomes a 2 a.m. incident.
- Rotation reminders. Set an interval (30/60/90/180/365 days) per secret. Overdue ones get a red badge and a macOS notification. I don't know a single solo developer who actually rotates keys on schedule without something forcing the issue — this is that something.
-
Export when you need it. One click to a
.env.local, a keys-only.env.examplefor source control, or aKEY=valueblock on the clipboard that clears itself after 30 seconds.
Auth is Touch ID or your login password, once per session — it locks the moment you switch apps. There's no account, no cloud sync, and zero network requests. Not "we minimize data collection" zero — actually zero. Your secrets never leave the machine, because there's nothing on the other end for them to go to.
Who this isn't for
Worth being honest about the edges, since "secrets manager" means different things to different people:
- If you need secrets shared and synced across a team, KeyStack is single-user by design. That's a real limitation, not a roadmap gap — the whole point is that it's local-first.
- It's macOS only. No Windows, no Linux, no iOS.
- It's not built to inject secrets into a CI/production pipeline. That's a different problem with a different tool.
If any of those are your actual problem, a cloud secrets manager is the right call and I'd say so even though I'm the one who built KeyStack. It's built for the much more common case: one developer, several projects, secrets currently scattered across plain text files that nobody's proud of.
Where to get it
It's a one-time $9.99 purchase on the Mac App Store — no subscription, no per-seat pricing, no upsells:
KeyStack on the App Store
If you've got a different local-first pattern you use for this instead — curious to hear it in the comments.
Top comments (0)