OKE reads environment variables at boot for connection detail and secrets — never for
behavior you could declare in `oke.config.ts`. Under `oke dev`, Compose writes these
into `.env.local`; this page is the full map.

<Callout title="The one rule">
  Put drivers, images, and locale lists in `oke.config.ts`. Use env vars for URLs, credentials, and
  runtime posture the host injects — not for inventing new behavior.
</Callout>

## Smallest Example

<Steps>

<Step>
### Let Compose write the map

```bash
oke dev
```

Compose fills `.env.local` with `DATABASE_URL`, Redis, S3, and vault keys for the
pinned images.

</Step>

<Step>
### Override one URL when needed

```bash
export DATABASE_URL=postgres://user:pass@db:5432/oke
```

Conventional names win over `OKE_*` aliases, then built-in defaults.

</Step>

</Steps>

## Precedence

<Callout title="Resolution order">
  For anything with both an `OKE_*` variable and a conventional one (like `DATABASE_URL`), the
  conventional variable wins first, then the `OKE_*` form, then the built-in default.
</Callout>

## SQL store

| Variable            | Used for                                                                                                                                                                                                                                                          | Default when unset                        |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------- |
| `DATABASE_URL`      | Postgres connection (`postgres` store / clock / journal / Console operator plane, drizzle-kit). App tables stay in `public`; Console operators/sessions use schema `oke_console` on the same database. When PgDog is pinned, this points at the pooler (`:6432`). | `postgres://localhost:5432/oke`           |
| `OKE_STORE_SQL_URL` | Direct SQL URL (Postgres host, even when PgDog fronts the app). Also used by Console when `DATABASE_URL` is unset.                                                                                                                                                | —                                         |
| `OKE_PGDOG_URL`     | PgDog pooler URL (same value as `DATABASE_URL` when both are present)                                                                                                                                                                                             | —                                         |
| `OKE_PGLITE_URL`    | PGlite data dir or `memory://` (`pglite` driver; required for `store.sql.test`)                                                                                                                                                                                   | `memory://` in `test`; else `.oke/pgdata` |
| `OKE_SQL_DRIVER`    | Force the sql driver id at boot                                                                                                                                                                                                                                   | config map                                |

`oke test` sets `OKE_PGLITE_URL=memory://` when unset. The `sqlite` driver and `OKE_SQLITE_URL` are removed.

## Index store

| Variable              | Used for                                            | Default when unset |
| --------------------- | --------------------------------------------------- | ------------------ |
| `OKE_INDEX_DRIVER`    | Force the index driver id                           | config map         |
| `OKE_STORE_INDEX_URL` | Meilisearch base URL (`meilisearch` driver)         | —                  |
| `OKE_STORE_INDEX_KEY` | Meilisearch API / master key (`meilisearch` driver) | `MEILI_MASTER_KEY` |

## KV store

| Variable           | Used for                       | Default when unset |
| ------------------ | ------------------------------ | ------------------ |
| `REDIS_URL`        | Cache Redis connection         | driver default     |
| `OKE_STORE_KV_URL` | Explicit cache KV URL override | —                  |
| `OKE_KV_DRIVER`    | Force the kv driver id         | config map         |

## Files store

| Variable               | Used for                         | Default when unset |
| ---------------------- | -------------------------------- | ------------------ |
| `S3_BUCKET`            | Bucket name (`s3` driver)        | —                  |
| `S3_ENDPOINT`          | S3-compatible endpoint (RustFS)  | —                  |
| `S3_ACCESS_KEY_ID`     | Access key                       | —                  |
| `S3_SECRET_ACCESS_KEY` | Secret key                       | —                  |
| `S3_REGION`            | Region                           | —                  |
| `S3_SESSION_TOKEN`     | Session token (temporary creds)  | —                  |
| `OKE_STORE_FILES_DB`   | Explicit files location override | —                  |
| `OKE_FILES_DRIVER`     | Force the files driver id        | config map         |

## Vault

Built-in store uses `OKE_VAULT_MASTER_KEY` (or `--key` / stdin on CLI). Managed providers use the
vars below — see [Vault](/docs/elements/vault) for which each id needs.

