outerlayer runner init installs the service that keeps the runner
running.
Before you begin
You need:- Node.js 22 or later, and the CLI:
npm install -g @outerlayer/cli. A service needs a fixed path to start, so use the global install rather thannpx. - A runner key. In the factory, open Settings → API keys, choose
Create API key, and pick the Runner preset. It holds what a runner
needs, including
work.claimandhosts.ingest. Name the key after the machine. The key is shown once. Give each host its own key: a runner key works only from the first host that uses it. See API keys. - The GitHub App installed on the repository. Otherwise every build
fails at provision with
repository_not_in_installation. See Connect a repository and GitHub App permissions and build tokens. - Docker Engine 26 or later, on Linux or WSL2, usable by the runner’s account. Docker Desktop alone is not enough. On a Mac, follow Run builds on macOS. On Windows, follow Run builds on Windows.
- On a Mac, Lima.
outerlayer runner init --vmuses it to run the Linux VM that the runner lives in. Install it withbrew install lima; see Lima’s install page. - Docker’s Buildx plugin, 0.18 or later, and access to Docker Hub. The
runner builds each repository’s image in a builder of its own. It is
docker-buildx-pluginin Docker’s apt repository. Without it the runner claims nothing. See Image builds. - For microVM builds: x86_64 Linux where the runner’s account can open
/dev/kvm. Without it, builds run in containers.
Give the runner its key
A factory key outranks an account login. If you also useouterlayer on
this machine, such as on your own Mac, do not log in with the runner key:
it would replace your own login in ~/.outerlayer/config.json, and your
sessions would switch factory. Give the runner a config file of its own
instead. Every runner command takes --config <path> to use it.
runner.env beside it. In the steps below, add
--config ~/.outerlayer-runner/config.json to each outerlayer runner
command, and keep runner.env in ~/.outerlayer-runner/.
On a machine that only runs the runner, you can log in instead. The key is
read from stdin, so it stays out of your shell history:
Set it up
runner init writes the runner’s block of the config file: ~/.outerlayer/config.json,
or the file you gave with --config. It
names the built-in hooks that fit the machine: builtin:vm on x86_64 Linux
whose account can open /dev/kvm, else builtin:container where Docker
Engine 26 or later runs. The full rule is in
outerlayer runner init.
- On macOS it offers to run the runner in a Linux VM.
--vmsays yes and--no-vmsays no; see Run builds on macOS. - On any other machine that cannot isolate a build, it refuses and writes
nothing. Run it again with
--allow-process-buildsto namebuiltin:process, where builds run as your account with no isolation.
runner init then installs and starts the service that keeps the runner
running; see Keep it running.
The service claims nothing yet. It waits for the two steps below: a command
for each queue, and Claude’s credential.
Edit the commands
runner init writes a placeholder command for each queue. The runner claims
nothing while a queue’s command is still the placeholder. Edit
runner.commands to start your agent. The runner block then looks like this
(abridged):
/build and /amend are skills that outerlayer init installs in the
repository. The running service reads the edited file on its next poll,
with no restart.
To use your own isolation, see Write your own hooks.
Give the runner Claude’s credential
The runner needs a Claude credential in its environment. A build never sees the credential itself. On a host with no browser, create one:runner.env, beside the config
file. Make the file readable only by the runner’s account, add the token,
and restart the service, which reads the file only when it starts. The paths
below are for a config in ~/.outerlayer-runner/; with the default config,
use ~/.outerlayer/runner.env:
ANTHROPIC_API_KEY=<key>. Any secret a
destination reads goes in the same file. See
What the service sets.
Check the host before it takes work
check validates the config, confirms the key works, and prints the
settings the runner would use. It takes the Claude credential from your
shell, and from the runner.env beside the config when the shell has none.
It names the file when it used it. It exits 1 and says what to fix when:
- a queue’s command is still the placeholder.
- a
claudecommand has a--permission-modeClaude Code does not accept, such asbypassPermissons. The message names the command and the value. - built-in hooks find the credential neither in your shell nor in
runner.env. - the key does not hold
work.claim. Create it with the Runner preset.
credentials unverified, the gateway did not answer
normally. Run it again later.
outerlayer doctor reports what isolation a build gets on this machine. It
reads the credential from the service’s runner.env.
Keep it running
outerlayer runner init already set up what keeps the runner running, with
the same command on every system. You write no service file. It restarts
the runner after a crash, a reboot and a self-update. It asks for sudo
where it needs root, and names each command first.
- Linux: the runner runs from boot, as a systemd service.
- macOS: the runner runs from login, as the same service inside the
Linux VM that
--vmmakes. - Windows: the runner runs from login, as the same service inside WSL2.
Run the runner in a terminal instead
The service and a terminal runner cannot run on the same config. To run the runner in a terminal, remove the service first:Build your first item
Ask for a build as yourself, not with the runner key. A build requested with a runner key gets no repository tokens, so it fails. Either:- choose Build beside the issue on the Work page, or
- run this from your own machine:
Watch it run
From a second terminal on the host:status lists running builds and their stage. logs -f follows one
item’s build log. outerlayer runner status --recent shows finished
builds. The session and the pull request land on the item’s page.
If something goes wrong, see Troubleshoot builds.
Every key is in The config file, and every
command in Runner commands.