Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.capy.sc/llms.txt

Use this file to discover all available pages before exploring further.

Synopsis

capy run -- <command> [args...]
Everything after -- is passed through to the child process.

Description

capy run decrypts your project’s secrets in memory and spawns the given command with them set as environment variables. Your app reads env vars the normal way for its runtime - process.env, os.environ, ENV["KEY"], std::env::var, whatever. This is Capy’s single runtime mechanism - works for any language, any framework, local dev through production, no per-language SDK to install. Plaintext values live only in the child process’s memory and are never written to disk.

Two modes

capy run auto-detects which mode to run in based on what’s in process.env:

Local mode (default)

When SECRETS_BLOB and PROJECT_KEY are not set, capy run:
  1. Reads .env from the current working directory.
  2. Resolves your project key, in priority order:
    • CAPY_KEY env var (64-char hex), or
    • the per-project cache at ~/.capy/orgs/{orgId}/projects/{projectId}/key.cache that capy (sync) populates after a successful server round-trip.
  3. Decrypts each capy:… snippet in .env.
  4. Spawns the child with the decrypted values set in its environment.
This is the mode for local development. Run capy once to sync and populate the cache; capy run after that is offline.

Deployed mode

When both SECRETS_BLOB and PROJECT_KEY are set in process.env, capy run:
  1. Parses SECRETS_BLOB locally - extracts the deploy ID, the service-held outer blob, and the encrypted env map.
  2. Posts the outer blob to POST /deploy/{deployId}/decrypt on the Capy service. The service verifies the deploy token isn’t revoked and returns a derived service key.
  3. Combines PROJECT_KEY with the service key to derive the decrypt key, then AES-GCM-decrypts the env map.
  4. Spawns the child with those values set in its environment.
This is the mode for CI builds and production deploys. The two env vars come from capy deploy. No local .env file, no local keyring, no interactive auth.
If only one of SECRETS_BLOB / PROJECT_KEY is set, capy run exits with an error rather than silently falling back to local mode. Makes platform misconfiguration loud instead of silent.

Behavior (both modes)

  • Variables already set in the parent shell environment are preserved as-is - decrypted values don’t overwrite explicit env.
  • Forwards SIGINT, SIGTERM, and SIGHUP to the child.
  • Exits with the child’s exit code.

Examples

# Node
capy run -- node app.js
capy run -- next dev
capy run -- bun test

# Python
capy run -- python app.py
capy run -- python -m uvicorn main:app

# Go
capy run -- go run .
capy run -- ./my-binary

# Ruby
capy run -- bundle exec rails server

# Rust
capy run -- cargo run

# Shell script
capy run -- ./deploy.sh

In containers

capy run can serve as the Docker entrypoint:
ENTRYPOINT ["capy", "run", "--"]
CMD ["python", "app.py"]
Make sure SECRETS_BLOB and PROJECT_KEY (from capy deploy) are present in the container’s environment at runtime.

Next.js on Vercel

In deployed mode, capy run also writes .capy/next-env.js before spawning the child. That file maps each decrypted variable name to its process.env reference. In next.config.js:
const capyEnv = require("./.capy/next-env");
module.exports = { env: capyEnv };
Next.js inlines each value as a string literal at build time. No per-variable list to maintain in next.config.js. See Deploying → Vercel for the full walkthrough.

See also