Your Claude Code sessions now run on your machine: self-hosted runner guide

Your Claude Code Sessions Now Run on Your Machine: Guide to the self-hosted-runner (and What’s Still Coming from Anthropic)

Anthropic released Claude Code 2.1.224 today, August 7, 2026, and the headline of the release is a single subcommand:

claude self-hosted-runner turns your own machines or containers into a place Claude Code web, mobile, and desktop sessions can run, on Team and Enterprise plans

The idea comes straight from CI self-hosted runners, and it works the same way. You run a process on a host within your network. That process registers against an “environment” that you create in the admin settings on claude.ai, polls Anthropic for queued work, clones the repo, and spins up a child Claude Code process on your hardware. When a dev starts a cloud session — from claude.ai, from the mobile or desktop app, from a scheduled routine, or from the terminal with claude --cloud — the environment picker now lists your environment alongside Anthropic’s.

Before setting anything up, it’s worth being precise about what moves and what doesn’t, because the name invites a mistaken assumption.

What Moves and What Doesn’t

The execution of the session moves. Repository checkouts, build artifacts, secrets, and any files the session creates or edits live on machines you provision. Sessions can reach internal services, databases, and registries from inside your network, without exposing them to the internet. You control the image, so compilers, SDKs, and internal CLIs come preinstalled and each session starts ready to build.

The model doesn’t move. Anthropic’s documentation says it plainly: “Session content still goes to api.anthropic.com for model inference.” Prompts, responses, tool results — the conversation itself — leaves your network over outbound HTTPS, and the session transcript is stored by Anthropic so the session can resume from any surface. Inference also can’t be routed through Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, or an LLM gateway in a self-hosted environment. The control plane, the queue, and the claude.ai interface are all still hosted by Anthropic.

In other words: this is not a way to lower your inference bill, nor a way to run Claude Code without dependency on Anthropic’s cloud. Billing doesn’t change: self-hosted sessions consume your organization’s Claude Code usage exactly like Anthropic-hosted ones. What you get is control over where your code lives while the agent works on it, and over what the agent can reach while doing it.

There’s one more thing worth knowing before planning a rollout, and it’s the sharpest edge of the release: self-hosted environments are not available for organizations with Zero Data Retention enabled. The teams whose compliance posture most obviously points toward self-hosting are, for now, the ones left out.

All connections are outbound. Anthropic never connects into your network.

Prerequisites

On the claude.ai side:

  • Team or Enterprise plan. It’s in public beta and comes disabled by default: an Owner or admin has to enable Allow self-hosted environments on the Cloud environments admin page, and Claude Code on the web has to be enabled for the organization. The New button doesn’t appear until that toggle is on. If you don’t have the role, someone who does can create the environment and pass you the secret — the runner steps don’t need any role in claude.ai.
  • A GitHub connection for your organization, so devs can choose repositories. Sessions check out from GitHub.

On the host side:

  • Linux or macOS, with outbound HTTPS to api.anthropic.com and to your git host. Windows is not supported as a runner host; run it in a Linux container. Developer workstations are not affected — sessions start from the browser.
  • A clock synchronized with real time. Authentication fails with more than five minutes of skew, and it’s common enough to be the first item on the troubleshooting list.
  • Claude Code 2.1.224 or later, and Git 2.24 or later.

Check the version first, because the failure mode is confusing:

claude self-hosted-runner --help

A ready host prints the runner’s usage text, with flags like --environment-secret-file. On any version before 2.1.224 it prints the generic output of claude --help. The same trap applies to the guided setup below: on an old version, claude self-hosted-runner setup starts a normal Claude session using those words as a prompt.

Note that the latest install channel brings each release as soon as it’s published, while the stable channel, the Homebrew cask, and the stable repos of apt, dnf, and apk come with roughly a week’s delay. Today, that matters.

The Quick Path

There’s a guided setup that creates the environment, spins up a local runner, confirms it registered, and writes a cheat sheet to ./runner-setup/CHEAT-SHEET.md:

claude self-hosted-runner setup

Run it on a machine where you’ve logged in with claude auth login under an account with Owner or admin role. It doesn’t work with API keys or third-party model providers, and needs an interactive session.

The Manual Path

Four steps.

