Skip to main content
Capy’s runtime story is one command: capy run -- <your command>. It wraps any process, decrypts your secrets in memory, and hands the plaintext values to the child as ordinary environment variables. Your app reads process.env (or os.environ, or ENV[...], or whatever your language uses) - no library to import, no SDK per language.

The pattern

Capy:
  1. Picks a mode from process.env — both SECRETS_BLOB and PROJECT_KEY set means deployed mode, neither set means local mode. Exactly one of the two set is an error; capy run exits 1 rather than guessing which you meant.
  2. Local mode: reads .env from the current directory and resolves your project key — through the Capy service on a cloud or BYOC profile, offline from your local key on a local-only profile. Deployed mode: parses SECRETS_BLOB, fetches the matching service key from the Capy service, and combines it with PROJECT_KEY to derive the decrypt key.
  3. Decrypts every capy:… snippet in .env (local mode), or the whole encrypted env map (deployed mode).
  4. Spawns the child with the decrypted values set in its environment.
  5. Forwards SIGINT, SIGTERM, and SIGHUP to the child; exits with the child’s exit code.
Deployed mode, and local mode on a cloud or BYOC profile, contact the Capy service once at startup to authorize the decryption, then never again for the life of the process. A local-only profile is the exception: it resolves the key entirely offline, prompting for your passphrase if the session is locked. See capy run for what each mode needs. In local mode, the plaintext lives only in the child process’s memory. In deployed mode, Capy writes decrypted secrets to .capy/next-env.js as well.

Examples

In package.json scripts

Put capy run in your scripts once and forget about it:
Then bun run dev / npm run dev / pnpm dev all work as usual; the wrapping is invisible.

Precedence: shell env vs. decrypted values

The rule differs between the two modes:
  • Local mode. Plaintext keys in .env follow dotenv’s usual precedence — a variable already set in your shell wins over the file. Encrypted capy:… values are the exception: they’re re-applied after that merge, so a decrypted project secret always overrides a same-named variable inherited from your shell.
  • Deployed mode. Variables already set in the environment win over every value decrypted from SECRETS_BLOB, so platform-level overrides stay sovereign.

What’s next

Deploying

How the runtime key source gets set in production.

capy run (CLI reference)

Mode detection, precedence, and behavior details.
Last modified on August 11, 2026