> ## Documentation Index
> Fetch the complete documentation index at: https://docs-stg.outerlayer.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Environment variables

> Every variable the CLI and its hooks read.

## Variables you set

| Variable | Read by | What it does | Default |
| - | - | - | - |
| `OUTERLAYER_WORK` | The session hooks, `sync`, `work open-pr` in a host build | The work item this session is for, as a bare number. Only a session launched with it uploads. See [Work on an item locally](/launch-a-session). | unset |
| `OUTERLAYER_URL` | Every cloud command, `runner container-start` | Gateway base URL. With no `--url`, no variable and no `url` in the config file, the command refuses. In the runner image, it is the factory's address, and it must match the config in the volume. | unset |
| `OUTERLAYER_API_KEY` | Every cloud command, `mcp serve`, `runner container-start` | The API key. An empty value is ignored. In the runner image, it is the runner key, and it must match the config in the volume. | unset |
| `OUTERLAYER_APP_ID` | Every cloud command, `runner container-start` | The factory id. For a login, it also overrides the repository's saved connection. In the runner image, it must match the config in the volume. | unset |
| `OUTERLAYER_RUNNER_NAME` | `runner container-start` | The name of the runner in the container image, as the factory shows it. `OUTERLAYER_HOST` is its earlier name and still works. It must match the config in the volume. See [Run the runner in a container](/run-the-runner-in-a-container). | unset |
| `OUTERLAYER_AGENT` | `runner container-start` | The agent whose commands the image writes into the config on its first start. Only `claude` is supported. | `claude` |
| `OUTERLAYER_RUNNER_IMAGE` | `runner start`, `runner stop`, `runner status`, `doctor` | The CLI version a runner container image runs. The image sets it, and you do not. Where it is set, the runner never updates itself, `runner stop` drains without ending the container, and `runner status` and `doctor` name the image tag to pull. | set by the image |
| `OUTERLAYER_NO_UPDATE_NOTICE` | Every `outerlayer` command, the session hooks | Any non-empty value turns off both notices of a newer CLI version: the line after a command in a terminal and the line at session start. It does not turn off the session-start line about maintained skills from another CLI version. | unset |
| `OUTERLAYER_TIER` | `sync` | Capture tier when `--tier` is absent: `metrics`, `redacted` or `full`. | the config file's `tier`, else `full` |
| `CLAUDE_CODE_OAUTH_TOKEN`, `ANTHROPIC_API_KEY`, `ANTHROPIC_AUTH_TOKEN` | `outerlayer runner`, `runner container-start` | The Claude credential for a build the runner provisions itself (`builtin:vm`, `builtin:container`, `builtin:process`). See the note below the table. | unset |
| `CREDENTIALS_DIRECTORY` | `outerlayer runner` | The directory where systemd puts the credentials of a service. The runner reads Claude's credential from its `claude` file when its environment holds none. Systemd sets it, and you do not. | unset |
| Any `${NAME}` in a destination's `header` | `outerlayer runner` | That destination's secret. The runner refuses to start while one is unset. Hooks and builds never receive it. See [Destinations](/destinations-and-secrets). | unset |
| `CI`, `JENKINS_URL` | `sync`, `emit artifact`, `emit <name>` | `CI=true`, `CI=1` or any `JENKINS_URL` marks the run as CI. Your CI system sets these. | unset |
| `GITHUB_ACTIONS`, `GITHUB_RUN_ID` | `work build` | Together, they record the GitHub Actions run as the item's source. GitHub Actions sets them. | unset |
| `GITHUB_REF`, `GITHUB_EVENT_PATH`, `GITHUB_REPOSITORY` | `emit artifact` | The pull request and repository an artifact anchors to without `--pr`. GitHub Actions sets them. | unset |
| `HOME` | Every command | Where `~/.outerlayer/` is. It wins over the account's home directory. | the account's home |
| `WSL_DISTRO_NAME` | `runner install --service` on WSL2 | The distribution the Windows scheduled task starts. WSL2 sets it, and `sudo` drops it, so run the command without `sudo`. Without it, no task is made. | set by WSL2 |
| `OUTERLAYER_ALLOW_STALE_BUILD` | `sync`, `emit artifact` | `1` lets a CLI built from a source checkout write data while its sources are newer than the build. Without it, both refuse outside CI. | unset |
| `NO_COLOR` | Every command | Any non-empty value strips escape codes. `--no-color` and `TERM=dumb` do too. | unset |
| `FORCE_COLOR` | Every command | Emit escape codes even to a pipe. `0` does not force. | unset |

