2026-01-08 22:37:06 +01:00
---
2026-01-30 03:15:10 +01:00
summary: "Where OpenClaw loads environment variables and the precedence order"
2026-01-08 22:37:06 +01:00
read_when:
- You need to know which env vars are loaded, and in what order
- You are debugging missing API keys in the Gateway
- You are documenting provider auth or deployment environments
2026-01-31 16:04:03 -05:00
title: "Environment Variables"
2026-01-08 22:37:06 +01:00
---
2026-01-31 21:13:13 +09:00
2026-01-08 22:37:06 +01:00
# Environment variables
2026-01-30 03:15:10 +01:00
OpenClaw pulls environment variables from multiple sources. The rule is **never override existing values ** .
2026-01-08 22:37:06 +01:00
## Precedence (highest → lowest)
2026-01-31 21:13:13 +09:00
1. **Process environment ** (what the Gateway process already has from the parent shell/daemon).
2. * * `.env` in the current working directory** (dotenv default; does not override).
3. **Global `.env` ** at `~/.openclaw/.env` (aka `$OPENCLAW_STATE_DIR/.env` ; does not override).
4. **Config `env` block ** in `~/.openclaw/openclaw.json` (applied only if missing).
5. **Optional login-shell import ** (`env.shellEnv.enabled` or `OPENCLAW_LOAD_SHELL_ENV=1` ), applied only for missing expected keys.
2026-01-08 22:37:06 +01:00
2026-04-04 18:24:29 -07:00
On Ubuntu fresh installs that use the default state dir, OpenClaw also treats `~/.config/openclaw/gateway.env` as a compatibility fallback after the global `.env` . If both files exist and disagree, OpenClaw keeps `~/.openclaw/.env` and prints a warning.
2026-01-08 22:37:06 +01:00
If the config file is missing entirely, step 4 is skipped; shell import still runs if enabled.
## Config `env` block
Two equivalent ways to set inline env vars (both are non-overriding):
``` json5
{
env: {
OPENROUTER_API_KEY: "sk-or-...",
vars: {
2026-01-31 21:13:13 +09:00
GROQ_API_KEY: "gsk-...",
},
},
2026-01-08 22:37:06 +01:00
}
```
## Shell env import
`env.shellEnv` runs your login shell and imports only **missing ** expected keys:
``` json5
{
env: {
shellEnv: {
enabled: true,
2026-01-31 21:13:13 +09:00
timeoutMs: 15000,
},
},
2026-01-08 22:37:06 +01:00
}
```
Env var equivalents:
2026-01-31 21:13:13 +09:00
2026-01-30 03:15:10 +01:00
- `OPENCLAW_LOAD_SHELL_ENV=1`
- `OPENCLAW_SHELL_ENV_TIMEOUT_MS=15000`
2026-01-08 22:37:06 +01:00
2026-03-01 20:31:06 -08:00
## Runtime-injected env vars
OpenClaw also injects context markers into spawned child processes:
- `OPENCLAW_SHELL=exec` : set for commands run through the `exec` tool.
- `OPENCLAW_SHELL=acp` : set for ACP runtime backend process spawns (for example `acpx` ).
- `OPENCLAW_SHELL=acp-client` : set for `openclaw acp client` when it spawns the ACP bridge process.
- `OPENCLAW_SHELL=tui-local` : set for local TUI `!` shell commands.
These are runtime markers (not required user config). They can be used in shell/profile logic
to apply context-specific rules.
2026-03-08 16:17:28 -07:00
## UI env vars
- `OPENCLAW_THEME=light` : force the light TUI palette when your terminal has a light background.
- `OPENCLAW_THEME=dark` : force the dark TUI palette.
- `COLORFGBG` : if your terminal exports it, OpenClaw uses the background color hint to auto-pick the TUI palette.
2026-01-16 16:32:07 -05:00
## Env var substitution in config
You can reference env vars directly in config string values using `${VAR_NAME}` syntax:
``` json5
{
models: {
providers: {
"vercel-gateway": {
2026-01-31 21:13:13 +09:00
apiKey: "${VERCEL_GATEWAY_API_KEY}",
},
},
},
2026-01-16 16:32:07 -05:00
}
```
2026-03-19 10:31:20 -07:00
See [Configuration: Env var substitution ](/gateway/configuration-reference#env-var-substitution ) for full details.
2026-01-16 16:32:07 -05:00
2026-02-24 16:26:51 -06:00
## Secret refs vs `${ENV}` strings
OpenClaw supports two env-driven patterns:
- `${VAR}` string substitution in config values.
2026-02-25 17:58:10 -06:00
- SecretRef objects (`{ source: "env", provider: "default", id: "VAR" }` ) for fields that support secrets references.
2026-02-24 16:26:51 -06:00
Both resolve from process env at activation time. SecretRef details are documented in [Secrets Management ](/gateway/secrets ).
2026-02-08 16:20:13 -05:00
## Path-related env vars
| Variable | Purpose |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OPENCLAW_HOME` | Override the home directory used for all internal path resolution (`~/.openclaw/` , agent dirs, sessions, credentials). Useful when running OpenClaw as a dedicated service user. |
| `OPENCLAW_STATE_DIR` | Override the state directory (default `~/.openclaw` ). |
| `OPENCLAW_CONFIG_PATH` | Override the config file path (default `~/.openclaw/openclaw.json` ). |
2026-02-22 18:15:13 +08:00
## Logging
| Variable | Purpose |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `OPENCLAW_LOG_LEVEL` | Override log level for both file and console (e.g. `debug` , `trace` ). Takes precedence over `logging.level` and `logging.consoleLevel` in config. Invalid values are ignored with a warning. |
2026-02-08 16:20:13 -05:00
### `OPENCLAW_HOME`
When set, `OPENCLAW_HOME` replaces the system home directory (`$HOME` / `os.homedir()` ) for all internal path resolution. This enables full filesystem isolation for headless service accounts.
**Precedence: ** `OPENCLAW_HOME` > `$HOME` > `USERPROFILE` > `os.homedir()`
**Example ** (macOS LaunchDaemon):
``` xml
<key > EnvironmentVariables</key>
<dict >
<key > OPENCLAW_HOME</key>
2026-04-01 23:50:25 -05:00
<string > /Users/user</string>
2026-02-08 16:20:13 -05:00
</dict>
```
`OPENCLAW_HOME` can also be set to a tilde path (e.g. `~/svc` ), which gets expanded using `$HOME` before use.
2026-03-21 10:47:29 -07:00
## nvm users: web_fetch TLS failures
If Node.js was installed via **nvm ** (not the system package manager), the built-in `fetch()` uses
nvm's bundled CA store, which may be missing modern root CAs (ISRG Root X1/X2 for Let's Encrypt,
DigiCert Global Root G2, etc.). This causes `web_fetch` to fail with `"fetch failed"` on most HTTPS sites.
On Linux, OpenClaw automatically detects nvm and applies the fix in the actual startup environment:
- `openclaw gateway install` writes `NODE_EXTRA_CA_CERTS` into the systemd service environment
- the `openclaw` CLI entrypoint re-execs itself with `NODE_EXTRA_CA_CERTS` set before Node startup
**Manual fix (for older versions or direct `node ...` launches): **
Export the variable before starting OpenClaw:
``` bash
export NODE_EXTRA_CA_CERTS = /etc/ssl/certs/ca-certificates.crt
openclaw gateway run
```
Do not rely on writing only to `~/.openclaw/.env` for this variable; Node reads
`NODE_EXTRA_CA_CERTS` at process startup.
2026-01-08 22:37:06 +01:00
## Related
- [Gateway configuration ](/gateway/configuration )
2026-01-24 09:49:35 +00:00
- [FAQ: env vars and .env loading ](/help/faq#env-vars-and-env-loading )
2026-01-08 22:37:06 +01:00
- [Models overview ](/concepts/models )