SpyBara
Go Premium

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

This page contains 342 additions and 0 deletions.

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

Riferimento per ambienti self-hosted

Riferimento completo per il runner self-hosted e l'orchestrator: flag CLI, variabili d'ambiente e metriche Prometheus.

Questa pagina è il riferimento per i due processi che eseguite in un ambiente self-hosted: il runner, che esegue le sessioni cloud di Claude Code sui vostri host, e l'orchestrator di autoscaling opzionale, che avvia i runner mentre le sessioni si accodano. Ognuno ha la propria tabella di flag. Entrambi vengono eseguiti su host Linux o macOS, per i quali i valori predefiniti come /workspace e ~/.claude sono presupposti. Eseguite claude self-hosted-runner --help per l'elenco autorevole sulla vostra versione installata.

Le serie di metriche e alcuni campi API utilizzano ancora pool per quello che queste pagine chiamano un ambiente; entrambi i termini denominano la stessa cosa. L'ID dell'ambiente è il campo pool_id, con la forma ccpool_...: ovunque queste pagine mostrino un identificatore pool, esso denomina l'ambiente. I flag CLI e le variabili d'ambiente lo scrivono come environment, come in --environment-secret-file; i nomi deprecati pool continuano a funzionare, come la riga --environment-secret-file descrive.

Flag CLI del runner

La maggior parte dei flag ha una variabile d'ambiente corrispondente. Quando entrambi sono impostati, il flag ha la precedenza. I flag di durata accettano minuti o secondi sulla CLI, ma la variabile d'ambiente associata è sempre in millisecondi, indicata dal suffisso _MS, e la colonna Default mostra l'unità del flag: --exit-if-unused-min 10 è equivalente a SELF_HOSTED_RUNNER_IDLE_SHUTDOWN_MS=600000, e un valore Helm come SELF_HOSTED_RUNNER_STARTUP_TIMEOUT_MS: "15" significa 15 millisecondi, non il valore predefinito di 15 minuti.

