Les environnements auto-hébergés sont en bêta publique sur les plans Team et Enterprise ; un Propriétaire les active en activant Autoriser les environnements auto-hébergés sur la page d’administration Environnements cloud. Cette page est la référence des drapeaux et des métriques ; consultez le guide de démarrage rapide pour la configuration et Déployer en production pour les recettes de flotte.
/workspace et ~/.claude s’appliquent. Exécutez claude self-hosted-runner --help pour la liste faisant autorité sur votre version installée.
Les séries de métriques et quelques champs API utilisent toujours pool pour ce que ces pages appellent un environnement ; les deux termes désignent la même chose. L’ID d’environnement est le champ pool_id, avec la forme ccpool_... : partout où ces pages affichent un identifiant pool, il désigne l’environnement. Les drapeaux CLI et les variables d’environnement l’écrivent environment, comme --environment-secret-file ; les orthographes pool dépréciées fonctionnent toujours, comme la ligne --environment-secret-file le décrit.
Drapeaux CLI du runner
La plupart des drapeaux ont une variable d’environnement correspondante. Quand les deux sont définis, le drapeau a la priorité. Les drapeaux de durée prennent des minutes ou des secondes sur la CLI, mais la variable d’environnement appariée est toujours en millisecondes, indiquée par le suffixe_MS, et la colonne Par défaut affiche l’unité du drapeau : --exit-if-unused-min 10 équivaut à SELF_HOSTED_RUNNER_IDLE_SHUTDOWN_MS=600000, et une valeur Helm comme SELF_HOSTED_RUNNER_STARTUP_TIMEOUT_MS: "15" signifie 15 millisecondes, pas la valeur par défaut de 15 minutes.
La plupart des drapeaux de durée ont un maximum, choisi pour garder chaque délai d’attente en dessous du plafond de minuteur 32 bits du runtime d’environ 24,85 jours. Les drapeaux
--*-min sont plafonnés à 10080 minutes, 7 jours ; --drain-grace-sec à 604800 secondes, également 7 jours ; et --drain-wait-sec à 86400 secondes, 24 heures. --session-stop-grace-sec et --post-session-hook-timeout-sec ne sont pas plafonnés. Dépasser un plafond se comporte différemment par surface :
- Drapeau : le démarrage échoue avec une erreur.
- Variable d’environnement : le runner serre la valeur au plafond de minuteur plutôt que de la rejeter.
Délai d’expiration du démarrage de session
Si une session a perdu son créneau pendant un tour tel que/code-review, mettez à jour le runner et le binaire enfant vers v2.1.309 ou ultérieur. De v2.1.299 à v2.1.308, le runner libérait une session, même en plein tour, dès que le délai d’expiration du démarrage s’écoulait sans message user ou assistant.
Avec --startup-timeout-min <n>, le runner libère le créneau d’une session quand son enfant ne s’est pas initialisé dans les <n> minutes qui suivent le clonage. Pendant un tour qui commence avant l’initialisation de l’enfant, la session conserve son créneau jusqu’à ce que <n> minutes s’écoulent sans aucune ligne sur le canal d’activité de l’enfant. Une fois l’enfant initialisé, le runner remet ce décompte à zéro et --release-idle-session-min régit la libération. Pour limiter une session dont l’enfant est actif mais bloqué, définissez --kill-session-after-min.
Listes de règles du mode auto
--server-auto-mode-lists vous permet de décider quelles règles du classifieur du mode auto provenant de l’extérieur du runner atteignent les sessions sur vos runners. Le plan de contrôle d’Anthropic peut envoyer des listes de règles avec une session et demander au runner de les appliquer. Certaines entrées peuvent être des règles rédigées par un administrateur de votre organisation. Les listes sont environment, soft_deny et allow :
environment: une entrée peut amener le classifieur à autoriser davantage comme à autoriser moins.soft_deny: une entrée bloque une action sauf si l’utilisateur l’a explicitement demandée ou si une exceptionallows’applique.allow: les exceptions aux entréessoft_deny.
no-allow: la valeur par défaut. Appliqueenvironmentetsoft_denyet retientallow. Une entréeenvironmentpeut toujours amener le classifieur à autoriser davantage, donc la valeur par défaut n’exclut pas tout assouplissement.all: applique les trois listes.none: n’en applique aucune. Choisisseznonepour exclure tout assouplissement provenant de ces listes. Cela supprime également les restrictionssoft_deny.
--log-level debug. Pour chaque session, le runner journalise alors une ligne contenant the server asked this runner to apply, ou une ligne contenant the server did not ask this runner to apply the auto mode lists it sends.
Drapeaux CLI de l’orchestrateur
La sous-commandeself-hosted-runner orchestrator, qui génère les runners à la demande, accepte --api-url, --environment-secret-file, --hooks-dir, --health-port et --log-level avec les mêmes valeurs par défaut que le runner et, où le drapeau du runner en a une, la même variable d’environnement, sauf que --hooks-dir est requis et doit contenir un hook spawn-runner. Il prend également ses propres drapeaux :
Drapeaux du connecteur SCM
Le connecteur SCM n’est pas disponible, donc laissez les drapeaux de cette section non définis. Si vous définissez--scm-connector-host, la connexion ne s’ouvre pas, et l’orchestrateur continue à la réessayer. Les runners commencent toujours en tant que sessions en file d’attente.
Le connecteur est une connexion WebSocket permanente de l’orchestrateur au plan de contrôle d’Anthropic. Il est conçu pour permettre aux flux pré-session hébergés, tels que le sélecteur de dépôt et le résolveur de branche ou de ref, d’atteindre un hôte GitHub Enterprise Server qui n’est routable que de l’intérieur de votre réseau. Consultez Exigences réseau sur la page GitHub Enterprise Server pour voir ce dont ces flux ont besoin.
À chaque tentative de connexion, l’orchestrateur envoie son secret d’environnement existant, et il réessaye automatiquement avec un backoff exponentiel, plafonné à 30 secondes plus une gigue.
Paramètres réservés aux variables d’environnement
Ces paramètres du runner sont lus uniquement à partir de l’environnement et couvrent le comportement que la plupart des déploiements laissent à la valeur par défaut :Télémétrie
Les enfants de session envoient la télémétrie opérationnelle à Anthropic sauf si vous la désactivez. Aucun code ou contenu de dépôt n’est envoyé. Définir les variables de télémétrie sur le processus du runner ; le runner les réaffirme après l’application des variables d’environnement fournies par le serveur, donc le paramètre de l’opérateur a toujours la priorité. Un contrôle est spécifique aux environnements auto-hébergés :CLAUDE_CODE_BYOC_ENABLE_DATADOG=1 opte pour les métriques opérationnelles Datadog, qui sont désactivées par défaut dans les environnements auto-hébergés. Les contrôles de télémétrie Claude Code généraux, DISABLE_TELEMETRY, DO_NOT_TRACK, DISABLE_ERROR_REPORTING et CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, s’appliquent aux enfants de session comme documenté dans la référence des variables d’environnement. DISABLE_GROWTHBOOK est connexe mais différent : définir DISABLE_GROWTHBOOK=1 désactive la récupération des drapeaux de fonctionnalité, et la télémétrie reste activée sauf si DISABLE_TELEMETRY est également défini.
CLAUDE_CODE_ENABLE_TELEMETRY n’est pas connexe : il active l’export OpenTelemetry vers votre propre collecteur, comme décrit dans Surveillance, et ne contrôle pas l’analytique d’Anthropic.
Point de terminaison de santé
Le runner sertGET /healthz sur le port de santé configuré. La réponse est 200 OK chaque fois que le processus est actif, quel que soit l’état de la boucle d’interrogation, donc une sonde HTTP sur ce point de terminaison détecte uniquement un processus mort. Le corps JSON décrit l’état actuel :
last_poll_age_ms comme signal de vivacité dans les sondes personnalisées ; une valeur qui croît sans limite indique que la boucle d’interrogation est bloquée. À la fois last_poll_at et last_poll_age_ms sont null jusqu’à la fin de la première interrogation.
Le /healthz propre à l’orchestrateur, sur son port de santé, retourne toujours 200. Le corps porte un champ connected signalant si l’interrogation la plus récente a réussi, plus les comptes de file d’attente de génération par état dans queue_counts. Pour savoir pourquoi connected vaut false, lisez le champ de premier niveau last_error, que chaque interrogation réussie réinitialise à null. Gater la disponibilité et les alertes sur connected plutôt que sur le code de statut.
Quand le connecteur SCM est configuré, le corps /healthz de l’orchestrateur porte également scm_connector_connected et un objet scm_connector avec connected, last_connected_at, last_error, reconnects et requests_forwarded. Les deux champs sont null quand --scm-connector-host n’est pas défini.
Métriques Prometheus
Chaque runner expose les métriques Prometheus àGET /metrics sur le même port que /healthz. Séries clés :
L’orchestrateur expose ses propres séries à
GET /metrics sur le même port que son /healthz :
Pour l’autoscaling, choisissez la série qui correspond à votre style de scaling et contrôlez-la avant qu’elle n’alimente le scaler :
- Scaling basé sur la profondeur de queue : alimentez
claude_code_self_hosted_orchestrator_pool_pending_sessionsdans votre scaler HPA ou KEDA, pasqueue_pending_sessions. - Scaling basé sur la capacité : mettez à l’échelle sur le ratio des
active_sessionsdu runner àcapacity. - Contrôle sur
connected: filtrez la requête avecclaude_code_self_hosted_orchestrator_connected == 1par instance, afin qu’une valeur obsolète d’un replica déconnecté n’alimente pas le scaler.
ignoreNullValues: "true" par défaut lit le résultat vide comme zéro et réduit ; définissez ignoreNullValues: "false" sur le ScaledObject, optionnellement avec un plancher de replicas fallback.
Le PodMonitor suivant de Prometheus Operator couvre les deux processus. Il sélectionne les pods par le label app.kubernetes.io/part-of: claude-code-self-hosted-runner et le port nommé health que la recette Kubernetes définit ; ajustez les namespaces pour correspondre à votre déploiement :
Exemples de règles d’alerte
Ces règles d’alerte d’exemple sont un point de départ ; ajustez les seuils pour la taille de votre flotte :Alerter sur les runners perdus et les sessions en attente
Sur une flotte fixe, chargezClaudeRunnersBelowFloor. Avec des runners à la demande, chargez plutôt ClaudeOrchestratorSessionsWaiting et ClaudeOrchestratorQueueWaitHigh.
Alerter lorsqu’une flotte fixe perd des runners
ClaudeRunnersBelowFloor se déclenche lorsqu’il reste, pendant 10 minutes, moins de runners enregistrés et scrapés que le plancher :
- Plancher : définissez le
2dansexprà environ la moitié de votre nombre de replicas, arrondi au supérieur. Avec trois replicas, conservez2, et l’alerte se déclenche lorsqu’il reste un runner ou aucun. - Namespace : remplacez
claude-runnersdans le matcher et danslabels, et copiez l’alerte pour chaque namespace supplémentaire. Si vos cibles n’ont pas de labelnamespace, supprimez le matcher et le label, sinon l’alerte lit 0 et se déclenche. ClaudeRunnerPollStaleetClaudeRunnerPollErrors: conservez-les chargées depuis les exemples de règles d’alerte, carClaudeRunnersBelowFloorcompte toujours un runner qui ne peut pas poller
Alerter lorsque des sessions attendent des runners à la demande
ClaudeOrchestratorSessionsWaiting se déclenche lorsque le nombre de sessions en attente d’un runner reste supérieur à 0 pendant 10 minutes. ClaudeOrchestratorQueueWaitHigh se déclenche lorsque plus de 1 % des attentes en queue des 10 dernières minutes ont dépassé 160 secondes, et que cela persiste pendant 5 minutes :
- Seuil : si une session est toujours en attente, relevez le
> 0dansClaudeOrchestratorSessionsWaitingau-dessus du nombre que vous observez habituellement ClaudeOrchestratorDisconnected: conservez-la chargée depuis les exemples de règles d’alerte, carClaudeOrchestratorSessionsWaitingcesse de se déclencher environ 2 minutes après la déconnexion du dernier orchestrateur du namespace
Passer les métriques enfants de session
Chaque session s’exécute dans son propre processus enfant avec ses propres métriques OpenTelemetry ; à--capacity au-dessus d’un, le runner réécrit comment ces métriques enfants sont exposées. Définir OTEL_METRICS_EXPORTER=prometheus sur l’hôte du runner et CLAUDE_CODE_ENABLE_TELEMETRY=1 dans l’environnement de la session, par exemple à partir de votre script wrapper ou l’environnement du runner lui-même, que les sessions héritent, réexpose les instruments de compteur et de jauge de chaque enfant sur le propre endpoint /metrics du runner, aux côtés des séries du runner. Le runner réécrit l’exporteur de l’enfant pour pousser sur OTLP vers un récepteur loopback uniquement sur le port de santé, étiquette chaque série avec les labels session_id et client_platform, et évince les séries d’une session quand cette session se termine. Les histogrammes ne passent pas, et une métrique enfant dont le nom entrerait en collision avec le propre préfixe du runner est supprimée.
À la --capacity 1 par défaut, la réécriture ne s’applique pas : l’enfant de la session lie son propre endpoint Prometheus sur le port 9464 comme d’habitude.
Associer les métriques d’une session à celles du runner
Pour voir ce qu’ont coûté les sessions inactives, effectuez une jointure entre la métriqueclaude_code_self_hosted_runner_session_idle_seconds du runner et la métrique de coût de Claude Code sur ccr_session_id. La métrique du runner ne porte pas ce label ; ajoutez-le donc avec label_replace, comme dans cette requête :
claude_code_cost_usage_total dans la requête. La requête fonctionne quelle que soit la valeur de --capacity.
session_id: sur le port 9464, ce label sur les métriques Claude Code contient lesession.idpropre à Claude Code, qui ne correspond à aucune série du runner. Une jointure sur celui-ci ne renvoie rien ; effectuez donc la jointure surccr_session_id.- Les métriques Claude Code n’ont pas de
ccr_session_id: vérifiez queOTEL_METRICS_INCLUDE_SESSION_IDn’est pas défini surfalse
Sémantique des compteurs du cycle de vie de la session
Les compteurssessions_started_total, sessions_completed_total, sessions_failed_total, et sessions_interrupted_total classent chaque session par la façon dont elle s’est terminée. Chaque enfant de session généré incrémente sessions_started_total au moment du spawn, et exactement un des trois autres incrémente à la sortie, donc sessions_started_total moins la somme des trois autres égale le nombre d’enfants de session actuellement en cours d’exécution.
completed: la session s’est terminée correctement. Cela couvre l’enfant quittant de lui-même avec le code0, la session étant archivée ou supprimée tandis que l’enfant était toujours connecté, et le runner remettant le slot correctement : libérant la session au timeout d’inactivité, au temps de retraite, ou à la limite--kill-session-after-min; un timeout de démarrage ; ou une désassignation côté serveur que la boucle de poll a remarquée avant que l’enfant ne quitte. Incrémentesessions_completed_total.failed: l’enfant a quitté de lui-même avec un code non-zéro, soit un crash soit un échec de configuration après spawn. Incrémentesessions_failed_total.interrupted: le runner a terminé l’enfant pour une raison opérationnelle qui n’est ni un succès de session ni une faute du runner, comme un drain, ou terminer une session qui était toujours sur le runner quand la fenêtre de grâceSELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MSaprès sa limite--kill-session-after-mins’est terminée. Un redémarrage roulant Kubernetes envoyantSIGTERMest un exemple de drain. Incrémentesessions_interrupted_total.
--kill-session-after-min et la comptait dans sessions_interrupted_total.
Le hook post-session classifie différemment les remises propres avec CLAUDE_RUNNER_EXIT_REASON. Le hook les signale comme interrupted, parce que le runner a arrêté l’enfant : une libération, un timeout de démarrage, une désassignation serveur, et un archivage ou une suppression que le poll a remarqué en premier. Ces compteurs enregistrent les mêmes événements que completed, parce que le slot a été remis correctement.
Si vous réconciliez les reçus de hook directement contre sessions_completed_total, vous sous-comptez les complétions. Utilisez le hook pour les garanties par session et les compteurs pour les taux agrégés.
Sur un environnement one-shot, --capacity 1 avec le --drain-grace-sec 0 par défaut, chaque processus runner quitte peu de temps après la fin de sa session. sessions_completed_total, sessions_failed_total, et sessions_interrupted_total incrémentent uniquement à la fin de la session, juste avant cette sortie, donc un scrape Prometheus toutes les 15 à 60 secondes attrape rarement l’incrément avant que les séries du runner ne disparaissent ; ces trois compteurs de fin de session sont les compteurs terminaux auxquels le reste de cette section se réfère. sessions_started_total incrémente au spawn et reste visible pour la durée de vie de la session, donc il s’affiche de manière fiable, mais sur un environnement one-shot il se lit plus proche de « sessions actuellement en cours d’exécution » qu’un compte cumulatif.
Utilisez la série dans ce tableau pour l’objectif correspondant au lieu des compteurs terminaux :
Les lignes
orchestrator_* n’existent que sur les environnements exécutant l’orchestrateur à la demande. Sur une flotte fixe dont les runners survivent à leurs sessions, avec --drain-grace-sec au-dessus de 0, utilisez sum(rate(claude_code_self_hosted_runner_sessions_started_total[5m])) pour le débit ; sur une flotte one-shot cette série a le même problème de fenêtre de scrape que les compteurs terminaux, donc fiez-vous au comptage des sessions en queue à la place. Vérifiez l’arriéré sur l’onglet Activity de l’environnement, sur la page d’administration Cloud environments : les runners n’exportent pas une série de profondeur de queue.
Pour le rapport de résultat par session, utilisez le hook post-session à la place : il se déclenche à chaque fin de session où un processus enfant a été généré, à part la terminaison abrupte du runner comme une préemption VM, selon le propre contrat du hook.
Étapes suivantes
- Environnements auto-hébergés : le modèle d’environnement, de runner et de session ; le guide de démarrage rapide et Déployer en production contiennent la configuration et les opérations
- Personnaliser les sessions : scripts wrapper, hooks de cycle de vie et runners à la demande
- Vérifier l’identité de la session : le token de session, ses revendications et comment le vérifier