Tus sesiones de Claude Code ahora corren en tu máquina: guía del self-hosted-runner

Tus sesiones de Claude Code ahora corren en tu máquina: guía del self-hosted-runner (y qué sigue saliendo a Anthropic)

Anthropic publicó hoy, 7 de agosto de 2026, Claude Code 2.1.224, y el titular del release es un solo subcomando:

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

La idea viene directo de los self-hosted runners de CI, y funciona igual. Corres un proceso en un host dentro de tu red. Ese proceso se registra contra un “environment” que creas en la configuración de administración de claude.ai, hace polling a Anthropic buscando trabajo en cola, clona el repo y levanta un proceso hijo de Claude Code en tu hardware. Cuando un dev arranca una cloud session — desde claude.ai, desde la app mobile o desktop, desde una scheduled routine, o desde la terminal con claude --cloud — el environment picker ahora lista tu environment junto a los de Anthropic.

Antes de configurar nada conviene ser preciso sobre qué se mueve y qué no, porque el nombre invita a una suposición equivocada.

Qué se mueve y qué no

Se mueve la ejecución de la sesión. Los checkouts del repositorio, los build artifacts, los secrets y cualquier archivo que la sesión cree o edite viven en máquinas que tú provisionas. Las sesiones pueden alcanzar servicios internos, bases de datos y registries desde adentro de tu red, sin exponerlos a internet. Tú controlas la imagen, así que compiladores, SDKs y CLIs internos vienen preinstalados y cada sesión arranca lista para buildear.

El modelo no se mueve. La documentación de Anthropic lo dice sin rodeos: “Session content still goes to api.anthropic.com for model inference.” Los prompts, las respuestas, los resultados de las herramientas — la conversación misma — salen de tu red por HTTPS saliente, y el transcript de la sesión queda almacenado por Anthropic para que la sesión pueda retomarse desde cualquier superficie. La inferencia tampoco puede enrutarse por Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry ni un LLM gateway en un environment self-hosted. El control plane, la cola y la interfaz de claude.ai también siguen hospedados por Anthropic.

O sea: esto no es una forma de bajar tu factura de inferencia, ni una forma de correr Claude Code sin dependencia del cloud de Anthropic. El billing no cambia: las sesiones self-hosted consumen el uso de Claude Code de tu organización exactamente igual que las hospedadas por Anthropic. Lo que ganas es control sobre dónde vive tu código mientras el agente trabaja sobre él, y sobre qué puede alcanzar el agente mientras lo hace.

Hay algo más que conviene saber antes de planificar un rollout, y es el filo más notorio del release: los environments self-hosted no están disponibles para organizaciones con Zero Data Retention activado. Los equipos cuya postura de compliance apunta más obviamente al self-hosting son, por ahora, los que quedan excluidos.

Todas las conexiones son salientes. Anthropic nunca se conecta hacia adentro de tu red.

Prerrequisitos

Del lado de claude.ai:

  • Plan Team o Enterprise. Es un public beta y viene apagado por defecto: un Owner o admin tiene que activar Allow self-hosted environments en la página de administración Cloud environments, y Claude Code on the web tiene que estar habilitado para la organización. El botón New no aparece hasta que ese toggle esté encendido. Si no tienes el rol, alguien que sí lo tenga puede crear el environment y pasarte el secret — los pasos del runner no necesitan ningún rol en claude.ai.
  • Una conexión de GitHub para tu organización, para que los devs puedan elegir repositorios. Las sesiones hacen checkout desde GitHub.

Del lado del host:

  • Linux o macOS, con HTTPS saliente hacia api.anthropic.com y hacia tu git host. Windows no está soportado como runner host; córrelo en un container Linux. Las workstations de los devs no se ven afectadas — las sesiones arrancan desde el browser.
  • Un reloj sincronizado con la hora real. La autenticación falla con más de cinco minutos de desfase, y es un caso lo bastante común como para ser el primer ítem de la lista de troubleshooting.
  • Claude Code 2.1.224 o superior, y Git 2.24 o superior.

Verifica la versión primero, porque el modo de fallo es confuso:

claude self-hosted-runner --help

Un host listo imprime el texto de uso del runner, con flags como --environment-secret-file. En cualquier versión anterior a 2.1.224 imprime la salida genérica de claude --help. La misma trampa aplica al setup guiado de más abajo: en una versión vieja, claude self-hosted-runner setup arranca una sesión normal de Claude usando esas palabras como prompt.

Ten en cuenta que el canal de instalación latest trae cada release apenas se publica, mientras que el canal stable, el cask de Homebrew y los repos estables de apt, dnf y apk vienen con más o menos una semana de retraso. Hoy, eso importa.

El camino rápido

Hay un setup guiado que crea el environment, levanta un runner local, confirma que se registró y escribe un cheat sheet en ./runner-setup/CHEAT-SHEET.md:

claude self-hosted-runner setup

Córrelo en una máquina donde hayas iniciado sesión con claude auth login bajo una cuenta con rol de Owner o admin. No funciona con API keys ni con proveedores de modelo de terceros, y necesita una sesión interactiva.

El camino manual

Cuatro pasos.