Flag Env var Default Description
--api-url <url> none https://api.anthropic.com URL base dell'API. Eseguire l'override solo per i test.
--base-dir <path> SELF_HOSTED_RUNNER_BASE_DIR /workspace; nessuno su Windows Directory per i checkout dei repository e le directory di lavoro per sessione. Il runner necessita dell'accesso in scrittura a questo percorso o al suo genitore. Il runner crea la directory all'avvio e esce con cannot create or write to base directory quando non riesce a crearla o scrivervi. Prima della v2.1.225, il runner creava la directory quando la prima sessione iniziava, quindi un percorso inutilizzabile causava il fallimento delle sessioni piuttosto che dell'avvio. Su Windows, che non è un host runner supportato, non c'è un valore predefinito: il runner esce all'avvio a meno che non passi il flag o imposti la variabile. Usa lo stesso valore su ogni runner in un ambiente. Vedi Keep the base directory and capacity identical across runners.
--capacity <n> none 1 Numero massimo di sessioni simultanee che questo runner gestisce. Tutte le sessioni appartengono allo stesso owner bloccato. Usa lo stesso valore su ogni runner in un ambiente; vedi Keep the base directory and capacity identical across runners.
--client-label <label> SELF_HOSTED_RUNNER_CLIENT_LABEL l'hostname dell'host Etichetta che il runner invia quando si registra. Il runner lo segnala anche come etichetta client_label di claude_code_self_hosted_runner_info. Richiede Claude Code v2.1.248 o successivo.
--configure-git SELF_HOSTED_RUNNER_CONFIGURE_GIT=1 off All'avvio, scrivi l'identità git globale, abilita la firma dei commit Anthropic, attiva la negoziazione push di git e installa hook di commit che aggiungono un trailer Co-authored-by:. La negoziazione push richiede Claude Code v2.1.257 o successivo. Vedi Configure git.
--confine-repo-settings <mode> SELF_HOSTED_RUNNER_CONFINE_REPO_SETTINGS warn Imposta la modalità della guardia che contrassegna una sessione quando le impostazioni impegnate di un repository tentano di concedere accesso in scrittura o lettura al di fuori dello spazio di lavoro della sessione, impostare variabili d'ambiente o eseguire l'override della postura sandbox o hooks dell'operatore, come sandbox.enabled: false o disableAllHooks. Il valore predefinito warn registra la violazione e avvia comunque la sessione, enforce rifiuta la sessione e off disabilita la scansione. Vedi Harden your deployment.
--debug-token-dir <path> SELF_HOSTED_RUNNER_DEBUG_TOKEN_DIR unset Scrivi i token live su disco per l'ispezione. Solo debug; non usare in produzione.
--defer-shutdown-max-min <n> SELF_HOSTED_RUNNER_DEFER_SHUTDOWN_MAX_MS 0 Al primo SIGTERM o SIGINT, continua a servire le sessioni già collegate invece di drenare, quindi rilascia tutto ciò che è ancora collegato N minuti dopo e esci. Aumenta il timeout di arresto del tuo host prima di impostare questo. Vedi Defer the drain past the first signal. 0 disabilita. Richiede Claude Code v2.1.238 o successivo.
--drain-grace-sec <n> SELF_HOSTED_RUNNER_DRAIN_GRACE_MS 0 Fino a quando il runner riceve un segnale di arresto o raggiunge il suo tempo di ritiro, controlla quando il runner esce dopo che le sue sessioni attive finiscono: 0 esce immediatamente senza polling per altri, e un valore positivo mantiene il runner attivo e ri-polling della coda dell'owner bloccato per quel numero di secondi, al costo dell'isolamento del contenitore per sessione descritto nella sezione hardening. Dopo un primo segnale che hai differito con --defer-shutdown-max-min, il runner esce non appena non contiene sessioni, indipendentemente da quello che imposti qui.
--drain-wait-sec <n> SELF_HOSTED_RUNNER_DRAIN_WAIT_MS 0 Una volta che il drenaggio inizia, che è su SIGTERM a meno che non imposti --defer-shutdown-max-min, attendi fino a N secondi affinché il turno in volo di ogni sessione e i compiti in background finiscano prima di terminare il figlio. Durante questa attesa, il runner conta un compito in background che ha appena finito come ancora in esecuzione fino a quando il turno di follow-up che legge il suo risultato inizia, per al massimo la finestra SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS.
--environment-secret-file <path> SELF_HOSTED_RUNNER_ENVIRONMENT_SECRET required Percorso a un file contenente il segreto dell'ambiente, o, per i runner generati dall'orchestrator, il JWT del work-order monouso. SELF_HOSTED_RUNNER_ENVIRONMENT_SECRET porta il valore del segreto direttamente, non un percorso di file. Il flag --pool-secret-file più vecchio e la variabile SELF_HOSTED_RUNNER_POOL_SECRET ancora funzionano e stampano un avviso di deprecazione su stderr; le build del runner del programma di anteprima più vecchie di 2.1.216 riconoscono solo quei nomi più vecchi.
--exec-path <path> SELF_HOSTED_RUNNER_EXEC_PATH own binary File binario o script wrapper da generare per ogni sessione. Vedi Wrapper scripts.
--exit-if-unused-min <n> SELF_HOSTED_RUNNER_IDLE_SHUTDOWN_MS 0 Esci dopo N minuti di polling senza lavoro mai assegnato, per il scale-down dell'autoscaler. 0 disabilita.
--git-host-rewrite <from>=<to> none unset Riscrivi gli URL di origine https://<from>/... a https://<to>/... prima della clonazione, per DNS a orizzonte diviso. Ripetibile; solo flag.
--git-ssh-rewrite <host> none unset Riscrivi gli URL di origine https://<host>/... a git@<host>:... prima della clonazione, per host git solo SSH. Ripetibile; solo flag.
--health-port <port> SELF_HOSTED_RUNNER_HEALTH_PORT 8080 Porta per il listener /healthz e /metrics. Imposta 0 per disabilitare.
--hooks-dir <path> SELF_HOSTED_RUNNER_HOOKS_DIR unset Directory degli script hook del ciclo di vita. Vedi Lifecycle hooks.
--kill-session-after-min <n> SELF_HOSTED_RUNNER_MAX_LIFETIME_MS 0 Limita una sessione a N minuti di tempo reale, come limite di sicurezza per le sessioni bloccate. Su v2.1.260 o successivo, il runner rilascia una sessione che raggiunge il limite in modo che possa riprendere al prossimo messaggio dell'utente, e la termina solo se è ancora sul runner quando la finestra di grazia SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS finisce. Prima della v2.1.260, il runner terminava la sessione al limite. Vedi Some sessions don't count as idle per i dettagli e come scegliere un valore. 0 disabilita.
--lock-to-account <id> SELF_HOSTED_RUNNER_LOCK_TO_ACCOUNT unset Pre-blocca il runner a un account specifico all'avvio invece di bloccare alla prima sessione. Accetta un indirizzo email o un ID user_... nell'organizzazione dell'ambiente. Un runner pre-bloccato non raccoglie mai sessioni del canale Claude Tag, che non hanno account.
--log-file <path> SELF_HOSTED_RUNNER_LOG_FILE unset Specchia i log del runner in un file oltre a stdout e stderr, creato con permessi 0600. Richiesto per self-hosted-runner doctor per accodare i log localmente.
--log-level <level> none info info o debug
--post-session-hook-timeout-sec <n> SELF_HOSTED_RUNNER_POST_SESSION_HOOK_TIMEOUT_MS 60 Budget per l'hook post-session alla fine di ogni sessione, incluso l'arresto del runner
--proxy-authorization-command <command> SELF_HOSTED_RUNNER_PROXY_AUTHORIZATION_COMMAND unset Comando shell che il runner esegue per ogni connessione al tuo proxy di uscita, usando il suo stdout ritagliato come valore dell'intestazione Proxy-Authorization. Richiede HTTPS_PROXY o HTTP_PROXY, e non può essere combinato con --proxy-authorization-file. Vedi Authenticate to an egress proxy. Richiede Claude Code v2.1.238 o successivo.
--proxy-authorization-file <path> SELF_HOSTED_RUNNER_PROXY_AUTHORIZATION_FILE unset File che il runner legge per ogni connessione al tuo proxy di uscita, usando i suoi contenuti ritagliati come valore dell'intestazione Proxy-Authorization. Usa questo flag per un token che un altro processo ruota in posizione. Porta gli stessi requisiti di --proxy-authorization-command, e non può essere combinato con esso. Vedi Authenticate to an egress proxy. Richiede Claude Code v2.1.238 o successivo.
--push-outcome-on-release SELF_HOSTED_RUNNER_PUSH_OUTCOME_ON_RELEASE off Alla fine di una sessione avviata dal runner come un drenaggio o una versione inattiva, esegui il push dei rami di risultato tracciati a origin prima di eliminare lo spazio di lavoro, in modo che i commit in volo sopravvivano a un riavvio. Best-effort; aggiunge 30 secondi al budget di arresto, e richiede git 2.29 o più recente per riprendere dal ramo sottoposto a push. Limita l'accesso push ai ref claude/* prima di abilitare; vedi Resumed sessions lose unpushed work. I repository estratti tramite un hook del ciclo di vita checkout non vengono sottoposti a push; fai uno snapshot di quelli dall'hook post-session invece.
--release-idle-session-min <n> SELF_HOSTED_RUNNER_SESSION_IDLE_MS 0 Rilascia uno slot di sessione dopo N minuti di inattività una volta che un turno finisce o la sessione attende l'azione dell'utente. Una sessione che è ancora a metà turno, inclusa una che contiene un compito in background che non finisce mai o un'approvazione richiesta dall'interno di una chiamata di strumento in esecuzione, non conta come inattiva; abbina con --kill-session-after-min come backstop duro. Dopo che il compito in background di una sessione finisce, il runner considera la sessione occupata fino a quando il turno di follow-up che legge il risultato inizia, per al massimo la finestra SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS. Fino a quando il runner riceve un segnale di arresto o raggiunge il suo tempo di ritiro, un rilascio che lascia il runner senza sessioni attive avvia lo stesso percorso di uscita di un drenaggio normale, governato da --drain-grace-sec. Dopo un primo segnale che hai differito con --defer-shutdown-max-min, il runner esce non appena un rilascio lo lascia senza sessioni. 0 disabilita.
--retire-at <epoch-seconds> SELF_HOSTED_RUNNER_RETIRE_AT unset Ritira il runner a un timestamp Unix assoluto in secondi, per l'infrastruttura che uccide il runner a un'ora nota; Runner lifecycle descrive la sequenza di rilascio e come dimensionare il margine. I valori prima del 2001 o dopo l'anno 5138 vengono rifiutati dal flag e ignorati dalla variabile d'ambiente.
--session-stop-grace-sec <n> SELF_HOSTED_RUNNER_SESSION_STOP_GRACE_MS 5 Quanto tempo aspettare affinché il processo Claude esca correttamente dopo la fine di una sessione, prima di forzare l'uccisione. Aumenta il valore se gli hook SessionEnd del figlio hanno bisogno di più tempo.
--startup-timeout-min <n> SELF_HOSTED_RUNNER_STARTUP_TIMEOUT_MS 15 Rilascia uno slot di sessione se il figlio non ha segnalato che si è inizializzato entro N minuti dalla generazione. Cancellato dal segnale di init del figlio sul canale di attività, non dall'output ordinario, dopo di che --release-idle-session-min prende il sopravvento. 0 disabilita.
--trust-workspace [bool] SELF_HOSTED_RUNNER_TRUST_WORKSPACE on Semina la fiducia persistente per i percorsi del repository di ogni sessione in modo che permissions.allow e additionalDirectories impegnati nel repo siano onorati. Imposta false per eliminare le concessioni di autorizzazione impegnate nel repo e configurare le regole di autorizzazione nella settings.json della configurazione dell'host; le impostazioni sandbox.* impegnate nel repository si applicano comunque in entrambi i casi, motivo per cui la guardia repo-settings le scansiona indipendentemente da questo flag.
--use-anthropic-git-proxy CLAUDE_RUNNER_USE_GIT_PROXY=1 off Clona tramite il proxy git di Anthropic invece dell'autenticazione git gestita dal cliente. Richiede --capacity 1 e git 2.32 o più recente; il runner rifiuta di avviarsi altrimenti. Sostituisce i flag di riscrittura.