**The Claude credential.** The OAuth token wins when both it and the API key
are set. The runner forwards the credential to Claude's API and never passes
it to the build. With none, the runner claims no work and reports itself
blocked.

A service loads the credential from `claude.env` beside the config
file, only when it starts. On systemd 247 or later it reaches the runner as a
file in `CREDENTIALS_DIRECTORY`. The runner then removes these variables from
its own environment when it starts. On older systemd they are in the service's
environment. In the runner image, set one in the container's environment. The
image never writes it to the volume. See [The gateway and
Claude](/container-builds#the-gateway-and-claude).

## Variables `outerlayer claude` sets

`outerlayer claude` sets these in the environment of the Claude Code it starts, in a governed checkout, on a laptop or in a build. You do not set them.

| Variable | What it does |
| - | - |
| `OUTERLAYER_CONTROL_PLANE_DIR` | The directory the control plane's files were composed into. The session-start hook reads it: when it is set, the control plane is attached and the hook says nothing about it being missing. Control-plane hooks reach their scripts through it. |
| `CLAUDE_CODE_ADDITIONAL_DIRECTORIES_CLAUDE_MD` | `1`. Makes Claude Code read the directory's `CLAUDE.md`, for subagents too. |

Which of a flag, a variable and the config file wins is in [Credential resolution](/reference/cli#credential-resolution). The runner is the exception: it uses only its own config file's values. The runner image's entrypoint reads its variables once, to write that file.

## Variables a build receives

`outerlayer runner` sets these for the hooks and the command, and so for
everything they start. Its own config file supplies them. Any `OUTERLAYER_*`
in the shell that started the runner is dropped.

Hooks and a build run on the host inherit the rest of the runner's
environment, minus destination secrets. A container build gets none of the
host's environment except the names in `runner.build.variables`. It also gets
the recipe's `containerEnv`, each destination's `env`, and the runner's own
values in the last rows below.

| Variable | Set for | Holds |
| - | - | - |
| `OUTERLAYER_URL`, `OUTERLAYER_APP_ID` | Every hook, the command, the sync step | The factory, from the config file's top-level `url` and `appId`. |
| `OUTERLAYER_API_KEY` | Every hook, the command, the sync step | The attempt's [item key](/reference/build-reference#item-key). It acts only on the claimed item while the claim is live. A build the runner provisions itself gets a placeholder. See [The gateway and Claude](/container-builds#the-gateway-and-claude). |
| `OUTERLAYER_WORK` | Every hook, the command | The claimed item's number. The session-start hook that `outerlayer init` installs for Claude Code reads it to link the session. Another agent needs a hook like it. |
| `OUTERLAYER_BRANCH` | Every hook, the command | The branch the build works and pushes on, when the claim names one. See [The branch a claim names](/reference/build-reference#the-branch-a-claim-names). |
| `OUTERLAYER_JOB_DIR` | Every hook, the command | This attempt's directory, holding `provision.out` and every log. |
| `OUTERLAYER_GOVERNANCE` | The command | `self` in a build that no control plane governs. `outerlayer claude` then asks the gateway nothing and does not check the Claude Code version. The runner's delivery record decides in a governed build, whatever this says. You do not set it. |
| `GIT_AUTHOR_NAME`, `GIT_AUTHOR_EMAIL`, `GIT_COMMITTER_NAME`, `GIT_COMMITTER_EMAIL` | Every hook, the command, the sync step, when the claim names a commit author | The identity the build commits as. See [Who a build's commits are authored by](/github-app-and-build-tokens#who-a-builds-commits-are-authored-by). |
| `GIT_CONFIG_COUNT`, `GIT_CONFIG_KEY_<n>`, `GIT_CONFIG_VALUE_<n>` | The command and a container build's sync step, when the claim names a co-author. Not set for a build run through an `exec`. They point `core.hooksPath` at the runner's git hooks, which add the co-author line. | |
| `ANTHROPIC_BASE_URL`, `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`, a credential placeholder | A build the runner provisions itself | They point Claude Code at the runner, which adds the host's Claude credential. See [The gateway and Claude](/container-builds#the-gateway-and-claude). |
| `OUTERLAYER_BUILD_DIR` | The provision and cleanup hooks | This build's directory. See [Write your own hooks](/write-your-own-hooks). |
| `OUTERLAYER_REPOSITORY`, `OUTERLAYER_RECIPE_COMMIT` | The provision hook | The repository, and the commit its default branch points at. See [Write your own hooks](/write-your-own-hooks). |
| `OUTERLAYER_MEMORY`, `OUTERLAYER_CPUS`, `OUTERLAYER_PIDS`, `OUTERLAYER_DISK` | The provision hook | The `runner.build` limits, by default `8g`, `4`, `4096` and `40g`. |
| `OUTERLAYER_OUTCOME`, `OUTERLAYER_LOG` | The cleanup hook, the report hook's end phase | The outcome and the command's log. See below. |
| `OUTERLAYER_PHASE` | The report hook | `start` or `end`. |
| `OUTERLAYER_EVAL_INPUT`, `OUTERLAYER_CHECK_ITEMS` | A host check's command | The read-only folder of the item, its diff and the build's sessions, and the file for check items. See [Host checks](/reference/build-reference#host-checks). |
| `OUTERLAYER_REPOSITORIES` | Every command in a `builtin:container` or `builtin:vm` build | A JSON list of the checkouts. See [The repositories in a build](/container-builds#the-repositories-in-a-build). |
| `HOME` (`/build/home`), `TMPDIR`, `HTTP_PROXY`, `HTTPS_PROXY`, `NO_PROXY` and their lowercase forms, `NODE_USE_ENV_PROXY`, `YARN_HTTP_PROXY`, `YARN_HTTPS_PROXY`, `GIT_TERMINAL_PROMPT`, `GH_CONFIG_DIR`, `GH_REPO`, `GH_NO_UPDATE_NOTIFIER` | Every command in a `builtin:container` build | The proxy variables point at [the tunnel](/container-builds#the-tunnel). |
| `NODE_OPTIONS` | Every command in a `builtin:container`, `builtin:vm` or `builtin:process` build | It keeps the options the image, the recipe's `containerEnv` or a named host variable set, and adds `--disable-warning=UNDICI-EHPA`. On Node 22, `NODE_USE_ENV_PROXY` prints that warning on the stderr of every Node process. |

What each hook adds is in [Write your own hooks](/write-your-own-hooks).

`OUTERLAYER_OUTCOME` is one of `ok`, `incomplete`, `failed`, `timed_out`,
`idle`, `lease_lost`, `interrupted` or `stopped`. It is empty when the
provision hook exited 75. `ok` means the command exited zero; any other exit
is `failed`.

The cleanup hook sees `ok` for every command that exited zero, because it
runs before the item's checks are read. The release, and the report hook
after it, carry `incomplete` instead when the item has no pull request.
They also carry it when those checks still fail or have no result. See [When the command exits
0](/reference/build-reference#when-the-command-exits-0).

Even `ok` is not a full verdict on the work: the checks prove only what they
check.

`OUTERLAYER_LOG` is unset in the report hook's start phase. The log will be
`$OUTERLAYER_JOB_DIR/command.log`.

Anything else a hook needs comes from `outerlayer work status --item
$OUTERLAYER_WORK --json` and `outerlayer work threads --item
$OUTERLAYER_WORK --json`. `work status` also carries the issue's body, as
`issue.body`.

## In CI

Set the three credential variables as secrets and the CLI needs no `login`:

```yaml theme={"system"}
env:
  OUTERLAYER_URL: ${{ vars.OUTERLAYER_URL }}
  OUTERLAYER_API_KEY: ${{ secrets.OUTERLAYER_API_KEY }}
  OUTERLAYER_APP_ID: ${{ vars.OUTERLAYER_APP_ID }}
```

`outerlayer emit artifact` anchors to the pull request from the CI environment without `--pr`. `outerlayer work build` records the CI run as the source.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.