# Examples

A cookbook of patterns you can copy and adapt. Each recipe links to the guide
that covers it in depth.

Almost everything here rests on two properties:

- **One encrypted secret set resolves the same way in every runtime** — local
  dev, CI, a container, a Kubernetes pod, an agent sandbox — because they all
  decrypt through the same key grant.
- **Environments compose.** An application environment is *its own secrets plus
  the groups it pulls in*, layered at runtime — so shared config lives in one
  place.

Agents get first-class treatment: because seekrit is zero-knowledge, an agent
can *use* a secret it is never allowed to *read*.

## Everyday: replace your `.env` file

### Run any command with secrets injected

Stop keeping a plaintext `.env` in the repo. A service token carries its own
org, app, and environment, so nothing else is needed:

```bash
export SEEKRIT_TOKEN=skt_…
seekrit run -- pnpm dev            # secrets injected into the child process
seekrit run -- ./migrate && ./serve
```

A local `.env` still works — it layers *on top* of the managed secrets, so you
can override one value without touching the shared set:

```
group secrets  <  app-env secrets  <  .env file  <  process env      (highest wins)
```

See the [CLI guide](/docs/guides/cli).

### See exactly where each value came from

When a value isn't what you expect, `--explain` prints each variable's source
layer to stderr (names only, never values):

```bash
seekrit run --explain -- true
```

## Composability: share config across apps

### One shared group, many apps

Put config that several apps share into a **group**, then compose it into each
app's environments. Here an `api` and a `web` app share a database and cache:

```bash
# A shared group with a per-environment value set
seekrit group create --name "Shared infra" --slug shared-infra
seekrit group env create --group shared-infra --name Production --slug production
seekrit secrets set DATABASE_URL 'postgres://…' --group shared-infra --env production
seekrit secrets set REDIS_URL    'rediss://…'   --group shared-infra --env production

# Compose it into each app's production environment
seekrit env groups add --app api --env production --group shared-infra
seekrit env groups add --app web --env production --group shared-infra

# App-specific secrets live on the app environment and override the group
seekrit secrets set STRIPE_KEY 'sk_live_…' --app api --env production
```

Change `DATABASE_URL` once in the group and both apps pick it up. See
[Environments & groups](/docs/guides/environments).

### Layer several groups with precedence

Compose more than one group and control precedence with `--position` (higher
wins). App-env secrets still win over every group:

```bash
seekrit env groups add --app api --env production --group shared-infra --position 10
seekrit env groups add --app api --env production --group third-party  --position 20
seekrit env groups list --app api --env production      # inspect the order
```

### Swap a single group's slice per boot

Group environments double as **variants**. Boot everything at `dev` but pull one
group — say auth providers — from its `staging` slice, without a separate
environment:

```bash
seekrit run --with auth-providers=staging -- pnpm dev
```

Overrides are fail-closed: you can only pull a slice you hold a key for. As a
logged-in developer you hold them all; for a service token, pre-authorize the
slice at creation with `token create … --allow auth-providers=staging`.

## One secret set, every runtime

### The same token in local dev, CI, and a container

Bind a token to one environment once, then hand it to every runtime — each
resolves and decrypts identically:

```bash
# Local / CI — Node CLI
SEEKRIT_TOKEN=skt_… seekrit run -- ./deploy.sh

# GitHub Actions — SEEKRIT_TOKEN from the repo's secret store
#   - run: seekrit run -- ./deploy.sh

# Container / distroless — the static launcher, no Node required
SEEKRIT_TOKEN=skt_… seekrit-run -- ./start-server
```

See [Service tokens](/docs/guides/service-tokens),
[CI/CD & containers](/docs/guides/ci-cd), and the
[`seekrit-run` launcher](/docs/guides/run).

### A container entrypoint that degrades gracefully

`seekrit-run` is a tiny static binary with no Node/OpenSSL/CA dependency, so it
runs in `distroless`, `alpine`, and `scratch`. Fetching secrets is best-effort:
if the token is missing or the API is unreachable, it warns and still runs your
command with just `.env` + the live environment — so the same image works with
or without seekrit wired up.

```dockerfile
FROM gcr.io/distroless/static
COPY --from=seekrit /usr/local/bin/seekrit-run /usr/local/bin/seekrit-run
ENTRYPOINT ["seekrit-run", "--"]
CMD ["./start-server"]
```

> **Warning:** Inject at runtime, never at build time — secrets fetched during `docker build` can be baked into an image layer. `seekrit-run` only ever puts values into the child process's environment; nothing touches disk.

## Built for agents

### Let an agent provision a service end-to-end

Register the MCP server once, giving the agent an admin token so it can create
structure headlessly:

```bash
SEEKRIT_TOKEN=skt_…  claude mcp add seekrit -- seekrit mcp
```

Now the agent drives seekrit as tools — a typical stand-up-a-service session:

1. `create_app` → `create_env` (production) — the data key is generated locally.
2. `set_secret` for `DATABASE_URL`, `API_KEY`, … (encrypted on this machine).
3. `create_token` bound to that env — a runtime token, auto-granted its keys.
4. `configure_project` to write `seekrit.json`, then hand the runtime token to CI
   or a container.
5. `run_command -- pnpm test` to verify the app boots with its secrets injected.

See the [AI agents guide](/docs/guides/ai-agents).

### Use secrets the agent can't read

The zero-knowledge model means an agent can put a secret to work without its
plaintext ever entering the conversation:

- **`run_command`** resolves the environment, injects it into a child process,
  and returns only the exit code and output — the values never reach the agent.
- **`export_env`** writes a gitignored file for tools that read `.env`.
- **`get_secret`** returns metadata; it only decrypts into the response when you
  pass `reveal: true`.

```
run_command -- pnpm test          # values injected, never returned
```

> **Warning:** Revealing a secret puts its plaintext in the agent's context, where it may be logged or retained. Use `run_command` (or `export_env`) whenever the agent needs to *use* a secret rather than *read* it.

### Ephemeral agent sandboxes

Give a throwaway sandbox exactly the secrets it needs through a short-lived,
independently revocable token — no long-lived credentials in the environment:

```bash
# Stand up a scoped env + token for the sandbox
seekrit env create --app storefront --name "Sandbox 7f3" --slug sandbox-7f3
seekrit secrets set OPENAI_API_KEY 'sk-…' --app storefront --env sandbox-7f3
seekrit token create --name sandbox-7f3 --app storefront --env sandbox-7f3   # prints skt_…

# … the sandbox runs `seekrit-run -- ./agent`, decrypting locally …

seekrit token revoke skt_XXXXXXXX      # on teardown
```

The token self-decrypts (no passphrase) and can only reach the environment it
was granted. See [CI/CD & containers](/docs/guides/ci-cd#ai-agent-sandboxes).

## Dynamic credentials: short-lived Postgres logins

Mint a database login that auto-expires, and hand the URL straight to a tool.
The password and its SCRAM verifier are generated on your machine — only the
verifier is sent, so the plaintext never reaches seekrit or Postgres at rest:

```bash
psql "$(seekrit pg lease prod-db --ttl 30m)"
```

This composes with everything above: an agent or CI job can lease a 30-minute
credential for one task instead of holding a standing database password. See
[Temporary access](/docs/concepts/temporary-access).