1. Crea el environment. En la página de administración Cloud environments, bajo Self-hosted environments, dale a New, ponle nombre y Create. En el segundo paso del wizard, Copy environment key. Ese es el environment secret, que se muestra una sola vez y no se puede recuperar después; expira 365 días desde su creación. El ID ccpool_... del environment queda visible en su diálogo de detalle.

2. Levanta un runner. Escribe el secret a un archivo sin que quede en el historial del shell:

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

Pega el valor, Enter, Ctrl-D. El umask del subshell deja el archivo legible solo por su dueño.

Después crea un base directory que el usuario del runner realmente pueda escribir, y levanta el runner:

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

Sin --base-dir el default es /workspace, que solo funciona si ya existe y es escribible, o si el runner corre como root. Este muerde: el runner no verifica el directorio al arrancar, así que un base dir mal configurado aparece después como sesiones que fallan apenas son tomadas, con EACCES, y no como un error de startup.

3. Verifica que se registró. El estado del environment pasa de No runners deployed a Healthy a los pocos segundos, y la pestaña Activity muestra el runner.

4. Enruta una sesión. Arranca una sesión en claude.ai/code y elige tu environment. El runner clona con las credenciales de git que el host ya tenga, así que para esta primera corrida elige un repo público o uno que el host ya pueda clonar. El runner loguea Picked up session <session-id> junto con su cuenta de sesiones activas y su capacidad, así que puedes confirmar desde la salida del propio host qué máquina tomó el trabajo.

Para mandar un follow-up desde cualquier máquina donde tengas sesión iniciada:

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

Tres comportamientos que te van a sorprender

El runner sale a propósito. Por defecto (--drain-grace-sec 0) sale apenas terminan sus sesiones activas, sin seguir haciendo polling. No es un crash — está diseñado así para que tu orquestador lo reinicie con un disco limpio. En el quickstart lo reinicias a mano; en producción lo corres bajo Kubernetes o equivalente.

Un runner atiende a un usuario a la vez. La primera sesión que toma un runner lo bloquea a la cuenta de ese usuario, y desde ahí corre solo sesiones de esa cuenta hasta el límite de --capacity. Eso es lo que evita que el código chequeado se mezcle entre usuarios, y tiene una consecuencia directa de dimensionamiento: el tamaño mínimo de tu flota es la cantidad de usuarios que esperas activos al mismo tiempo. --capacity compra paralelismo dentro de las sesiones de un usuario, no entre usuarios. Cuando hay sesiones encoladas con runners en línea, esta suele ser la razón.

El dispatch es a nivel organización. Cualquier miembro de tu organización de Anthropic puede mandar una sesión a cualquiera de sus environments — no hay control de acceso por environment en el dispatch. Trata cada runner host como alcanzable para ejecución de código por cualquier miembro de la organización, y no pongas datos ni credenciales en uno que algún miembro no debería poder leer.

Antes de apuntarlo a algo real

El quickstart es deliberadamente lo mínimo que funciona. El checklist de producción es otro documento, y varios de sus ítems no son obvios:

  • Containers efímeros por sesión, --capacity 1, sin reutilizar filesystem entre cuentas.
  • Nada de credenciales amplias en la imagen — una credencial horneada en una imagen de runner compartida queda disponible para cada sesión que corra cada miembro de la organización. Genera tokens de vida corta por sesión desde un wrapper script, o usa --use-anthropic-git-proxy, que clona con el token de vida corta de la propia sesión y no necesita ninguna credencial de git en la imagen.
  • Egress default-deny en tu propio borde de red. El código de la sesión lo dirige el modelo y Bash viene preaprobado por defecto, así que la salida por shell corre sin pedir permiso. El producto no puede hacerte cumplir esto.
  • Bloquea el endpoint de metadata del cloud (169.254.169.254) desde adentro del container de la sesión — las políticas a nivel de subred no interceptan tráfico link-local.
  • En una flota fija, el environment secret vive en cada runner host, donde el código de cualquier sesión puede leerlo. Los on-demand runners lo mantienen en un host orquestador que nunca corre código de usuario.

Y una limitación que pertenece al mismo párrafo que la pregunta de residencia: el tráfico de connectors sale de tu red. GitHub, Slack, Linear y el resto de los connectors de claude.ai se llaman desde el lado de Anthropic, no desde tu runner. Si el tráfico de herramientas tiene que quedarse dentro de tu borde, corre los equivalentes como MCP servers locales en tu imagen, o filtra los connectors con allowedMcpServers / deniedMcpServers.

¿Vale la pena?

Si tu equipo no usa cloud sessions, acá no hay nada para ti — las sesiones de terminal e IDE siempre corrieron en tu propia máquina. Si lo que quieres es tener una máquina siempre encendida manejada desde otros dispositivos, eso es Remote Control, y funciona también en Pro y Max.

El self-hosting es para equipos cuyos requisitos de red, tooling o compliance hacen que la ubicación de ejecución de la sesión sea una restricción real, y te cuesta una carga operativa concreta: tú construyes la imagen, tú corres la flota, tú controlas su egress. El resumen honesto es que mueve tu código y tu build, no tu conversación.

¿Y tú? ¿Correr el agente sobre tu propia infraestructura cambiaría la respuesta para un repo que hoy no meterías en una cloud session — o lo que realmente importa es que el prompt salga de la red?