How OpenClaw loads environment variables and why service starts lose them
Env vars and .env loading
How does OpenClaw load environment variables?
OpenClaw reads env vars from the parent process (shell, launchd/systemd, CI, etc.) and additionally loads:
.env from the current working directory.
a global fallback .env from ~/.openclaw/.env ($OPENCLAW_STATE_DIR/.env).
Normally, neither .env file overrides existing env vars. For an OpenClaw-installed systemd service, the global .env may replace only service values that OpenClaw recorded as managed; operator-owned service values still take precedence. Provider credential and endpoint-routing keys are an exception for workspace .env: keys such as GEMINI_API_KEY, XAI_API_KEY, MISTRAL_API_KEY, or any key ending in _ENDPOINT (and other bundled-provider auth or endpoint env vars) are ignored from workspace .env and should live in the process environment, ~/.openclaw/.env, or config env.vars.
Inline env vars in config apply only if missing from the process env:
This runs your login shell and imports only missing expected keys (never overrides). Env var equivalents: OPENCLAW_LOAD_SHELL_ENV=1, OPENCLAW_SHELL_ENV_TIMEOUT_MS=15000.
I set COPILOT_GITHUB_TOKEN, but models status shows "Shell env: off." Why?
openclaw models status reports whether shell env import is enabled. "Shell env: off" does not mean your env vars are missing - it just means OpenClaw will not load your login shell automatically.
If the Gateway runs as a service (launchd/systemd), it will not inherit your shell environment. Fix by putting the token in ~/.openclaw/.env, enabling env.shellEnv.enabled: true, or adding it to config env (applies only if missing), then restarting the gateway and rechecking:
openclaw models status
Copilot activates only with an explicit models.providers.github-copilot entry, a saved Copilot auth profile, or COPILOT_GITHUB_TOKEN. Generic GH_TOKEN and GITHUB_TOKEN variables do not enable or authenticate Copilot. Run openclaw models auth login --provider github-copilot to sign in.