Los entornos autohospedados están en versión beta pública en planes Team y Enterprise; un Propietario los habilita activando Allow self-hosted environments en la página de administración Cloud environments. Esta página es la referencia de banderas y métricas; consulte el inicio rápido para la configuración y Implementar en producción para las recetas de flota.
/workspace y ~/.claude asumen. Ejecute claude self-hosted-runner --help para la lista autorizada en su versión instalada.
Las series de métricas y algunos campos de API aún utilizan pool para lo que estas páginas llaman un entorno; ambos términos nombran lo mismo. El ID del entorno es el campo pool_id, con la forma ccpool_...: dondequiera que estas páginas muestren un identificador pool, nombra el entorno. Las banderas CLI y las variables de entorno lo escriben como environment, como --environment-secret-file; los nombres pool obsoletos aún funcionan, como describe la fila --environment-secret-file.
Flags CLI del runner
La mayoría de los flags tienen una variable de entorno correspondiente. Cuando ambos se establecen, el flag tiene precedencia. Los flags de duración toman minutos o segundos en la CLI, pero la variable de entorno emparejada siempre está en milisegundos, indicada por el sufijo_MS, y la columna Default muestra la unidad del flag: --exit-if-unused-min 10 es equivalente a SELF_HOSTED_RUNNER_IDLE_SHUTDOWN_MS=600000, y un valor de Helm como SELF_HOSTED_RUNNER_STARTUP_TIMEOUT_MS: "15" significa 15 milisegundos, no los 15 minutos predeterminados.
La mayoría de los flags de duración tienen un máximo, elegido para mantener cada timeout dentro del techo del temporizador de 32 bits del runtime de aproximadamente 24,85 días. Los flags
--*-min se limitan a 10080 minutos, 7 días; --drain-grace-sec a 604800 segundos, también 7 días; y --drain-wait-sec a 86400 segundos, 24 horas. --session-stop-grace-sec y --post-session-hook-timeout-sec no tienen límite. Exceder un límite se comporta diferente por superficie:
- Flag: el inicio falla con un error.
- Variable de entorno: el runner fija el valor al techo del temporizador en lugar de rechazarlo.
Tiempo de espera de inicio de la sesión
Si una sesión perdió su slot durante un turno como/code-review, actualiza el runner y el binario hijo a v2.1.309 o posterior. Desde v2.1.299 hasta v2.1.308, el runner liberaba una sesión, incluso a mitad de turno, una vez que pasaba el tiempo de espera de inicio sin un mensaje user o assistant.
Con --startup-timeout-min <n>, el runner libera el slot de una sesión cuando su proceso hijo no se ha inicializado dentro de los <n> minutos posteriores a la clonación. Durante un turno que comienza antes de que el proceso hijo se inicialice, la sesión conserva su slot hasta que pasan <n> minutos sin ninguna línea en el canal de actividad del proceso hijo. Una vez que el proceso hijo se inicializa, el runner descarta ese conteo y --release-idle-session-min rige la liberación. Para limitar una sesión cuyo proceso hijo está vivo pero atascado, establece --kill-session-after-min.
Listas de reglas del modo automático
--server-auto-mode-lists te permite decidir qué reglas del clasificador del modo automático procedentes de fuera del runner llegan a las sesiones de tus runners. El plano de control de Anthropic puede enviar listas de reglas con una sesión y pedir al runner que las aplique. Algunas entradas pueden ser reglas que escribió un administrador de tu organización. Las listas son environment, soft_deny y allow:
environment: una entrada puede hacer que el clasificador permita más, así como menos.soft_deny: una entrada bloquea una acción a menos que el usuario la haya pedido explícitamente o se aplique una excepción deallow.allow: las excepciones a las entradas desoft_deny.
no-allow: el valor predeterminado. Aplicaenvironmentysoft_denyy retieneallow. Una entrada deenvironmenttodavía puede hacer que el clasificador permita más, así que el valor predeterminado no descarta toda relajación.all: aplica las tres listas.none: no aplica ninguna de ellas. Eligenonepara descartar toda relajación proveniente de estas listas. También elimina las restricciones desoft_deny.
--log-level debug. Para cada sesión, el runner registra entonces una línea que contiene the server asked this runner to apply, o una que contiene the server did not ask this runner to apply the auto mode lists it sends.
Banderas de CLI del Orchestrator
El subcomandoself-hosted-runner orchestrator, que genera runners bajo demanda, acepta --api-url, --environment-secret-file, --hooks-dir, --health-port y --log-level con los mismos valores predeterminados que el runner y, donde la bandera del runner tiene uno, la misma variable de entorno, excepto que --hooks-dir es obligatorio y debe contener un hook spawn-runner. También toma sus propias banderas:
Banderas del conector SCM
El conector SCM no está disponible, así que deje las banderas en esta sección sin establecer. Si establece--scm-connector-host, la conexión no se abre y el orchestrator sigue reintentando. Los runners aún se inician a medida que las sesiones se encolan.
El conector es una conexión WebSocket permanente desde el orchestrator al plano de control de Anthropic. Está diseñado para permitir que los flujos previos a la sesión alojados, como el selector de repositorio y el resolutor de rama o ref, lleguen a un host de GitHub Enterprise Server que solo es enrutable desde dentro de su red. Consulte Requisitos de red en la página de GitHub Enterprise Server para ver lo que esos flujos necesitan.
En cada intento de conexión, el orchestrator envía su secreto de entorno existente, y reintenta automáticamente con retroceso exponencial, limitado a 30 segundos más jitter.
Configuración solo de variables de entorno
Estas configuraciones del runner se leen solo del entorno y cubren comportamiento que la mayoría de los despliegues dejan en el predeterminado:Telemetría
Los hijos de sesión envían telemetría operacional a Anthropic a menos que la desactive. No se envía código ni contenido del repositorio. Establezca variables de telemetría en el proceso del runner; el runner las reafirma después de aplicar variables de entorno proporcionadas por el servidor, por lo que la configuración del operador siempre tiene precedencia. Un control es específico para entornos autohospedados:CLAUDE_CODE_BYOC_ENABLE_DATADOG=1 se suscribe a métricas operacionales de Datadog, que están desactivadas de forma predeterminada en entornos autohospedados. Los controles generales de telemetría de Claude Code, DISABLE_TELEMETRY, DO_NOT_TRACK, DISABLE_ERROR_REPORTING, y CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, se aplican a hijos de sesión como se documenta en la referencia de variables de entorno. DISABLE_GROWTHBOOK está relacionado pero es diferente: establecer DISABLE_GROWTHBOOK=1 desactiva la búsqueda de banderas de características, y la telemetría permanece activada a menos que DISABLE_TELEMETRY también esté establecido.
CLAUDE_CODE_ENABLE_TELEMETRY no está relacionado: habilita la exportación de OpenTelemetry a su propio recopilador, como se describe en Monitoring, y no controla la analítica de Anthropic.
Punto final de salud
El runner sirveGET /healthz en el puerto de salud configurado. La respuesta es 200 OK siempre que el proceso esté vivo, sea cual sea el estado del bucle de sondeo, por lo que un sondeo HTTP en este punto final detecta solo un proceso muerto. El cuerpo JSON describe el estado actual:
last_poll_age_ms como una señal de vivacidad en sondeos personalizados; un valor que crece sin límites indica que el bucle de sondeo está atascado. Tanto last_poll_at como last_poll_age_ms son null hasta que se completa el primer sondeo.
El /healthz propio del orquestador, en su puerto de salud, siempre devuelve 200. El cuerpo lleva un campo connected que reporta si el sondeo más reciente tuvo éxito, más conteos de cola de generación por estado en queue_counts. Para ver por qué connected es false, lee el campo de nivel superior last_error, que cada sondeo exitoso restablece a null. Basa la preparación y las alertas en connected en lugar del código de estado.
Cuando el conector SCM está configurado, el cuerpo /healthz del orquestador también lleva scm_connector_connected y un objeto scm_connector con connected, last_connected_at, last_error, reconnects, y requests_forwarded. Ambos campos son null cuando --scm-connector-host no está establecido.
Métricas de Prometheus
Cada runner sirve métricas de Prometheus enGET /metrics en el mismo puerto que /healthz. Series clave:
El orquestador sirve sus propias series en
GET /metrics en el mismo puerto que su /healthz:
Para escalado automático, elija la serie que coincida con su estilo de escalado y ciérrela antes de que se alimente al escalador:
- Escalado de profundidad de cola: alimente
claude_code_self_hosted_orchestrator_pool_pending_sessionsen su escalador HPA o KEDA, noqueue_pending_sessions. - Escalado de capacidad: escale en la relación de
active_sessionsdel runner acapacity. - Cierre en
connected: filtre la consulta conclaude_code_self_hosted_orchestrator_connected == 1por instancia, para que el valor obsoleto de una réplica desconectada no se alimente al escalador.
ignoreNullValues: "true" predeterminado lee el resultado vacío como cero y escala hacia adentro; establezca ignoreNullValues: "false" en ScaledObject, opcionalmente con un piso de réplica fallback.
El siguiente PodMonitor del Operador de Prometheus cubre ambos procesos. Selecciona pods por la etiqueta app.kubernetes.io/part-of: claude-code-self-hosted-runner y el puerto health nombrado que la receta de Kubernetes establece; ajuste los espacios de nombres para que coincidan con su despliegue:
Reglas de alerta de ejemplo
Estas reglas de alerta de ejemplo son un punto de partida; ajuste los umbrales para el tamaño de su flota:Alertar sobre runners perdidos y sesiones en espera
En una flota fija, cargaClaudeRunnersBelowFloor. Con runners bajo demanda, carga ClaudeOrchestratorSessionsWaiting y ClaudeOrchestratorQueueWaitHigh en su lugar.
Alertar cuando una flota fija pierde runners
ClaudeRunnersBelowFloor se dispara cuando quedan menos runners registrados y raspados que el mínimo durante 10 minutos:
- Mínimo: establece el
2enexpren aproximadamente la mitad de tu número de réplicas, redondeado hacia arriba. Con tres réplicas mantén2, y la alerta se dispara cuando queda un runner o ninguno. - Espacio de nombres: reemplaza
claude-runnersen el matcher y enlabels, y copia la alerta para cada espacio de nombres adicional. Si tus destinos no tienen una etiquetanamespace, elimina el matcher y la etiqueta, o la alerta lee 0 y se dispara. ClaudeRunnerPollStaleyClaudeRunnerPollErrors: mantenlas cargadas desde las reglas de alerta de ejemplo, porqueClaudeRunnersBelowFloorsigue contando un runner que no puede sondear
Alertar cuando las sesiones esperan runners bajo demanda
ClaudeOrchestratorSessionsWaiting se dispara cuando el número de sesiones que esperan un runner se mantiene por encima de 0 durante 10 minutos. ClaudeOrchestratorQueueWaitHigh se dispara cuando más del 1% de las esperas en cola de los últimos 10 minutos superaron los 160 segundos, y eso se mantiene durante 5 minutos:
- Umbral: si siempre hay alguna sesión esperando, sube el
> 0enClaudeOrchestratorSessionsWaitingpor encima del número que sueles ver ClaudeOrchestratorDisconnected: mantenla cargada desde las reglas de alerta de ejemplo, porqueClaudeOrchestratorSessionsWaitingdeja de dispararse unos 2 minutos después de que se desconecta el último orquestador del espacio de nombres
Pasar a través de métricas de hijo de sesión
Cada sesión se ejecuta en su propio proceso hijo con sus propias métricas de OpenTelemetry; en--capacity superior a uno, el runner reescribe cómo se exponen esas métricas del hijo. Establecer OTEL_METRICS_EXPORTER=prometheus en el host del runner y CLAUDE_CODE_ENABLE_TELEMETRY=1 en el entorno de la sesión, por ejemplo desde su script de envoltura o el entorno propio del runner, que las sesiones heredan, re-expone los instrumentos de contador y indicador de cada hijo en el punto final /metrics propio del runner, junto con la serie del runner. El runner reescribe el exportador del hijo para empujar sobre OTLP a un receptor solo de loopback en el puerto de salud, etiqueta cada serie con etiquetas session_id y client_platform, y desaloja la serie de una sesión cuando esa sesión termina. Los histogramas no pasan, y una métrica del hijo cuyo nombre entraría en conflicto con el prefijo propio del runner se descarta.
En el --capacity 1 predeterminado, la reescritura no se aplica: el hijo de la sesión vincula su propio punto final de Prometheus en el puerto 9464 como de costumbre.
Unir las métricas de una sesión con las del runner
Para ver cuánto han costado las sesiones inactivas, une la métricaclaude_code_self_hosted_runner_session_idle_seconds del runner con la métrica de costo de Claude Code por ccr_session_id. La métrica del runner no lleva esa etiqueta, así que agrégasela con label_replace, como en esta consulta:
claude_code_cost_usage_total en la consulta. La consulta funciona con cualquier --capacity.
session_id: en el puerto 9464, esa etiqueta en las métricas de Claude Code contiene elsession.idpropio de Claude Code, que no coincide con ninguna serie del runner. Una unión por ella no devuelve nada, así que haz la unión porccr_session_id.- Las métricas de Claude Code no tienen
ccr_session_id: comprueba queOTEL_METRICS_INCLUDE_SESSION_IDno esté establecido enfalse
Semántica del contador del ciclo de vida de la sesión
Los contadoressessions_started_total, sessions_completed_total, sessions_failed_total, y sessions_interrupted_total clasifican cada sesión por cómo terminó. Cada hijo de sesión generado incrementa sessions_started_total en el tiempo de generación, y exactamente uno de los otros tres incrementa al salir, por lo que sessions_started_total menos la suma de los otros tres es igual al número de hijos de sesión actualmente en ejecución.
completed: la sesión terminó limpiamente. Esto cubre el hijo saliendo por su cuenta con código0, la sesión siendo archivada o eliminada mientras el hijo aún estaba conectado, y el runner devolviendo el slot limpiamente: liberar la sesión en el timeout de inactividad, en el tiempo de retiro o en el límite--kill-session-after-min; un timeout de inicio; o una desasignación del lado del servidor que el bucle de sondeo notó antes de que el hijo saliera. Incrementasessions_completed_total.failed: el hijo salió por su cuenta con un código distinto de cero, ya sea un bloqueo o una falla de configuración después de la generación. Incrementasessions_failed_total.interrupted: el runner terminó el hijo por una razón operacional que no es ni un éxito de sesión ni una falla del runner, como un drenaje, o terminar una sesión que aún estaba en el runner cuando la ventana de graciaSELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MSdespués de su límite--kill-session-after-minterminó. Un reinicio rodante de Kubernetes enviandoSIGTERMes un ejemplo de un drenaje. Incrementasessions_interrupted_total.
--kill-session-after-min y la contaba en sessions_interrupted_total.
El CLAUDE_RUNNER_EXIT_REASON del hook post-session clasifica los traspasos limpios de manera diferente. El hook los reporta como interrupted, porque el runner detuvo el hijo: una liberación, un agotamiento del tiempo de espera de inicio, una desasignación del servidor, y un archivado o eliminación que el sondeo notó primero. Estos contadores registran esos mismos eventos como completed, porque el slot fue devuelto limpiamente.
Si reconcilia recibos de hook contra sessions_completed_total directamente, subestima completaciones. Use el hook para garantías por sesión y los contadores para tasas agregadas.
En un entorno de un solo disparo, --capacity 1 con el --drain-grace-sec 0 predeterminado, cada proceso del runner sale momentos después de que su única sesión termina. sessions_completed_total, sessions_failed_total, y sessions_interrupted_total incrementan solo al final de la sesión, justo antes de esa salida, por lo que un raspado de Prometheus cada 15 a 60 segundos rara vez detecta el incremento antes de que la serie del runner desaparezca; estos tres contadores de final de sesión son los contadores terminales a los que se refiere el resto de esta sección. sessions_started_total incrementa en la generación y permanece visible durante la vida de la sesión, por lo que se muestra de forma confiable, pero en un entorno de un solo disparo se lee más cerca de “sesiones actualmente en ejecución” que un recuento acumulativo.
Use la serie en esta tabla para el objetivo correspondiente en lugar de los contadores terminales:
Las filas
orchestrator_* existen solo en entornos que ejecutan el orquestador bajo demanda. En una flota fija cuyos runners sobreviven a sus sesiones, con --drain-grace-sec superior a 0, use sum(rate(claude_code_self_hosted_runner_sessions_started_total[5m])) para throughput; en una flota de un solo disparo esa serie tiene el mismo problema de ventana de raspado que los contadores terminales, así que confíe en el recuento de sesiones en cola en su lugar. Verifique el backlog en la pestaña Activity del entorno, en la página de administración Cloud environments: los runners no exportan una serie de profundidad de cola.
Para reportes de resultado por sesión, use el hook post-session en su lugar: se dispara en cada final de sesión donde se generó un proceso hijo, aparte de la terminación abrupta del runner como una preemción de VM, según el contrato propio del hook.
Qué sigue
- Self-hosted environments: el entorno, runner, y modelo de sesión; el quickstart y Deploy to production contienen configuración y operaciones
- Customize sessions: scripts de envoltura, hooks de ciclo de vida, y runners bajo demanda
- Verify session identity: el token de sesión, sus reclamaciones, y cómo verificarlo