La maggior parte dei flag di durata ha un massimo, scelto per mantenere ogni timeout entro il limite del timer a 32 bit del runtime di circa 24,85 giorni. I flag --*-min hanno un limite di 10080 minuti, 7 giorni; --drain-grace-sec a 604800 secondi, anche 7 giorni; e --drain-wait-sec a 86400 secondi, 24 ore. --session-stop-grace-sec e --post-session-hook-timeout-sec non hanno limiti. Superare un limite si comporta diversamente per superficie:

  • Flag: l'avvio fallisce con un errore.
  • Variabile d'ambiente: il runner fissa il valore al limite del timer piuttosto che rifiutarlo.

Flag CLI dell'orchestrator

Il sottocomando self-hosted-runner orchestrator, che genera runner on-demand, accetta --api-url, --environment-secret-file, --hooks-dir, --health-port e --log-level con gli stessi valori predefiniti del runner e, dove il flag del runner ne ha uno, la stessa variabile d'ambiente, tranne che --hooks-dir è obbligatorio e deve contenere un hook spawn-runner. Accetta anche i suoi flag:

Flag Default Description
--hook-concurrency <n> 4 Numero massimo di hook spawn-runner in esecuzione in parallelo. Limita anche quante richieste di spawn vengono rivendicate per polling.
--hook-timeout <sec> 60 Termina l'albero dei processi dell'hook dopo questo numero di secondi. Il timeout più la sua grazia di 5 secondi deve rimanere al di sotto di --expected-spawn-seconds; l'orchestrator lo applica all'avvio.
--expected-spawn-seconds <sec> 120 Tempo di avvio p99 previsto per i runner generati, nell'intervallo applicato dal server da 10 a 3600. Inviato ad ogni polling come il lease lato server; se nessun runner si registra prima che trascorra, la sessione viene ri-offerta con un ID ordine nuovo. Tutte le repliche devono condividere questo valore.
--min-idle <n> 0 Mantieni almeno N slot di sessione inattivi liberi generando proattivamente runner di standby. 0 disabilita il pre-riscaldamento. Abbina con il --exit-if-unused-min del runner in modo che i runner di standby in eccesso si riprendano.
--debug-dir <path> unset Scrivi il work order e lo stderr dell'hook di ogni richiesta di spawn su disco. Solo debug; non impostare mai in produzione.

