SpyBara
Go Premium

self-hosted-environments-reference.md 2026-09-11 23:01 UTC to 2026-09-12 03:02 UTC

This page contains 343 additions and 0 deletions.

2026
Sat 12 03:02 Fri 18 23:58 Sat 19 23:57

Referencia de entornos autohospedados

Referencia completa para el ejecutor y orquestador autohospedados: banderas CLI, variables de entorno y métricas de Prometheus.

Esta página es la referencia para los dos procesos que ejecuta en un entorno autohospedado: el ejecutor, que ejecuta sesiones en la nube de Claude Code en sus hosts, y el orquestador de escalado automático opcional, que inicia ejecutores a medida que las sesiones se ponen en cola. Cada uno tiene su propia tabla de banderas. Ambos se ejecutan en hosts Linux o macOS, que los valores predeterminados como /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.

Flag Env var Default Description
--api-url <url> none https://api.anthropic.com URL base de API. Anule solo para pruebas.
--base-dir <path> SELF_HOSTED_RUNNER_BASE_DIR /workspace; ninguno en Windows Directorio para checkouts de repositorio y directorios de trabajo por sesión. El runner necesita acceso de escritura a esta ruta o su padre. El runner crea el directorio al iniciar y sale con cannot create or write to base directory cuando no puede crearlo o escribir en él. Antes de v2.1.225, el runner creaba el directorio cuando la primera sesión comenzaba, por lo que una ruta inutilizable fallaba en sesiones en lugar de al iniciar. En Windows, que no es un host de runner compatible, no hay predeterminado: el runner sale al iniciar a menos que pase el flag o establezca la variable. Use el mismo valor en cada runner en un entorno. Consulte Keep the base directory and capacity identical across runners.
--capacity <n> none 1 Máximo de sesiones concurrentes que este runner maneja. Todas las sesiones pertenecen al mismo owner bloqueado. Use el mismo valor en cada runner en un entorno; consulte Keep the base directory and capacity identical across runners.
--client-label <label> SELF_HOSTED_RUNNER_CLIENT_LABEL el hostname del host Etiquete el runner que envía cuando se registra. El runner también lo reporta como la etiqueta client_label de claude_code_self_hosted_runner_info. Requiere Claude Code v2.1.248 o posterior.
--configure-git SELF_HOSTED_RUNNER_CONFIGURE_GIT=1 off Al iniciar, escriba la identidad global de git, habilite la firma de commits de Anthropic, active la negociación de push de git e instale hooks de commit que agreguen un tráiler Co-authored-by:. La negociación de push requiere Claude Code v2.1.257 o posterior. Consulte Configure git.
--confine-repo-settings <mode> SELF_HOSTED_RUNNER_CONFINE_REPO_SETTINGS warn Establece el modo del guard que marca una sesión cuando la configuración comprometida de un repositorio intenta otorgar acceso de escritura o lectura fuera del workspace de esa sesión, establecer variables de entorno o anular la postura de sandbox o hooks del operador, como sandbox.enabled: false o disableAllHooks. El warn predeterminado registra la violación e inicia la sesión de todas formas, enforce rechaza la sesión, y off desactiva el escaneo. Consulte Harden your deployment.
--debug-token-dir <path> SELF_HOSTED_RUNNER_DEBUG_TOKEN_DIR unset Escriba tokens en vivo en disco para inspección. Solo depuración; no use en producción.
--defer-shutdown-max-min <n> SELF_HOSTED_RUNNER_DEFER_SHUTDOWN_MAX_MS 0 En el primer SIGTERM o SIGINT, continúe sirviendo las sesiones ya adjuntas en lugar de drenarlas, luego libere lo que aún esté adjunto N minutos después y salga. Aumente el timeout de parada de su host antes de establecer esto. Consulte Defer the drain past the first signal. 0 desactiva. Requiere Claude Code v2.1.238 o posterior.
--drain-grace-sec <n> SELF_HOSTED_RUNNER_DRAIN_GRACE_MS 0 Hasta que el runner reciba una señal de apagado o alcance su tiempo de retiro, controla cuándo sale el runner después de que sus sesiones activas terminen: 0 sale inmediatamente sin sondear más, y un valor positivo mantiene el runner vivo y re-sondea la cola del owner bloqueado durante esos muchos segundos primero, al costo del aislamiento de contenedor por sesión descrito en la sección de endurecimiento. Después de una primera señal que difirió con --defer-shutdown-max-min, el runner sale tan pronto como no tenga sesiones, sin importar lo que establezca aquí.
--drain-wait-sec <n> SELF_HOSTED_RUNNER_DRAIN_WAIT_MS 0 Una vez que comienza el drenaje, que es en SIGTERM a menos que establezca --defer-shutdown-max-min, espere hasta N segundos para que el turno en vuelo de cada sesión y las tareas de fondo terminen antes de terminar el hijo. Durante esta espera, el runner cuenta una tarea de fondo que acaba de terminar como aún en ejecución hasta que comienza el turno de seguimiento que lee su resultado, durante como máximo la ventana SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS.
--environment-secret-file <path> SELF_HOSTED_RUNNER_ENVIRONMENT_SECRET required Ruta a un archivo que contiene el secreto del entorno, o, para runners generados por el orquestador, el JWT de orden de trabajo de un solo uso. SELF_HOSTED_RUNNER_ENVIRONMENT_SECRET lleva el valor secreto directamente, no una ruta de archivo. El flag más antiguo --pool-secret-file y la variable SELF_HOSTED_RUNNER_POOL_SECRET aún funcionan e imprimen un aviso de deprecación a stderr; las compilaciones de runner del programa de vista previa más antiguas que 2.1.216 solo reconocen esos nombres más antiguos.
--exec-path <path> SELF_HOSTED_RUNNER_EXEC_PATH own binary Binario o script de envoltura para generar para cada sesión. Consulte Wrapper scripts.
--exit-if-unused-min <n> SELF_HOSTED_RUNNER_IDLE_SHUTDOWN_MS 0 Salga después de N minutos de sondeo sin trabajo nunca asignado, para escala hacia abajo del autoscaler. 0 desactiva.
--git-host-rewrite <from>=<to> none unset Reescriba las URLs de origen https://<from>/... a https://<to>/... antes de clonar, para DNS de horizonte dividido. Repetible; solo flag.
--git-ssh-rewrite <host> none unset Reescriba las URLs de origen https://<host>/... a git@<host>:... antes de clonar, para hosts git solo SSH. Repetible; solo flag.
--health-port <port> SELF_HOSTED_RUNNER_HEALTH_PORT 8080 Puerto para el listener /healthz y /metrics. Establezca 0 para desactivar.
--hooks-dir <path> SELF_HOSTED_RUNNER_HOOKS_DIR unset Directorio de scripts de hook de ciclo de vida. Consulte Lifecycle hooks.
--kill-session-after-min <n> SELF_HOSTED_RUNNER_MAX_LIFETIME_MS 0 Limite una sesión a N minutos de reloj de pared, como límite de seguridad para sesiones atascadas. En v2.1.260 o posterior, el runner libera una sesión que alcanza el límite para que pueda reanudarse en el siguiente mensaje de su usuario, y la termina solo si aún está en el runner cuando termina la ventana de gracia SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS. Antes de v2.1.260, el runner terminaba la sesión en el límite. Consulte Some sessions don't count as idle para los detalles y cómo elegir un valor. 0 desactiva.
--lock-to-account <id> SELF_HOSTED_RUNNER_LOCK_TO_ACCOUNT unset Pre-bloquee el runner a una cuenta específica al iniciar en lugar de bloquear en la primera sesión. Acepta una dirección de correo electrónico o un ID user_... en la organización del entorno. Un runner pre-bloqueado nunca recoge sesiones del canal Claude Tag, que no tienen cuenta.
--log-file <path> SELF_HOSTED_RUNNER_LOG_FILE unset Espeje los logs del runner a un archivo además de stdout y stderr, creado con permisos 0600. Requerido para que self-hosted-runner doctor rastree logs localmente.
--log-level <level> none info info o debug
--post-session-hook-timeout-sec <n> SELF_HOSTED_RUNNER_POST_SESSION_HOOK_TIMEOUT_MS 60 Presupuesto para el hook post-session en cada final de sesión, incluido el apagado del runner
--proxy-authorization-command <command> SELF_HOSTED_RUNNER_PROXY_AUTHORIZATION_COMMAND unset Comando de shell que el runner ejecuta para cada conexión a su proxy de salida, usando su stdout recortado como el valor del encabezado Proxy-Authorization. Requiere HTTPS_PROXY o HTTP_PROXY, y no se puede combinar con --proxy-authorization-file. Consulte Authenticate to an egress proxy. Requiere Claude Code v2.1.238 o posterior.
--proxy-authorization-file <path> SELF_HOSTED_RUNNER_PROXY_AUTHORIZATION_FILE unset Archivo que el runner lee para cada conexión a su proxy de salida, usando su contenido recortado como el valor del encabezado Proxy-Authorization. Use este flag para un token que otro proceso rota en su lugar. Lleva los mismos requisitos que --proxy-authorization-command, y no se puede combinar con él. Consulte Authenticate to an egress proxy. Requiere Claude Code v2.1.238 o posterior.
--push-outcome-on-release SELF_HOSTED_RUNNER_PUSH_OUTCOME_ON_RELEASE off En un final de sesión iniciado por el runner como un drenaje o liberación por inactividad, empuje las ramas de resultado rastreadas a origin antes de eliminar el workspace, para que los commits en vuelo sobrevivan a un reinicio. Mejor esfuerzo; agrega 30 segundos al presupuesto de apagado, y requiere git 2.29 o más nuevo para reanudar desde la rama empujada. Restrinja el acceso de push a refs claude/* antes de habilitar; consulte Resumed sessions lose unpushed work. Los repositorios verificados a través de un hook de ciclo de vida checkout no se empujan; tome una instantánea de esos desde el hook post-session en su lugar.
--release-idle-session-min <n> SELF_HOSTED_RUNNER_SESSION_IDLE_MS 0 Libere un slot de sesión después de N minutos de inactividad una vez que un turno termina o la sesión espera la acción del usuario. Una sesión que aún está a mitad de turno, incluida una que sostiene una tarea de fondo que nunca termina o una aprobación solicitada desde dentro de una llamada de herramienta en ejecución, no cuenta como inactiva; empareje con --kill-session-after-min como el tope duro. Después de que la tarea de fondo de una sesión termina, el runner considera la sesión ocupada hasta que comienza el turno de seguimiento que lee el resultado, durante como máximo la ventana SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS. Hasta que el runner reciba una señal de apagado o alcance su tiempo de retiro, una liberación que deja el runner sin sesiones activas inicia la misma ruta de salida que un drenaje normal, gobernado por --drain-grace-sec. Después de una primera señal que difirió con --defer-shutdown-max-min, el runner sale tan pronto como una liberación lo deja sin sesiones. 0 desactiva.
--retire-at <epoch-seconds> SELF_HOSTED_RUNNER_RETIRE_AT unset Retire el runner en una marca de tiempo Unix absoluta en segundos, para infraestructura que mata el runner en un tiempo conocido; Runner lifecycle describe la secuencia de liberación y cómo dimensionar el margen. Los valores antes de 2001 o después del año 5138 son rechazados por el flag e ignorados por la variable de entorno.
--session-stop-grace-sec <n> SELF_HOSTED_RUNNER_SESSION_STOP_GRACE_MS 5 Cuánto tiempo esperar a que el proceso de Claude salga limpiamente después de que una sesión termina, antes de matarlo por la fuerza. Aumente el valor si los hooks SessionEnd propios del hijo necesitan más tiempo.
--startup-timeout-min <n> SELF_HOSTED_RUNNER_STARTUP_TIMEOUT_MS 15 Libere un slot de sesión si el hijo no ha señalado que se inicializó dentro de N minutos de generación. Borrado por la señal de inicialización del hijo en el canal de actividad, no por salida ordinaria, después de lo cual --release-idle-session-min toma el control. 0 desactiva.
--trust-workspace [bool] SELF_HOSTED_RUNNER_TRUST_WORKSPACE on Semilla de confianza persistida para las rutas del repositorio de cada sesión para que permissions.allow y additionalDirectories comprometidos en el repositorio sean honrados. Establezca false para descartar concesiones de permisos comprometidas en el repositorio y configure reglas de permiso en la settings.json de la configuración del host en su lugar; la configuración sandbox.* comprometida en el repositorio aún se aplica de cualquier forma, que es por qué el guard de configuración de repositorio los escanea independientemente de este flag.
--use-anthropic-git-proxy CLAUDE_RUNNER_USE_GIT_PROXY=1 off Clone a través del proxy de git de Anthropic en lugar de autenticación de git administrada por el cliente. Requiere --capacity 1 y git 2.32 o más nuevo; el runner se niega a iniciar de otra forma. Supersede los flags de reescritura.

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.

Flags CLI del orquestador

El subcomando self-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 el flag del runner tiene uno, la misma variable de entorno, excepto que --hooks-dir es requerido y debe contener un hook spawn-runner. También toma sus propios flags:

Flag Default Description
--hook-concurrency <n> 4 Máximo de hooks spawn-runner ejecutándose en paralelo. También limita cuántas solicitudes de generación se reclaman por sondeo.
--hook-timeout <sec> 60 Termine el árbol de procesos del hook después de estos muchos segundos. El timeout más su gracia de muerte de 5 segundos debe mantenerse por debajo de --expected-spawn-seconds; el orquestador lo aplica al iniciar.
--expected-spawn-seconds <sec> 120 Tiempo de arranque p99 esperado para runners generados, en el rango aplicado por el servidor de 10 a 3600. Enviado en cada sondeo como el arrendamiento del lado del servidor; si ningún runner se registra antes de que transcurra, la sesión se re-ofrece con un ID de orden nuevo. Todas las réplicas deben compartir este valor.
--min-idle <n> 0 Mantenga al menos N slots de sesión inactivos libres generando runners de espera de forma proactiva. 0 desactiva el precalentamiento. Empareje con el --exit-if-unused-min del runner para que los runners de espera excedentes se reclamen a sí mismos.
--debug-dir <path> unset Escriba la orden de trabajo y stderr del hook de cada solicitud de generación en disco. Solo depuración; nunca establezca en producción.

Flags del conector SCM

El orquestador puede mantener una conexión WebSocket permanente al plano de control de Anthropic para que los flujos previos a la sesión alojados, como el selector de repositorio y el resolutor de rama o ref, puedan alcanzar un host de GitHub Enterprise Server que solo es enrutable desde dentro de su red. El conector permanece apagado a menos que establezca --scm-connector-host.

Flag Default Description
--scm-connector-host <host[:port]> unset Nombre de host de GitHub Enterprise Server para reenviar solicitudes. El puerto predeterminado es 443. Establecer este flag habilita el conector.
--scm-connector-id <n> required with --scm-connector-host El ID numérico de la conexión de GitHub Enterprise Server de su organización. Póngase en contacto con su equipo de cuenta de Anthropic para el valor cuando habilite el conector.
--scm-connector-provider <slug> ghe Segmento de ruta que identifica el proveedor, coincidiendo con ^[a-z0-9-]{1,32}$.
--scm-connector-ca-file <path> unset Paquete de CA adicional, en formato PEM, para conexiones TLS al host de GitHub Enterprise Server.
--scm-connector-host-rewrite <from>=<to_host:to_port> unset Solo para pruebas de extremo a extremo: redirige la conexión TCP mientras mantiene el encabezado Host y TLS SNI como --scm-connector-host.

El conector se autentica con el secreto del entorno existente del orquestador y se reconecta automáticamente: con retroceso exponencial en una conexión caída, o un retraso fijo de 30 segundos cuando el plano de control cierra la conexión porque otra réplica del orquestador ya la sostiene.

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:

Env var Default Description
SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS 30000 Cuánto tiempo el runner considera una sesión ocupada después de que una tarea de fondo termina mientras el turno de seguimiento que lee el resultado no ha comenzado. Las filas --drain-wait-sec y --release-idle-session-min describen dónde se aplica la retención en drenaje y liberación por inactividad, y Runner lifecycle describe dónde se aplica en retiro --retire-at. 0 o un valor inutilizable vuelve al predeterminado, por lo que la retención no se puede desactivar. Requiere Claude Code v2.1.228 o posterior.
SELF_HOSTED_RUNNER_HOST_CONFIG_DIR ~/.claude Directorio capturado en la instantánea de inicio del runner y sembrado en el CLAUDE_CONFIG_DIR de cada sesión; los cambios en disco se aplican después de un reinicio del runner. Establecer la variable también mueve dónde el runner lee .claude.json para siembra de MCP, por lo que establecerlo, incluso a su propio predeterminado, reubica esa búsqueda; apunte a un directorio vacío para desactivar completamente la siembra.
SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS 900000 Cuánto tiempo el runner espera después de que una sesión alcanza su límite --kill-session-after-min, para que un turno en ejecución termine o se complete la liberación, antes de terminar la sesión
SELF_HOSTED_RUNNER_SIGKILL_GRACE_MS 30000 Cuánto tiempo el runner espera a que el SO entregue SIGKILL a un hijo atascado en E/S no interrumpible antes de salir él mismo. Limitado a --post-session-hook-timeout-sec más 15 segundos, y 30 más cuando --push-outcome-on-release está establecido, por lo que el mínimo efectivo es 75 segundos en valores predeterminados.
CLAUDE_RUNNER_FETCH_DEPTH 50 Profundidad de búsqueda de git para clones frescos. Establezca un entero positivo, o full o 0 para una búsqueda completa. Los repositorios ya presentes en el workspace mantienen su profundidad existente.
CLAUDE_RUNNER_SKIP_GIT_VERIFY unset Cuando es 1, omita la verificación de presencia .git después de que se ejecute un hook checkout. Establezca esto cuando su hook materializa una fuente que no es git.
FORCE_AUTOUPDATE_PLUGINS unset Cuando es 1, permita que los mercados de plugins se actualicen automáticamente aunque el binario esté fijado
CLAUDE_CODE_DISABLE_ARTIFACT unset Cuando es 1, desactive la herramienta Artifact en sesiones independientemente de la configuración de administración de la organización, y elimine el requisito de salida *.frame.claudeusercontent.com

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 sirve GET /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:

{
  "status": "ok",
  "runner_id": "ccrunner_...",
  "active_sessions": 2,
  "last_poll_at": "2026-03-31T18:04:11.220Z",
  "last_poll_age_ms": 842
}

Use 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 orquestador sirve su propio /healthz en su puerto de salud. Su punto final siempre devuelve 200, y el cuerpo lleva un campo connected reportando si el sondeo más reciente tuvo éxito, más conteos de cola de generación por estado en queue_counts. Cierre la preparación y 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 en GET /metrics en el mismo puerto que /healthz. Series clave:

Series Notes
claude_code_self_hosted_runner_info{runner_id,version,client_label} Siempre 1; útil para inventario de flota y detección de desviación de versión
claude_code_self_hosted_runner_capacity --capacity configurado
claude_code_self_hosted_runner_active_sessions Sesiones actualmente en ejecución
claude_code_self_hosted_runner_locked_account{email} Presente una vez que el runner se ha bloqueado a un usuario y se ha emitido un token de sesión que lleva una reclamación act.email. La serie está ausente en un runner bloqueado a un agente de Claude Tag, cuyos tokens de sesión no llevan act.email. El valor de la etiqueta es el correo electrónico de la cuenta; si su almacén de métricas es ampliamente legible, suelte o hash la etiqueta en el tiempo de raspado, por ejemplo con metric_relabel_configs de Prometheus.
claude_code_self_hosted_runner_last_poll_age_seconds Segundos desde el último sondeo exitoso. Alerte si es superior a 60.
claude_code_self_hosted_runner_poll_errors_total{error_kind} Fallos acumulativos de PollWork por tipo: transport, timeout, 5xx, 429, o 4xx. Las cinco series están presentes desde el inicio del proceso; alerte en rate(...[5m]) > 0.
claude_code_self_hosted_runner_sessions_started_total{client_platform} Procesos hijo de sesión generados durante la vida útil del runner, una serie por origen de sesión como web_claude_ai, ios, android, desktop_app, o claude_code_cli, o unknown cuando el servidor no envió uno. Las sesiones de Slack llevan claude_in_slack o claude-in-slack dependiendo de qué integración de Slack las creó, así que coincida ambas con un selector de regex como {client_platform=~"claude[-_]in[-_]slack"}. Use sum() para el total de la flota.
claude_code_self_hosted_runner_sessions_completed_total{client_platform} Sesiones que terminaron limpiamente, etiquetadas de la misma forma. Más amplio que una salida limpia simple: consulte semántica del contador del ciclo de vida de la sesión para lo que cuenta.
claude_code_self_hosted_runner_sessions_failed_total{client_platform} Sesiones que terminaron en fallo, etiquetadas de la misma forma. Misma advertencia: consulte semántica del contador del ciclo de vida de la sesión.
claude_code_self_hosted_runner_sessions_interrupted_total{client_platform} Sesiones que el runner terminó por una razón operacional en lugar de un resultado de sesión, etiquetadas de la misma forma. Consulte semántica del contador del ciclo de vida de la sesión.
claude_code_self_hosted_runner_initializing_sessions Sesiones actualmente en la fase de inicialización, desde la asignación hasta el evento de inicialización del hijo
claude_code_self_hosted_runner_session_init_duration_seconds Histograma de duraciones de inicialización de sesión
claude_code_self_hosted_runner_session_init_errors_total Sesiones que fallaron antes de alcanzar la inicialización: una falla de hook de checkout, preparación de git, problema de token, o un bloqueo previo a la inicialización del hijo
claude_code_self_hosted_runner_session_start_hook_errors_total Hooks SessionStart que reportaron un resultado de error, uno por ejecución de hook fallida
claude_code_self_hosted_runner_session_idle_seconds{session_id,client_platform} Indicador por sesión de segundos desde que la sesión se volvió inactiva. Útil para terminar sesiones atascadas en un aviso de permiso sin respuesta.

El orquestador sirve sus propias series en GET /metrics en el mismo puerto que su /healthz:

Series Notes
claude_code_self_hosted_orchestrator_info{version,pool_id,orchestrator_uuid,hostname} Siempre 1
claude_code_self_hosted_orchestrator_connected 1 cuando el sondeo más reciente tuvo éxito; cae a 0 después de cualquier sondeo fallido, sea cual sea el tipo de fallo
claude_code_self_hosted_orchestrator_last_poll_age_seconds Segundos desde el último intento de sondeo, éxito o fallo, a diferencia de la métrica con el mismo nombre del runner, que mide desde el último éxito; empareje con connected para detectar sondeos fallidos. El bucle de sondeo del orquestador espera en la ejecución del hook, así que alerte por encima de --hook-timeout más un margen, alrededor de 90 segundos en valores predeterminados, en lugar de un 60 plano.
claude_code_self_hosted_orchestrator_poll_errors_total{error_kind} Fallos acumulativos de PollSpawnHints por tipo: transport, timeout, 5xx, 429, o 4xx. Las cinco series están presentes desde el inicio del proceso; alerte en rate(...[5m]) > 0.
claude_code_self_hosted_orchestrator_queue_pending_sessions Solicitudes de generación reclamables ahora mismo
claude_code_self_hosted_orchestrator_queue_backing_off_sessions Solicitudes de generación en retroceso de reintento después de una falla de hook reintentable
claude_code_self_hosted_orchestrator_queue_circuit_broken_sessions Solicitudes de generación bloqueadas hasta que un Owner las reintente desde la pestaña Activity del entorno; alerte si es superior a cero
claude_code_self_hosted_orchestrator_pool_pending_sessions Total de sesiones esperando un runner para este entorno. Agregado de todo el entorno, idéntico en cada instancia del orquestador: use MAX en lugar de SUM entre instancias.
claude_code_self_hosted_orchestrator_pool_active_sessions Sesiones actualmente asignadas a un runner vivo en este entorno. Agregado de todo el entorno, idéntico en cada instancia del orquestador: use MAX en lugar de SUM entre instancias.
claude_code_self_hosted_orchestrator_spawn_hooks_total{result} Resultados acumulativos del hook spawn-runner: ok, retryable, non_retryable. Cuenta invocaciones de hook del orquestador, no hijos de sesión que los runners generan: no comparable a sessions_started_total, ya que la capacidad superior a uno, grupos cálidos, y runners generados nuevamente para la misma sesión divergen los dos.
claude_code_self_hosted_orchestrator_spawn_hook_duration_seconds Histograma de duraciones de hook
claude_code_self_hosted_orchestrator_warm_hints_dispatched_total Solicitudes de generación de espera despachadas desde el inicio del proceso
claude_code_self_hosted_orchestrator_session_queue_wait_seconds Histograma de segundos que cada sesión esperó en la cola antes de que el orquestador la reclamara para generación, registrado desde la marca de tiempo de espera en cola que el plano de control envía con la solicitud de generación de cada sesión. Use para alertas de tiempo de cola p50/p99. Los generadores de precalentamiento no se muestrean.
claude_code_self_hosted_orchestrator_clock_skew_seconds Sesgo de reloj local menos servidor; diagnóstico, presente una vez medido
claude_code_self_hosted_orchestrator_scm_connector_connected 1 cuando el WebSocket del conector SCM está abierto; 0 mientras marca o retrocede. Ausente cuando --scm-connector-host no está establecido.
claude_code_self_hosted_orchestrator_scm_connector_requests_forwarded_total Solicitudes HTTP acumulativas proxificadas al host SCM configurado desde el inicio del proceso. Ausente cuando --scm-connector-host no está establecido.

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_sessions en su escalador HPA o KEDA, no queue_pending_sessions.
  • Escalado de capacidad: escale en la relación de active_sessions del runner a capacity.
  • Cierre en connected: filtre la consulta con claude_code_self_hosted_orchestrator_connected == 1 por instancia, para que el valor obsoleto de una réplica desconectada no se alimente al escalador.

Durante una interrupción de sondeo completa, cada réplica desconectada, la consulta cerrada no devuelve datos. HPA mantiene el recuento de réplica actual en una métrica faltante, pero el escalador de Prometheus de KEDA en su 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:

# Ejemplo de PodMonitor del Operador de Prometheus para el runner + orquestador
# autohospedado de Claude Code. Ajuste los selectores de espacio de nombres y
# etiqueta para que coincidan con su despliegue. Tanto el runner como el
# orquestador sirven /metrics en su --health-port (predeterminado 8080).
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
  name: claude-code-self-hosted-runner
  namespace: monitoring
spec:
  namespaceSelector:
    matchNames:
      - claude-runners
  selector:
    matchExpressions:
      # Coincide con el Deployment del runner de la receta de Kubernetes, más
      # cualquier Job de runner bajo demanda y pods del orquestador que etiquete
      # de la misma forma y dé un containerPort 'health' nombrado.
      - key: app.kubernetes.io/part-of
        operator: In
        values: [claude-code-self-hosted-runner]
  podMetricsEndpoints:
    - port: health
      path: /metrics
      interval: 30s

Estas reglas de alerta de ejemplo son un punto de partida; ajuste los umbrales para el tamaño de su flota:

# Reglas de alerta de Prometheus de ejemplo para el runner + orquestador
# autohospedado de Claude Code. Ajuste los umbrales para el tamaño de su flota
# y SLOs.
groups:
  - name: claude-code-self-hosted-runner
    rules:
      - alert: ClaudeRunnerPollStale
        expr: claude_code_self_hosted_runner_last_poll_age_seconds > 60
        for: 2m
        labels: {severity: warning}
        annotations:
          summary: "Runner {{ $labels.pod }} no ha sondado en >60s"
      - alert: ClaudeRunnerVersionDrift
        expr: count(count by (version) (claude_code_self_hosted_runner_info)) > 1
        for: 30m
        labels: {severity: info}
        annotations:
          summary: "Los runners están ejecutando versiones mixtas"
      - alert: ClaudeRunnerInitErrorsHigh
        expr: increase(claude_code_self_hosted_runner_session_init_errors_total[10m]) > 3
        for: 5m
        labels: {severity: warning}
        annotations:
          summary: "Runner {{ $labels.pod }}: >3 fallos de inicialización de sesión en 10m (hook de checkout / git / token / bloqueo previo a la inicialización)"
      - alert: ClaudeRunnerPollErrors
        expr: sum by (pod) (rate(claude_code_self_hosted_runner_poll_errors_total[5m])) > 0
        for: 2m
        labels: {severity: warning}
        annotations:
          summary: "Runner {{ $labels.pod }}: PollWork fallando ({{ $value | humanize }}/s en 5m)"
      - alert: ClaudeRunnerSessionStartHookErrors
        expr: increase(claude_code_self_hosted_runner_session_start_hook_errors_total[10m]) > 3
        for: 5m
        labels: {severity: warning}
        annotations:
          summary: "Runner {{ $labels.pod }}: >3 fallos de hook SessionStart en 10m"

  - name: claude-code-self-hosted-orchestrator
    rules:
      - alert: ClaudeOrchestratorDisconnected
        expr: claude_code_self_hosted_orchestrator_connected == 0
        for: 2m
        labels: {severity: critical}
        annotations:
          summary: "El orquestador {{ $labels.pod }} no puede alcanzar el plano de control de Anthropic"
      - alert: ClaudeOrchestratorPollStale
        expr: claude_code_self_hosted_orchestrator_last_poll_age_seconds > 90
        for: 2m
        labels: {severity: warning}
        annotations:
          summary: "El orquestador {{ $labels.pod }} no ha sondado en >90s (el bucle de sondeo espera en la ejecución del hook)"
      - alert: ClaudeOrchestratorCircuitBroken
        expr: claude_code_self_hosted_orchestrator_queue_circuit_broken_sessions > 0
        for: 1m
        labels: {severity: critical}
        annotations:
          summary: "{{ $value }} sesiones con circuito abierto — el hook spawn-runner es repetidamente no reintentable; corrija la infraestructura y luego reintente desde la pestaña Activity"
      - alert: ClaudeOrchestratorPollErrors
        expr: sum by (pod) (rate(claude_code_self_hosted_orchestrator_poll_errors_total[5m])) > 0
        for: 2m
        labels: {severity: warning}
        annotations:
          summary: "Orquestador {{ $labels.pod }}: PollSpawnHints fallando ({{ $value | humanize }}/s en 5m)"
      - alert: ClaudeOrchestratorSpawnHookFailing
        expr: sum by (pod) (increase(claude_code_self_hosted_orchestrator_spawn_hooks_total{result!="ok"}[5m])) > 3
        for: 5m
        labels: {severity: warning}
        annotations:
          summary: "Orquestador {{ $labels.pod }}: >3 fallos de hook spawn-runner en 5m"

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.

Semántica del contador del ciclo de vida de la sesión

Los contadores sessions_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ódigo 0, 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. Incrementa sessions_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. Incrementa sessions_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 gracia SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS después de su límite --kill-session-after-min terminó. Un reinicio rodante de Kubernetes enviando SIGTERM es un ejemplo de un drenaje. Incrementa sessions_interrupted_total.

Antes de v2.1.260, el runner terminaba cada sesión que alcanzaba su límite --kill-session-after-min y la contaba en sessions_interrupted_total.

El CLAUDE_RUNNER_EXIT_REASON del hook post-session clasifica traspasos limpios de manera diferente. El hook reporta una liberación, un timeout de inicio, y una desasignación del servidor como interrupted, porque el runner detuvo el hijo. 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:

Goal Use
Throughput claude_code_self_hosted_orchestrator_spawn_hooks_total{result="ok"}, un contador en el orquestador de larga vida que incrementa una vez por hook spawn-runner exitoso y permanece significativo bajo rate(). Cuenta invocaciones de hook en lugar de sesiones, por lo que el precalentamiento y los generadores repetidos para la misma sesión lo divergen de los recuentos de sesión.
Utilization sum(claude_code_self_hosted_runner_active_sessions) contra sum(claude_code_self_hosted_runner_capacity), ambos indicadores válidos en cada raspado independientemente de la vida útil del runner
Backlog claude_code_self_hosted_orchestrator_pool_pending_sessions para profundidad de cola, y claude_code_self_hosted_orchestrator_queue_circuit_broken_sessions, alertando si es superior a cero
Failures claude_code_self_hosted_runner_sessions_failed_total, mejor esfuerzo: los bloqueos reales después de la generación sí lo incrementan, y rate() es significativo en runners que sobreviven a sus sesiones con --drain-grace-sec superior a 0. Un entorno de un solo disparo tiene el mismo problema de ventana de raspado que los otros contadores terminales, así que trate cualquier valor distinto de cero que vea como digno de investigación. Las fallas antes de la generación, como una falla de hook de checkout, preparación de git, o un problema de token, aparecen solo en session_init_errors_total.

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