Skip to main content
dotenvx implements a long-standing approach: encrypt the values in your .env to a public key, commit the encrypted file to git, hand the corresponding private key to anyone who needs to decrypt at runtime. There is no service in the path, no account to create, and no vendor whose breach you have to worry about. For a single developer or a stable two-person team, this is hard to beat, and Capy is not pretending otherwise. The interesting question is what happens after the team grows.

At a glance

When the team grows

A second engineer joins. You generate them a key, share it over Signal or 1Password, and confirm they can decrypt. A third engineer joins; same dance. By the fifth or sixth engineer, the answer to “who has which key” lives in a shared password manager, which has now become the actual security boundary. The file encryption is still happening, but the property the team is relying on is a vault someone else controls. The first time an engineer leaves the team, the question is whether their key still works. It does. They had it. The careful response is to rotate every secret they had access to and redistribute new keys to everyone else. In practice, most teams skip the rotation, because it is tedious and nobody wants to spend the afternoon on it. This is the pattern engineering leads describe in interviews almost universally: nobody rotates their secrets. The tool didn’t make them irresponsible; the operational steps did.

What changes under Capy

Capy preserves the property dotenvx is built around (values are ciphertext before they leave the engineer’s machine) and replaces the manual key-distribution and revocation steps with cryptographic primitives the service mediates. Adding a teammate is capy invite alice@example.com, which prints a capy redeem <code> command you send them. The code carries the org master key double-wrapped: your CLI wraps it with a key derived from the invite token and the invitee’s email, then the service adds an outer wrap over that. Neither half opens it alone — the invitee authenticates so the service strips its layer, then unwraps the inner layer locally. The org key never moves in the clear, and nothing has to be parked in a shared vault. The code still carries the one-time invite token, so treat it like a password and send it over a channel you trust. Removing a teammate is capy kick alice@example.com. The service stops co-decrypting for them, so the outer wrap on their local key.enc never comes off and the file is inert, while the rest of the team’s keys keep working unchanged. There is no rotation event and no afternoon spent re-encrypting and shipping new private keys to the survivors. The keep.lock manifest is the other piece dotenvx doesn’t have. It lives in your git repo as a list of hash references (committable, value-free), so a code reviewer sees in a PR diff that someone added or changed STRIPE_SECRET_KEY, without seeing what the value is. dotenvx commits the encrypted file itself, which is workable but mixes the value-list and the value-storage in a way that makes review patterns more awkward.

Where dotenvx remains the right answer

If your situation is “one developer, one machine, one key, no team operations to perform,” dotenvx is built for it and there is no reason to introduce a service to the path. The crossover is the moment the team is more than two people, or whenever turnover becomes plausible. Past that point, what dotenvx asks you to do manually (distribute keys, track who has which one, rotate everything when someone leaves) is what Capy is asking you to stop having to do at all.
Last modified on August 11, 2026