Flag del connettore SCM

L'orchestrator può mantenere una connessione WebSocket permanente al piano di controllo di Anthropic in modo che i flussi pre-sessione ospitati, come il selettore di repository e il risolutore di ramo o ref, possano raggiungere un host GitHub Enterprise Server che è instradabile solo dall'interno della tua rete. Il connettore rimane disattivato a meno che non imposti --scm-connector-host.

Flag Default Description
--scm-connector-host <host[:port]> unset Nome host di GitHub Enterprise Server a cui inoltrare le richieste. La porta predefinita è 443. L'impostazione di questo flag abilita il connettore.
--scm-connector-id <n> required with --scm-connector-host L'ID numerico della connessione GitHub Enterprise Server della tua organizzazione. Contatta il tuo team di account Anthropic per il valore quando abiliti il connettore.
--scm-connector-provider <slug> ghe Segmento di percorso che identifica il provider, corrispondente a ^[a-z0-9-]{1,32}$.
--scm-connector-ca-file <path> unset Bundle CA aggiuntivo, in formato PEM, per le connessioni TLS all'host GitHub Enterprise Server.
--scm-connector-host-rewrite <from>=<to_host:to_port> unset Solo per test end-to-end: reindirizza la connessione TCP mantenendo l'intestazione Host e TLS SNI come --scm-connector-host.

Il connettore si autentica con il segreto dell'ambiente esistente dell'orchestrator e si riconnette automaticamente: con backoff esponenziale su una connessione interrotta, o un ritardo fisso di 30 secondi quando il piano di controllo chiude la connessione perché un'altra replica dell'orchestrator la contiene già.

Impostazioni solo variabili d'ambiente

Queste impostazioni del runner vengono lette solo dall'ambiente e coprono il comportamento che la maggior parte delle distribuzioni lascia al valore predefinito:

Env var Default Description
SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS 30000 Quanto tempo il runner considera una sessione occupata dopo che un compito in background finisce mentre il turno di follow-up che legge il risultato non è ancora iniziato. Le righe --drain-wait-sec e --release-idle-session-min descrivono dove si applica la tenuta su drenaggio e rilascio inattivo, e Runner lifecycle descrive dove si applica al ritiro --retire-at. 0 o un valore inutilizzabile ricade al valore predefinito, quindi la tenuta non può essere disattivata. Richiede Claude Code v2.1.228 o successivo.
SELF_HOSTED_RUNNER_HOST_CONFIG_DIR ~/.claude Directory acquisita nello snapshot di avvio del runner e seminata nella CLAUDE_CONFIG_DIR di ogni sessione; le modifiche su disco si applicano dopo un riavvio del runner. L'impostazione della variabile sposta anche dove il runner legge .claude.json per il seeding MCP, quindi impostarla, incluso al suo valore predefinito, trasferisce quella ricerca; punta a una directory vuota per disabilitare completamente il seeding.
SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS 900000 Quanto tempo il runner attende dopo che una sessione raggiunge il suo limite --kill-session-after-min, affinché un turno in esecuzione finisca o il rilascio si completi, prima di terminare la sessione
SELF_HOSTED_RUNNER_SIGKILL_GRACE_MS 30000 Quanto tempo il runner attende che il sistema operativo consegni SIGKILL a un figlio bloccato in I/O non interrompibile prima di uscire lui stesso. Limitato inferiormente a --post-session-hook-timeout-sec più 15 secondi, e 30 in più quando --push-outcome-on-release è impostato, quindi il minimo effettivo è 75 secondi ai valori predefiniti.
CLAUDE_RUNNER_FETCH_DEPTH 50 Profondità di fetch git per cloni freschi. Imposta un numero intero positivo, o full o 0 per un fetch completo. I repository già presenti nello spazio di lavoro mantengono la loro profondità esistente.
CLAUDE_RUNNER_SKIP_GIT_VERIFY unset Quando 1, salta il controllo della presenza .git dopo l'esecuzione di un hook checkout. Imposta questo quando il tuo hook materializza una fonte non-git.
FORCE_AUTOUPDATE_PLUGINS unset Quando 1, consenti ai marketplace dei plugin di auto-aggiornare anche se il binario è bloccato
CLAUDE_CODE_DISABLE_ARTIFACT unset Quando 1, disabilita lo strumento Artifact nelle sessioni indipendentemente dall'impostazione di amministrazione dell'organizzazione, e elimina il requisito di uscita *.frame.claudeusercontent.com

