Self-Hosted Runner
A self-hosted runner lets SetForth's agents run on hardware you control — your own laptop, a server, or a machine inside your network. You install a small program, register it with SetForth from your dashboard, and it picks up agent work for your organization and runs it on that machine.
The runner only makes outbound connections to SetForth over HTTPS, so there is nothing inbound to open on your network. Each agent session runs inside Docker on the host, isolated from your other work.
Supported platforms
The runner is supported on macOS and Linux:
- macOS — supported. Runs as a managed service via launchd.
- Linux — supported. Runs as a managed service via systemd.
- Windows — not supported directly. Run the runner inside WSL2 (a Linux distribution such as Ubuntu) or a Linux virtual machine, then follow the Linux instructions. Docker Desktop's WSL2 backend works for this.
Prerequisites
- A macOS or Linux host. Windows is not supported directly — run the runner via WSL2 or a Linux VM and follow the Linux instructions.
- Node.js 20 or newer on the machine that will run the runner.
- Docker (Desktop or Engine), installed and running. The runner always runs agents inside containers, so Docker must be available on the host.
- Anthropic credentials on the host. The agent is powered by Claude, so the host must provide credentials one of two ways (see Anthropic credentials below).
- A SetForth account with a role that can manage runners in your organization. If you cannot see the Runners page in your dashboard, ask an organization admin to grant you access or to register the runner for you.
Anthropic credentials
The agent runs inside a Docker container on the host and is powered by Claude, so the host must supply Anthropic credentials. You do not need the Claude CLI installed for normal operation — the agent runs in the container, not from your shell. Provide credentials one of two ways:
ANTHROPIC_API_KEYenvironment variable. Set this in the runner's environment. Usage is billed to your Anthropic API account.- A Claude subscription via
claude login. Sign in once on the host with the Claude CLI, and the runner uses that subscription. Usage counts against your Claude subscription. The CLI is only needed to perform that one-time login; it is not used at runtime.
Either option works. If both are present, the runner uses the ANTHROPIC_API_KEY.
Install
Install the runner CLI globally on the machine that will run your agents:
npm install -g @setforth/self-hosted-runner
This installs the set-forth-runner command.
Register the runner
In your SetForth dashboard, open Runners and add a runner. SetForth registers it and generates a runner.config.yml file with the values this runner needs to connect:
runnerId: # this runner's id
orgId: # your organization id
platformUrl: # the SetForth API origin to connect to
apiKey: # this runner's secret access token
The apiKey is shown once, at registration time, and is not retrievable afterward. Copy the generated config right away and save it to a stable path, for example ~/.set-forth-runner/runner.config.yml.
Keep the apiKey secret. It is this runner's credential: anyone who has it can connect a runner to your organization and run agent work as you, so treat it like a password. Keep runner.config.yml out of version control and off shared machines. If the key is ever exposed, rotate it from the runner's menu in the dashboard (Rotate API key), which revokes the old one.
By default the runner reads runner.config.yml from the current directory. Start it from the folder that holds the file, or point at the file explicitly with --config /path/to/runner.config.yml.
Run the runner
There are two ways to run it.
As a managed service (recommended)
Best for an always-on runner. It starts at boot, restarts on crash, and keeps running across logout (launchd on macOS, systemd on Linux):
set-forth-runner install-service --config ~/.set-forth-runner/runner.config.yml
The absolute path of the config file is recorded when you install the service, so keep runner.config.yml where it is afterward. A background service has no shell environment, so the connection values must all be present in the config file itself (the dashboard-generated file already includes them). Remove the service later with:
set-forth-runner uninstall-service
In the foreground
Runs in the terminal, which is handy for a quick test. It stops when you close the terminal, so it will not come back after a logout or reboot:
set-forth-runner start
Stopping cleanly
To stop a runner without interrupting work in progress, drain it. The runner finishes its current session and then exits:
set-forth-runner drain
Pressing Ctrl-C (or sending SIGTERM) does the same thing.
Checking the config
To confirm a config file resolves to a complete runner identity without actually starting the runner:
set-forth-runner validate-config --config ~/.set-forth-runner/runner.config.yml
Configuration reference
Beyond the connection values, runner.config.yml accepts optional settings:
agent.permission_mode—defaultruns the agent with its normal permission prompts;skipbypasses them. Useskipwith caution.agent.allowed_tools— a list restricting which tools the agent may use (for exampleRead,Edit,Write,Bash). Omit it to allow the defaults.agent.disallowed_tools— a list of tools to deny. A denied tool wins over the allow list.agent.max_turns— a cap on how many turns the agent may take per session.agent.env— extra environment variables to pass to the agent process.local_logs— write per-session logs on the host for local troubleshooting. Setenabled: trueand, optionally, adirectory(you can also override the location with theRUNNER_LOG_DIRenvironment variable).
A sample config with the connection values plus a few optional settings:
runnerId: your-runner-id
orgId: your-org-id
platformUrl: https://api.setforth.app
apiKey: your-secret-api-key
agent:
permission_mode: default
allowed_tools:
- Read
- Edit
- Write
- Bash
max_turns: 100
env:
MY_CUSTOM_VAR: "value"
local_logs:
enabled: true
directory: ~/.set-forth-runner/logs
Updating
Upgrades are manual. Install the latest version, then drain the runner so it restarts on the new build:
npm install -g @setforth/self-hosted-runner@latest
set-forth-runner drain
If you run the runner as a managed service, it restarts automatically after draining. If you run it in the foreground, start it again after the upgrade.