1. Create the environment. On the Cloud environments admin page, under Self-hosted environments, click New, give it a name, and Create. In the second step of the wizard, Copy environment key. That’s the environment secret, shown only once and not recoverable afterward; it expires 365 days from creation. The environment’s ccpool_... ID stays visible in its detail dialog.

2. Spin up a runner. Write the secret to a file without it ending up in shell history:

mkdir -p /etc/claude
(umask 077 && cat > /etc/claude/environment-secret)

Paste the value, Enter, Ctrl-D. The subshell’s umask leaves the file readable only by its owner.

Then create a base directory that the runner user can actually write to, and spin up the runner:

mkdir -p '<writable-dir>'
claude self-hosted-runner \
  --environment-secret-file '/etc/claude/environment-secret' \
  --base-dir '<writable-dir>'

Without --base-dir the default is /workspace, which only works if it already exists and is writable, or if the runner runs as root. Here’s the gotcha: the runner doesn’t verify the directory on startup, so a misconfigured base dir shows up later as sessions that fail as soon as they’re picked up, with EACCES, not as a startup error.

3. Verify it registered. The environment status goes from No runners deployed to Healthy in a few seconds, and the Activity tab shows the runner.

4. Route a session. Start a session on claude.ai/code and choose your environment. The runner clones with whatever git credentials the host already has, so for this first run pick a public repo or one the host can already clone. The runner logs Picked up session <session-id> along with its active sessions count and capacity, so you can confirm from the host’s own output which machine picked up the job.

To send a follow-up from any machine where you have a session open:

claude -p "your message" --cloud <session-id>

Three behaviors that will surprise you

The runner exits on purpose. By default (--drain-grace-sec 0) it exits as soon as its active sessions finish, without continuing to poll. It’s not a crash — it’s designed that way so your orchestrator restarts it with a clean disk. In the quickstart you restart it manually; in production you run it under Kubernetes or equivalent.

One runner serves one user at a time. The first session a runner picks up locks it to that user’s account, and from then on it only runs sessions for that account up to the --capacity limit. That’s what prevents checked-in code from mixing between users, and it has a direct sizing consequence: the minimum size of your fleet is the number of users you expect active at the same time. --capacity buys parallelism within a user’s sessions, not between users. When sessions are queued with runners online, this is usually why.

Dispatch is at the organization level. Any member of your Anthropic organization can send a session to any of its environments — there’s no per-environment access control on dispatch. Treat each runner host as reachable for code execution by any member of the organization, and don’t put data or credentials on one that some member shouldn’t be able to read.

Before pointing it at something real

The quickstart is deliberately the bare minimum that works. The production checklist is a separate document, and several of its items aren’t obvious:

  • Ephemeral containers per session, --capacity 1, no filesystem reuse across accounts.
  • No broad credentials in the image — a credential baked into a shared runner image is available to every session that runs for every member of the organization. Generate short-lived tokens per session from a wrapper script, or use --use-anthropic-git-proxy, which clones with the session’s own short-lived token and needs no git credential in the image.
  • Default-deny egress at your own network edge. Session code is directed by the model and Bash comes pre-approved by default, so shell output runs without asking permission. The product can’t enforce this for you.
  • Block the cloud metadata endpoint (169.254.169.254) from inside the session container — subnet-level policies don’t intercept link-local traffic.
  • On a fixed fleet, the environment secret lives on each runner host, where code from any session can read it. On-demand runners keep it on an orchestrator host that never runs user code.

And a limitation that belongs in the same paragraph as the residency question: connector traffic leaves your network. GitHub, Slack, Linear, and the rest of claude.ai’s connectors are called from Anthropic’s side, not from your runner. If tool traffic has to stay within your edge, run the equivalents as local MCP servers in your image, or filter connectors with allowedMcpServers / deniedMcpServers.

Is it worth it?

If your team doesn’t use cloud sessions, there’s nothing here for you — terminal and IDE sessions always ran on your own machine. If what you want is to have a machine always on managed from other devices, that’s Remote Control, and it works on Pro and Max too.

Self-hosting is for teams whose network, tooling, or compliance requirements make the session execution location a real constraint, and it costs you concrete operational overhead: you build the image, you run the fleet, you control its egress. The honest summary is that it moves your code and your build, not your conversation.

And you? Would running the agent on your own infrastructure change the answer for a repo you wouldn’t put in a cloud session today — or is what really matters that the prompt stays off the network?