Telemetria

I figli della sessione inviano telemetria operativa ad Anthropic a meno che non la disattivi. Nessun codice o contenuto del repository viene inviato. Imposta le variabili di telemetria sul processo del runner; il runner le ri-asserisce dopo aver applicato le variabili d'ambiente fornite dal server, quindi l'impostazione dell'operatore ha sempre la precedenza.

Un controllo è specifico per gli ambienti self-hosted: CLAUDE_CODE_BYOC_ENABLE_DATADOG=1 acconsente alle metriche operative di Datadog, che sono disattivate per impostazione predefinita negli ambienti self-hosted. I controlli generali di telemetria di Claude Code, DISABLE_TELEMETRY, DO_NOT_TRACK, DISABLE_ERROR_REPORTING e CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, si applicano ai figli della sessione come documentato nel riferimento delle variabili d'ambiente. DISABLE_GROWTHBOOK è correlato ma diverso: impostare DISABLE_GROWTHBOOK=1 disabilita il recupero dei flag di funzionalità, e la telemetria rimane attiva a meno che DISABLE_TELEMETRY non sia anche impostato.

CLAUDE_CODE_ENABLE_TELEMETRY non è correlato: abilita l'esportazione OpenTelemetry al tuo collettore, come descritto in Monitoring, e non controlla l'analittica di Anthropic.

Endpoint di salute

Il runner serve GET /healthz sulla porta di salute configurata. La risposta è 200 OK ogni volta che il processo è attivo, qualunque stato sia il ciclo di polling, quindi un probe HTTP su questo endpoint rileva solo un processo morto. Il corpo JSON descrive lo stato attuale:

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

Usa last_poll_age_ms come segnale di vivacità nei probe personalizzati; un valore che cresce senza limiti indica che il ciclo di polling è bloccato. Sia last_poll_at che last_poll_age_ms sono null fino al completamento del primo polling.

L'orchestrator serve il suo /healthz sulla sua porta di salute. Il suo endpoint restituisce sempre 200, e il corpo porta un campo connected che segnala se il polling più recente ha avuto successo, più i conteggi della coda di spawn per stato in queue_counts. Gated readiness e alerting su connected piuttosto che sul codice di stato.

Quando il connettore SCM è configurato, il corpo /healthz dell'orchestrator porta anche scm_connector_connected e un oggetto scm_connector con connected, last_connected_at, last_error, reconnects e requests_forwarded. Entrambi i campi sono null quando --scm-connector-host non è impostato.

Metriche Prometheus

Ogni runner serve metriche Prometheus su GET /metrics sulla stessa porta di /healthz. Serie chiave:

Series Notes
claude_code_self_hosted_runner_info{runner_id,version,client_label} Sempre 1; utile per l'inventario della flotta e il rilevamento della deriva di versione
claude_code_self_hosted_runner_capacity --capacity configurato
claude_code_self_hosted_runner_active_sessions Sessioni attualmente in esecuzione
claude_code_self_hosted_runner_locked_account{email} Presente una volta che il runner si è bloccato a un utente e un token di sessione che porta un'affermazione act.email è stato emesso. La serie è assente su un runner bloccato a un agente Claude Tag, i cui token di sessione non portano act.email. Il valore dell'etichetta è l'email dell'account; se il tuo archivio di metriche è ampiamente leggibile, elimina o hash l'etichetta al momento della raschiatura, ad esempio con Prometheus metric_relabel_configs.
claude_code_self_hosted_runner_last_poll_age_seconds Secondi dall'ultimo polling riuscito. Avviso se superiore a 60.
claude_code_self_hosted_runner_poll_errors_total{error_kind} Errori cumulativi di PollWork per tipo: transport, timeout, 5xx, 429 o 4xx. Tutte e cinque le serie sono presenti dall'avvio del processo; avviso su rate(...[5m]) > 0.
claude_code_self_hosted_runner_sessions_started_total{client_platform} Processi figlio della sessione generati durante la vita del runner, una serie per origine della sessione come web_claude_ai, ios, android, desktop_app o claude_code_cli, o unknown quando il server non ne ha inviato uno. Le sessioni Slack portano claude_in_slack o claude-in-slack a seconda di quale integrazione Slack le ha create, quindi abbina entrambe con un selettore regex come {client_platform=~"claude[-_]in[-_]slack"}. Usa sum() per il totale della flotta.
claude_code_self_hosted_runner_sessions_completed_total{client_platform} Sessioni che sono terminate correttamente, etichettate allo stesso modo. Più ampio di una semplice uscita pulita: vedi session lifecycle counter semantics per cosa conta.
claude_code_self_hosted_runner_sessions_failed_total{client_platform} Sessioni che sono terminate in errore, etichettate allo stesso modo. Stessa avvertenza: vedi session lifecycle counter semantics.
claude_code_self_hosted_runner_sessions_interrupted_total{client_platform} Sessioni che il runner ha terminato per un motivo operativo piuttosto che un risultato di sessione, etichettate allo stesso modo. Vedi session lifecycle counter semantics.
claude_code_self_hosted_runner_initializing_sessions Sessioni attualmente nella fase di init, dall'assegnazione all'evento di init del figlio
claude_code_self_hosted_runner_session_init_duration_seconds Istogramma delle durate di init della sessione
claude_code_self_hosted_runner_session_init_errors_total Sessioni che hanno fallito prima di raggiungere init: un errore di hook di checkout, preparazione git, problema di token o un crash pre-init del figlio
claude_code_self_hosted_runner_session_start_hook_errors_total Hook SessionStart che hanno segnalato un risultato di errore, uno per esecuzione di hook fallita
claude_code_self_hosted_runner_session_idle_seconds{session_id,client_platform} Gauge per sessione di secondi dall'inattività della sessione. Utile per terminare le sessioni bloccate su un prompt di autorizzazione senza risposta.

