> ## Documentation Index
> Fetch the complete documentation index at: https://docs.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 [Launch a session](/launch-a-session). | unset |
| `OUTERLAYER_URL` | Every cloud command | Gateway base URL. With no `--url`, no variable and no `url` in the config file, the command refuses. | unset |
| `OUTERLAYER_API_KEY` | Every cloud command, `mcp serve` | The API key. An empty value is ignored. | unset |
| `OUTERLAYER_APP_ID` | Every cloud command | The factory id. For a login, it also overrides the repository's saved connection. | 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` | `outerlayer runner` | The Claude credential for a build the runner provisions itself (`builtin:vm`, `builtin:container`, `builtin:process`). The OAuth token wins when both are set. The runner forwards it to Claude's API and never passes it to the build. With neither, the runner claims no work and reports itself blocked. A service reads them from `runner.env` beside the config file, only when it starts. See [The gateway and Claude](/container-builds#the-gateway-and-claude). | 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 result` | `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. Only for working on the CLI itself. | 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 |

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.

## Variables a build receives

`outerlayer runner` sets these for the hooks and the command. 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 row below.

| Variable | Set for |
| - | - |
| `OUTERLAYER_URL`, `OUTERLAYER_APP_ID`, `OUTERLAYER_API_KEY` | Every hook, the command, the sync step. The key is the attempt's [item key](/reference/cli-runner#item-key), or a placeholder in a build the runner provisions itself. |
| `OUTERLAYER_WORK`, `OUTERLAYER_BRANCH` | Every hook, the command |
| `OUTERLAYER_JOB_DIR` | Every hook, the command. This attempt's directory, holding `provision.out` and every log. |
| `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 |
| `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`. |
| `ANTHROPIC_BASE_URL`, `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC`, a credential placeholder | A build the runner provisions itself |
| `OUTERLAYER_BUILD_DIR` | The provision and cleanup hooks |
| `OUTERLAYER_REPOSITORY`, `OUTERLAYER_RECIPE_COMMIT` | The provision hook |
| `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 |
| `OUTERLAYER_PHASE` | The report hook: `start` or `end` |
| `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). |

What each holds is in [The build's variables](/write-your-own-hooks#the-builds-variables) and the hook sections after it.

`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, or
those checks still fail or have no result. See [When the command exits
0](/reference/cli-runner#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`. Neither carries the issue's 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.