| Variable               | Used for                                                                                                     | Default when unset    |
| ---------------------- | ------------------------------------------------------------------------------------------------------------ | --------------------- |
| `OKE_VAULT_PROVIDER`   | Managed backend (`aws-secrets-manager` · `azure-key-vault` · `gcp-secret-manager` · `doppler` · `1password`) | — (platform-injected) |
| `OKE_VAULT_REGION`     | Cloud region (AWS Secrets Manager; GCP user-managed replication)                                             | —                     |
| `OKE_VAULT_MOUNT`      | Scope: AWS/Azure prefix, GCP `project[/prefix]`, Doppler `project/config`, 1Password vault name              | —                     |
| `OKE_VAULT_MASTER_KEY` | Built-in vault master key (base64)                                                                           | —                     |
| `OKE_VAULT_URL`        | Azure Key Vault URI, 1Password Connect host, optional Doppler origin                                         | —                     |
| `OKE_VAULT_TOKEN`      | Doppler service/personal token, 1Password Connect token                                                      | —                     |

## Channel (email) — boot binder

Read when `drivers.channel.email` resolves to that driver id.

| Variable                | Used for                                         |
| ----------------------- | ------------------------------------------------ |
| `SMTP_URL`              | `smtp` — full SMTP URL (`smtp://…`)              |
| `SMTP_USER`             | Overrides the user embedded in `SMTP_URL`        |
| `SMTP_PASSWORD`         | Overrides the password in `SMTP_URL`             |
| `OKE_CHANNEL_EMAIL_URL` | Alternative to `SMTP_URL`                        |
| `RESEND_API_KEY`        | `resend` API key                                 |
| `SNDR_API_KEY`          | `sndr` API key                                   |
| `SNDR_BASE_URL`         | Optional SNDR API origin (default `api.sndr.sh`) |
| `TAQNYAT_MAIL_TOKEN`    | `taqnyat-mail` bearer token (Email-enabled)      |
| `TAQNYAT_CAMPAIGN`      | `taqnyat-mail` campaign name                     |

## Channel (SMS) — boot binder

Read when `drivers.channel.sms` resolves to that driver id (`console` opens nothing).

| Variable               | Used for                         |
| ---------------------- | -------------------------------- |
| `TAQNYAT_BEARER_TOKEN` | `taqnyat` bearer token           |
| `TAQNYAT_TOKEN`        | Alias for `TAQNYAT_BEARER_TOKEN` |
| `TAQNYAT_SENDER`       | Taqnyat pre-approved sender id   |
| `MSEGAT_USERNAME`      | `msegat` account username        |
| `MSEGAT_API_KEY`       | `msegat` API key                 |
| `MSEGAT_SENDER`        | Msegat pre-approved sender id    |
| `UNIFONIC_APPSID`      | `unifonic` AppSid                |
| `UNIFONIC_APP_SID`     | Alias for `UNIFONIC_APPSID`      |
| `UNIFONIC_SENDER`      | Unifonic SenderID (optional)     |

WhatsApp (`wa-cloud`) and push (`webpush` / `fcm`) are not opened from env at
boot — pass them on `BootOptions.channel.drivers` with their open options.

## Live test gates (opt-in, contributors)

Provider-quota-burning live suites in the okengine repo are double-gated: the
medium flag **plus** that provider's real credentials — credentials alone never
send. App projects can ignore these.

| Variable         | Used for                                                  |
| ---------------- | --------------------------------------------------------- |
| `OKE_SMS_LIVE`   | `=1` allows live SMS provider tests (e.g. Taqnyat OTP)    |
| `OKE_EMAIL_LIVE` | `=1` allows live email provider tests (e.g. Taqnyat Mail) |

## AI providers