L'orchestrator serve le sue serie su GET /metrics sulla stessa porta del suo /healthz:

Series Notes
claude_code_self_hosted_orchestrator_info{version,pool_id,orchestrator_uuid,hostname} Sempre 1
claude_code_self_hosted_orchestrator_connected 1 quando il polling più recente ha avuto successo; scende a 0 dopo qualsiasi polling fallito, qualunque sia il tipo di errore
claude_code_self_hosted_orchestrator_last_poll_age_seconds Secondi dall'ultimo tentativo di polling, successo o errore, a differenza della metrica identicamente denominata del runner, che misura dall'ultimo successo; abbina con connected per catturare i polling falliti. Il ciclo di polling dell'orchestrator attende l'esecuzione dell'hook, quindi avviso sopra --hook-timeout più un margine, circa 90 secondi ai valori predefiniti, piuttosto che un flat 60.
claude_code_self_hosted_orchestrator_poll_errors_total{error_kind} Errori cumulativi di PollSpawnHints per tipo: transport, timeout, 5xx, 429 o 4xx. Tutte e cinque le serie sono presenti dall'avvio del processo; avviso su rate(...[5m]) > 0.
claude_code_self_hosted_orchestrator_queue_pending_sessions Richieste di spawn rivendicabili in questo momento
claude_code_self_hosted_orchestrator_queue_backing_off_sessions Richieste di spawn in backoff di retry dopo un errore di hook riprova
claude_code_self_hosted_orchestrator_queue_circuit_broken_sessions Richieste di spawn bloccate fino a quando un Owner non le riprova dalla scheda Activity dell'ambiente; avviso se superiore a zero
claude_code_self_hosted_orchestrator_pool_pending_sessions Sessioni totali in attesa di un runner per questo ambiente. Aggregato a livello di ambiente, identico su ogni istanza dell'orchestrator: usa MAX piuttosto che SUM tra le istanze.
claude_code_self_hosted_orchestrator_pool_active_sessions Sessioni attualmente assegnate a un runner vivo in questo ambiente. Aggregato a livello di ambiente, identico su ogni istanza dell'orchestrator: usa MAX piuttosto che SUM tra le istanze.
claude_code_self_hosted_orchestrator_spawn_hooks_total{result} Risultati cumulativi dell'hook spawn-runner: ok, retryable, non_retryable. Conta le invocazioni dell'hook dell'orchestrator, non i figli della sessione che i runner generano: non comparabili a sessions_started_total, poiché la capacità superiore a uno, i pool caldi e i runner generati di nuovo per la stessa sessione divergono i due.
claude_code_self_hosted_orchestrator_spawn_hook_duration_seconds Istogramma delle durate dell'hook
claude_code_self_hosted_orchestrator_warm_hints_dispatched_total Richieste di spawn di standby inviate dall'avvio del processo
claude_code_self_hosted_orchestrator_session_queue_wait_seconds Istogramma di secondi che ogni sessione ha atteso nella coda prima che l'orchestrator la rivendicasse per spawn, registrato dal timestamp di attesa della coda che il piano di controllo invia con la richiesta di spawn di ogni sessione. Usa per l'avviso del tempo di coda p50/p99. I spawn di pre-riscaldamento non vengono campionati.
claude_code_self_hosted_orchestrator_clock_skew_seconds Skew dell'orologio locale meno server; diagnostico, presente una volta misurato
claude_code_self_hosted_orchestrator_scm_connector_connected 1 quando il WebSocket del connettore SCM è aperto; 0 durante la composizione o il backoff. Assente quando --scm-connector-host non è impostato.
claude_code_self_hosted_orchestrator_scm_connector_requests_forwarded_total Richieste HTTP cumulative inoltrate all'host SCM configurato dall'avvio del processo. Assente quando --scm-connector-host non è impostato.

