Self-hosted environments quickstart
Stand up your first self-hosted environment: one runner on one host, a test session routed to it, and a follow-up sent from the CLI.
This walkthrough gets the smallest working self-hosted environment running: a single runner on a single host executing a single test session. It is a proof of concept, not a production deployment. Before you point it at private repositories or internal systems, work through deploying to production.
You will switch between two places:
- claude.ai in a browser, to create the environment, check its health and start a session.
- A terminal on the runner host, for everything the runner does.
Note: Self-hosted environments are in public beta on Team and Enterprise plans. See availability and limitations.
Before you start
On claude.ai
- An Owner must have switched on Allow self-hosted environments on the Cloud environments admin page. Until then the New button doesn't appear. If you aren't an Owner, ask one to create the environment and pass you the secret. The runner and terminal steps need no claude.ai role, and wherever a step says to check the admin UI, the runner's log tells you the same thing.
- Your organisation needs a GitHub connection so people can choose repositories when starting sessions (see Claude Code on the web).
On the host
| Requirement | Detail |
|---|---|
| Operating system | Linux or macOS, bare metal, VM or container. Windows is not supported as a runner host; use a Linux container. Developers' own machines can be anything, because they start sessions in a browser |
| Outbound HTTPS | api.anthropic.com; claude.ai and the download hosts it redirects to (for installing); your git host. The full list is in the deploy guide's network requirements |
| Clock | Synchronised, for example with NTP. Authentication fails if it drifts more than five minutes |
| Claude Code | v2.1.224 or later, installed any standard way (see setup). The runner is the self-hosted-runner subcommand of the normal claude binary |
| Git | 2.24 or newer. Some deploy options need newer still |
A note on versions: the native installer's default latest channel gets releases immediately, while the stable channel, the Homebrew claude-code cask and the stable apt, dnf and apk repositories lag by about a week. Pin an exact version for a real fleet.
Check the host is ready:
claude self-hosted-runner --help
You should see the runner's own usage text, including flags like --environment-secret-file. If you get the general claude --help output, the binary is older than 2.1.224; run claude update or reinstall from latest.
Option A: guided setup
If you can run an interactive session on the host, the quickest route is:
claude self-hosted-runner setup
This starts a Claude Code session that talks you through creating the environment in the admin UI, starts a local runner with the secret file you save, confirms it registers, and writes a cheat sheet to ./runner-setup/CHEAT-SHEET.md.
It has conditions:
- You must be signed in with
claude auth loginas an account with the Owner role. - It doesn't work with API keys or third-party model providers.
- Run the version check first. On a binary older than 2.1.224, this command just opens an ordinary Claude session with "setup" as the prompt.
If any of that rules it out, use the manual steps.
Option B: manual setup
1. Create the environment
- Open the Cloud environments page in claude.ai admin settings.
- Under Self-hosted environments, choose New, give it a name (I use something like
build-farm-eu), and choose Create. - On the wizard's second step, choose Copy environment key.
That key is the environment secret. You see it exactly once and cannot retrieve it later, and it expires 365 days after creation. Paste it straight into the next step.
Also note the environment's ccpool_... ID, which stays visible in its detail dialog. You need it later for token verification and for dispatching CI test sessions.
To rotate or replace a lost secret: create a new one from the environment's Configuration tab, roll it out to your runners, then revoke the old one. A runner holding a revoked secret fails its next authenticated poll, logs poll auth failed and exits, at which point your orchestrator restarts it with the new secret.
2. Store the secret on the host
Any path the runner can read works. Using /etc/claude (which needs root):
sudo mkdir -p /etc/claude
sudo sh -c 'umask 077; cat > /etc/claude/environment-secret'
Paste the key, press Enter, then Ctrl-D. Reading from the terminal keeps the secret out of shell history, and the umask makes the file readable by its owner only.
3. Start the runner
Pick an absolute base directory the runner can create or write to. It checks repositories out and creates per-session folders beneath it. Without --base-dir it uses /workspace, which only works if that already exists and is writable, or you run as root.
claude self-hosted-runner \
--environment-secret-file /etc/claude/environment-secret \
--base-dir /srv/claude-runner
The runner registers and starts polling. If it can't create or write the base directory, it exits at startup with an error naming the path, rather than registering.
For this test, restart it by hand if it exits. Production runners sit under an orchestrator that restarts them, usually with a fresh filesystem each time.
4. Check it registered
Back on the Cloud environments page, the environment's status should flip from No runners deployed to Healthy within seconds. Open the environment and choose Activity to see the runner itself.
5. Send it a session
- Go to claude.ai/code and start a session.
- In the environment picker, choose your self-hosted environment.
- Pick a repository this host can already clone, or a public one. The runner uses whatever git credentials the host already has; proper credentials for private repositories are covered in the deploy guide.
- Give Claude a small task, such as "list the top-level directories and summarise what each does".
The runner logs Picked up session <session-id> with its active count and capacity, so you can see which host took it. Follow the conversation at claude.ai/code as usual. If the session stays queued, the deploy guide's troubleshooting section is the place to look.
When the session finishes, the runner exits. That is intended: see runner lifecycle. In production, run it under something that restarts it on exit and backs off if it keeps exiting immediately after starting.
Message the session from your terminal
You can add to a running session from any machine where you're signed in with claude auth login. It doesn't have to be the runner host or the machine that started the session:
claude -p "Now add a CONTRIBUTING.md based on what you found" --cloud session_01AbCdEf
The last argument can be a bare session_... or cse_... ID, or the session's claude.ai/code URL. On success the CLI prints Sent to cloud session. with the session ID and a link to view it. This works identically for Anthropic-hosted sessions; Claude Code on the web covers JSON output and the account and policy requirements.
What to do next
- Deploy to production: harden the host, lock down egress, set up git credentials and run a fleet on Kubernetes or Compose.
- Customise sessions: wrapper scripts, hooks, on-demand runners, MCP servers and permissions.
- Test end to end: a CI smoke test before promoting a runner image.