| Variable              | Used for                                                                                | Default when unset |
| --------------------- | --------------------------------------------------------------------------------------- | ------------------ |
| `ANTHROPIC_API_KEY`   | `anthropic` driver credential                                                           | —                  |
| `ANTHROPIC_MODEL`     | Model override for the anthropic driver                                                 | —                  |
| `OPENAI_API_KEY`      | `openai-compatible` driver credential                                                   | —                  |
| `OPENAI_BASE_URL`     | `openai-compatible` base URL                                                            | OpenAI cloud       |
| `OKE_AI_DRIVER`       | Force the AI driver id (honoured under Compose / `oke dev`)                             | config map         |
| `OKE_AI_URL`          | openai-compatible base URL (must end in `/v1`) — BYO; Compose does not manage inference | —                  |
| `OKE_AI_MODEL`        | Default model id for openai-compatible / setup bindings                                 | —                  |
| `OKE_AI_VISION_MODEL` | Vision model id written by `oke ai setup` (logical `ai.model("vision")`)                | —                  |
| `OKE_AI_EMBED_MODEL`  | Embedding model id written by `oke ai setup`                                            | —                  |

## Framework behavior

| Variable                 | Used for                                                                                                              |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| `OKE_DOCKER`             | `"1"` marks Compose / `oke dev` posture (set by the CLI)                                                              |
| `OKE_DB_AUTO_PUSH`       | Overrides `db.autoPush` at boot                                                                                       |
| `OKE_DRIZZLE_DIALECT`    | `"postgresql"` for drizzle-kit overlays (templates hardcode it)                                                       |
| `OKE_DEV_REQUEST_LOG`    | `"1"` logs requests during `oke dev` (set by the CLI) — surface, flow, status, timestamp, run id                      |
| `OKE_CONSOLE_SECRET`     | Console operator-session signing secret (HMAC) — set in production; else `.oke/console.secret`. Not a Vault contract. |
| `OKE_CONSOLE_AUTH_STORE` | `"1"` lists the operator-plane `oke_console` schema in Store browse (read-only). Hidden by default.                   |
| `OKE_RUNS_INGEST_URL`    | Host → Console WideEvent ingest URL (`oke dev` sets this on the app child). Enables a memory runs store + push.       |
| `OKE_RUNS_INGEST_SECRET` | Shared secret for `POST /console/runs/ingest` (`x-oke-runs-ingest` header). Minted by `oke dev`; never return events. |
| `PORT`                   | App port in production containers (default `6530`)                                                                    |
| `NODE_ENV`               | `"production"` switches the Console to its production posture                                                         |

Console operator rows are **not** stored in `.oke/console.sqlite`. With `DATABASE_URL` (or
`OKE_STORE_SQL_URL`) they live in Postgres schema `oke_console`. Without a Postgres URL,
Console uses PGlite under `.oke/console-pg` for local reopen durability.

## Troubleshooting

<Accordions>

<Accordion title="Compose did not write .env.local">
  Run `oke dev` (not a bare `bun` entry) so Compose posture sets `OKE_DOCKER=1` and writes
  connection URLs. Confirm `images` pins exist in [Configuration](/docs/reference/configuration).
</Accordion>

<Accordion title="Vault sealed / missing master key">
  Built-in vault needs `OKE_VAULT_MASTER_KEY` (or `oke vault unseal`). See
  [Vault](/docs/elements/vault).
</Accordion>

<Accordion title="Console operator store missing">
  Operator rows need `DATABASE_URL` or `OKE_STORE_SQL_URL` (schema `oke_console`). Without Postgres,
  Console uses PGlite under `.oke/console-pg`.
</Accordion>

</Accordions>

## Learn more

- [Configuration](/docs/reference/configuration) — the declarative side of the same knobs
- [Vault](/docs/elements/vault) — how `OKE_VAULT_*` gets minted on first boot
- [CLI](/docs/reference/cli) — which commands write these for you
- [Security](/docs/reference/security) — `OKE_CONSOLE_SECRET`

## Next

<Cards>
  <Card
    title="Configuration"
    description="Drivers and images in oke.config.ts."
    href="/docs/reference/configuration"
  />
  <Card title="CLI" description="oke dev writes the env map." href="/docs/reference/cli" />
  <Card title="Vault" description="Master key and managed providers." href="/docs/elements/vault" />
</Cards>