Per l'autoscaling, scegli la serie che corrisponde al tuo stile di scaling e gated prima che si nutra nello scaler:

  • Scaling della profondità della coda: alimenta claude_code_self_hosted_orchestrator_pool_pending_sessions nel tuo HPA o scaler KEDA, non queue_pending_sessions.
  • Scaling della capacità: scala sul rapporto tra active_sessions e capacity del runner.
  • Gate su connected: filtra la query con claude_code_self_hosted_orchestrator_connected == 1 per istanza, quindi il valore stantio di una replica disconnessa non si nutre nello scaler.

Durante un'interruzione completa del polling, ogni replica disconnessa, la query gated non restituisce dati. HPA mantiene il numero di replica attuale su una metrica mancante, ma lo scaler Prometheus di KEDA al suo ignoreNullValues: "true" predefinito legge il risultato vuoto come zero e scala in; imposta ignoreNullValues: "false" su ScaledObject, facoltativamente con un floor di replica fallback.

Il seguente PodMonitor di Prometheus Operator copre entrambi i processi. Seleziona i pod per l'etichetta app.kubernetes.io/part-of: claude-code-self-hosted-runner e la porta denominata health che la ricetta Kubernetes imposta; regola gli spazi dei nomi per corrispondere alla tua distribuzione:

# Example Prometheus Operator PodMonitor for the Claude Code self-hosted
# runner + orchestrator. Adjust the namespace and label selectors to match
# your deployment. Both the runner and the orchestrator serve /metrics on
# their --health-port (default 8080).
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
  name: claude-code-self-hosted-runner
  namespace: monitoring
spec:
  namespaceSelector:
    matchNames:
      - claude-runners
  selector:
    matchExpressions:
      # Matches the runner Deployment from the Kubernetes recipe, plus any
      # on-demand runner Jobs and orchestrator pods you label the same way
      # and give a named 'health' containerPort.
      - key: app.kubernetes.io/part-of
        operator: In
        values: [claude-code-self-hosted-runner]
  podMetricsEndpoints:
    - port: health
      path: /metrics
      interval: 30s

Queste regole di avviso di esempio sono un punto di partenza; sintonizza le soglie per la dimensione della tua flotta:

