# Environments & groups

Most apps share the bulk of their configuration. seekrit models this with
**groups**: reusable secret bags that application environments compose. An
application environment is then just *its own secrets + the groups it pulls in*,
resolved and layered at runtime.

## The model

- A **group** is an org-scoped secret bag with its own environments, keyed by
  slug (`dev`, `staging`, `production`, `sandbox`, …).
- An **application environment** composes one or more groups. At resolve time
  each group is matched to the environment whose slug matches the app
  environment's.
- Values **layer**, lowest precedence first:

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

So a shared `DATABASE_URL` in a group is overridden by the app's own value,
which is overridden by a local `.env`, which is overridden by an exported shell
variable.

Once the layers are merged, `${OTHER_SECRET}` references inside values are
expanded — so a value can be assembled from the group's pieces and the app's
overrides at once. See [secret references](/docs/guides/references).

For a pull request or preview deploy that needs *almost* an environment, fork it
into a [branch config](/docs/guides/branches) instead of creating a real
environment: it inherits everything, overrides only what differs, and deletes
itself.

## Setting it up

Say an `api` and a `worker` share ~80% of their config. Put the shared values in
a group and compose it into each app's environments.

```bash
# 1. A shared group with a per-environment value set
seekrit group create --name "Common backend" --slug common
seekrit group env create --group common --name Production --slug production
seekrit secrets set DATABASE_URL 'postgres://…' --group common --env production

# 2. Compose it into each app environment
seekrit env groups add --app api    --env production --group common
seekrit env groups add --app worker --env production --group common

# 3. App-specific secrets live on the app environment
seekrit secrets set QUEUE_NAME jobs --app worker --env production
```

Now `worker/production` resolves to `common@production` overlaid with
`worker/production`'s own keys. Composing more than one group? Precedence follows
`--position` (higher wins); pass it on `env groups add`.

The dashboard shows the same thing from the environment's side — its own secrets,
the group secrets layered beneath them, and who holds the key:

![An environment page: a secrets table with redacted values, two rows inherited from a group, and Key access and Composed groups panels alongside](https://seekrit.dev/screenshots/original/dashboard-environment.webp)

*An environment page. Rows under “inherited from groups” come from a composed group; the panels on the right control who holds the environment's key and which groups layer beneath it.*

## Local `.env` and process env

`seekrit run` auto-loads `.env` from the working directory and overlays it above
the managed layers, and the live shell overrides everything. This makes seekrit
the single way your app gets its environment while still letting you tweak
individual values locally.

```bash
echo 'VITE_CLIENT_BASE_URL=http://localhost:5173' > .env
SEEKRIT_TOKEN=skt_… seekrit run -- pnpm dev     # .env wins over managed secrets
```

Point at other files with `--env-file` (repeatable; later files win), and see
exactly where each value came from with `--explain`:

```bash
seekrit run --env-file .env --env-file .env.local --explain -- pnpm dev
```

## Swapping one group per boot

Group environments double as **variants**. To boot with a different slice of a
single group — say staging auth keys — while keeping everything else at `dev`,
override just that group:

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

Everything else resolves at the app environment's slug; only `auth-providers`
switches to its `staging` slice. Overrides are fail-closed: you can only pull a
slice you hold a key grant for. As a logged-in developer you hold them all; for a
service token, pre-authorize alternate slices at creation with
`token create … --allow auth-providers=staging`.

> **Note:** Committing a config file no longer pins an environment. `seekrit.json` names only org + app; the environment is selected by the service token (or `--env`).