# Example Prometheus alert rules for the Claude Code self-hosted runner
# + orchestrator. Tune thresholds for your fleet size and 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 }} has not polled in >60s"
      - alert: ClaudeRunnerVersionDrift
        expr: count(count by (version) (claude_code_self_hosted_runner_info)) > 1
        for: 30m
        labels: {severity: info}
        annotations:
          summary: "Runners are running mixed versions"
      - 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 session init failures in 10m (checkout hook / git / token / pre-init crash)"
      - 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 failing ({{ $value | humanize }}/s over 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 SessionStart hook failures in 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: "Orchestrator {{ $labels.pod }} cannot reach the Anthropic control plane"
      - alert: ClaudeOrchestratorPollStale
        expr: claude_code_self_hosted_orchestrator_last_poll_age_seconds > 90
        for: 2m
        labels: {severity: warning}
        annotations:
          summary: "Orchestrator {{ $labels.pod }} has not polled in >90s (poll loop waits on hook execution)"
      - alert: ClaudeOrchestratorCircuitBroken
        expr: claude_code_self_hosted_orchestrator_queue_circuit_broken_sessions > 0
        for: 1m
        labels: {severity: critical}
        annotations:
          summary: "{{ $value }} sessions circuit-broken — spawn-runner hook is repeatedly non-retryable; fix infra then retry from the Activity tab"
      - alert: ClaudeOrchestratorPollErrors
        expr: sum by (pod) (rate(claude_code_self_hosted_orchestrator_poll_errors_total[5m])) > 0
        for: 2m
        labels: {severity: warning}
        annotations:
          summary: "Orchestrator {{ $labels.pod }}: PollSpawnHints failing ({{ $value | humanize }}/s over 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: "Orchestrator {{ $labels.pod }}: >3 spawn-runner hook failures in 5m"

Passa attraverso le metriche del figlio della sessione

Ogni sessione viene eseguita nel suo processo figlio con le sue metriche OpenTelemetry; a --capacity superiore a uno, il runner riscrive come quelle metriche figlio vengono esposte. L'impostazione di OTEL_METRICS_EXPORTER=prometheus sull'host del runner e CLAUDE_CODE_ENABLE_TELEMETRY=1 nell'ambiente della sessione, ad esempio dal tuo script wrapper o dall'ambiente del runner stesso, che le sessioni ereditano, ri-espone gli strumenti di contatore e gauge di ogni figlio sull'endpoint /metrics del runner, insieme alle serie del runner. Il runner riscrive l'esportatore del figlio per eseguire il push su OTLP a un ricevitore solo loopback sulla porta di salute, etichetta ogni serie con etichette session_id e client_platform, e rimuove le serie di una sessione quando quella sessione termina. Gli istogrammi non passano, e una metrica figlio il cui nome entrerebbe in collisione con il prefisso del runner è eliminata.

Al --capacity 1 predefinito, la riscrittura non si applica: il figlio della sessione lega il suo endpoint Prometheus sulla porta 9464 come al solito.

Semantica del contatore del ciclo di vita della sessione

I contatori sessions_started_total, sessions_completed_total, sessions_failed_total e sessions_interrupted_total classificano ogni sessione in base a come è terminata. Ogni figlio della sessione generato incrementa sessions_started_total al momento della generazione, e esattamente uno degli altri tre incrementa all'uscita, quindi sessions_started_total meno la somma degli altri tre è uguale al numero di figli della sessione attualmente in esecuzione.

  • completed: la sessione è terminata correttamente. Questo copre il figlio che esce da solo con codice 0, la sessione archiviata o eliminata mentre il figlio era ancora connesso, e il runner che restituisce lo slot in modo pulito: il rilascio della sessione al timeout di inattività, al tempo di ritiro o al limite --kill-session-after-min; un timeout di avvio; o un deassign lato server che il ciclo di polling ha notato prima che il figlio uscisse. Incrementa sessions_completed_total.
  • failed: il figlio è uscito da solo con un codice diverso da zero, sia un crash che un errore di configurazione dopo la generazione. Incrementa sessions_failed_total.
  • interrupted: il runner ha terminato il figlio per un motivo operativo che non è né un successo della sessione né un errore del runner, come un drenaggio, o terminando una sessione che era ancora sul runner quando la finestra di grazia SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS dopo il suo limite --kill-session-after-min è terminata. Un riavvio rolling di Kubernetes che invia SIGTERM è un esempio di drenaggio. Incrementa sessions_interrupted_total.

Prima della v2.1.260, il runner terminava ogni sessione che raggiungeva il suo limite --kill-session-after-min e la contava in sessions_interrupted_total.

Il CLAUDE_RUNNER_EXIT_REASON dell'hook post-session classifica gli handoff puliti diversamente. L'hook segnala un rilascio, un timeout di avvio e un deassign del server come interrupted, perché il runner ha fermato il figlio. Questi contatori registrano gli stessi eventi come completed, perché lo slot è stato restituito correttamente.

Se riconcili le ricevute dell'hook direttamente contro sessions_completed_total, sottostimi i completamenti. Usa l'hook per le garanzie per sessione e i contatori per i tassi aggregati.

Su un ambiente monouso, --capacity 1 con il --drain-grace-sec 0 predefinito, ogni processo del runner esce momenti dopo la fine della sua sessione. sessions_completed_total, sessions_failed_total e sessions_interrupted_total incrementano solo alla fine della sessione, subito prima di quell'uscita, quindi un raschiamento Prometheus ogni 15-60 secondi raramente cattura l'incremento prima che le serie del runner scompaiano; questi tre contatori di fine sessione sono i contatori terminali a cui il resto di questa sezione si riferisce. sessions_started_total incrementa alla generazione e rimane visibile per la vita della sessione, quindi si mostra in modo affidabile, ma su un ambiente monouso legge più vicino a "sessioni attualmente in esecuzione" che a un conteggio cumulativo.

Usa la serie in questa tabella per l'obiettivo corrispondente invece dei contatori terminali:

Goal Use
Throughput claude_code_self_hosted_orchestrator_spawn_hooks_total{result="ok"}, un contatore sull'orchestrator di lunga durata che incrementa una volta per hook spawn-runner riuscito e rimane significativo sotto rate(). Conta le invocazioni dell'hook piuttosto che le sessioni, quindi il pre-riscaldamento e i spawn ripetuti per la stessa sessione divergono da conteggi di sessione.
Utilization sum(claude_code_self_hosted_runner_active_sessions) contro sum(claude_code_self_hosted_runner_capacity), entrambi i gauge validi ad ogni raschiamento indipendentemente dalla durata del runner
Backlog claude_code_self_hosted_orchestrator_pool_pending_sessions per la profondità della coda, e claude_code_self_hosted_orchestrator_queue_circuit_broken_sessions, avviso se superiore a zero
Failures claude_code_self_hosted_runner_sessions_failed_total, best effort: i veri crash dopo la generazione incrementano, e rate() è significativo su runner che sopravvivono alle loro sessioni con --drain-grace-sec superiore a 0. Un ambiente monouso ha lo stesso problema della finestra di raschiamento degli altri contatori terminali, quindi tratta qualsiasi valore diverso da zero che vedi come degno di indagine. I fallimenti prima della generazione, come un errore di hook di checkout, preparazione git o un problema di token, appaiono solo in session_init_errors_total.

Le righe orchestrator_* esistono solo su ambienti che eseguono l'orchestrator on-demand. Su una flotta fissa i cui runner sopravvivono alle loro sessioni, con --drain-grace-sec superiore a 0, usa sum(rate(claude_code_self_hosted_runner_sessions_started_total[5m])) per il throughput; su una flotta monouso quella serie ha lo stesso problema della finestra di raschiamento dei contatori terminali, quindi affidati al conteggio delle sessioni in coda. Controlla il backlog nella scheda Activity dell'ambiente, nella pagina di amministrazione Cloud environments: i runner non esportano una serie di profondità della coda.

Per la segnalazione dei risultati per sessione, usa l'hook post-session invece: si attiva alla fine di ogni sessione dove un processo figlio è stato generato, a parte la terminazione abrupte del runner come una preemption VM, per il contratto proprio dell'hook.

Prossimi passi