SpyBara
Go Premium

self-hosted-environments-reference.md 2026-09-17 05:00 UTC to 2026-09-18 23:58 UTC

This page contains 80 additions and 73 deletions.

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

Référence des environnements auto-hébergés

Référence complète pour le runner et l'orchestrateur auto-hébergés : drapeaux CLI, variables d'environnement et métriques Prometheus.

Cette page est la référence pour les deux processus que vous exécutez dans un environnement auto-hébergé : le runner, qui exécute les sessions cloud Claude Code sur vos hôtes, et l'orchestrateur d'autoscaling optionnel, qui démarre les runners à mesure que les sessions s'accumulent. Chacun a sa propre table de drapeaux. Les deux s'exécutent sur des hôtes Linux ou macOS, pour lesquels les valeurs par défaut telles que /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.

Drapeau Variable d'env Par défaut Description
--api-url <url> aucune https://api.anthropic.com URL de base de l'API. À remplacer uniquement pour les tests.
--base-dir <path> SELF_HOSTED_RUNNER_BASE_DIR /workspace ; aucune sur Windows Répertoire pour les clones de dépôts et les répertoires de travail par session. Le runner a besoin d'un accès en écriture à ce chemin ou à son parent. Le runner crée le répertoire au démarrage et se termine avec cannot create or write to base directory quand il ne peut pas le créer ou y écrire. Avant v2.1.225, le runner créait le répertoire au démarrage de la première session, donc un chemin inutilisable échouait les sessions plutôt que le démarrage. Sur Windows, qui n'est pas un hôte runner supporté, il n'y a pas de valeur par défaut : le runner se termine au démarrage sauf si vous passez le drapeau ou définissez la variable. Utilisez la même valeur sur chaque runner dans un environnement. Voir Garder le répertoire de base et la capacité identiques sur tous les runners.
--capacity <n> aucune 1 Nombre maximum de sessions simultanées que ce runner gère. Toutes les sessions appartiennent au même propriétaire verrouillé. Utilisez la même valeur sur chaque runner dans un environnement ; voir Garder le répertoire de base et la capacité identiques sur tous les runners.
--client-label <label> SELF_HOSTED_RUNNER_CLIENT_LABEL le nom d'hôte de l'hôte Étiquette que le runner envoie lors de son enregistrement. Le runner la signale également comme l'étiquette client_label de claude_code_self_hosted_runner_info. Nécessite Claude Code v2.1.248 ou ultérieur.
--configure-git SELF_HOSTED_RUNNER_CONFIGURE_GIT=1 désactivé Au démarrage, écrire l'identité git globale, activer la signature de commit Anthropic, activer la négociation de push git, et installer des hooks de commit qui ajoutent une remorque Co-authored-by:. La négociation de push nécessite Claude Code v2.1.257 ou ultérieur. Voir Configurer git.
--confine-repo-settings <mode> SELF_HOSTED_RUNNER_CONFINE_REPO_SETTINGS warn Définit le mode de la garde qui signale une session quand les paramètres validés d'un dépôt tentent d'accorder un accès en écriture ou en lecture en dehors de l'espace de travail de cette session, de définir des variables d'environnement ou de remplacer la posture sandbox ou hooks de l'opérateur, comme sandbox.enabled: false ou disableAllHooks. Le warn par défaut enregistre la violation et démarre quand même la session, enforce refuse la session, et off désactive l'analyse. Voir Renforcer votre déploiement.
--debug-token-dir <path> SELF_HOSTED_RUNNER_DEBUG_TOKEN_DIR non défini Écrire les tokens en direct sur le disque pour inspection. Débogage uniquement ; ne pas utiliser en production.
--defer-shutdown-max-min <n> SELF_HOSTED_RUNNER_DEFER_SHUTDOWN_MAX_MS 0 Au premier SIGTERM ou SIGINT, continuer à servir les sessions déjà attachées au lieu de les drainer, puis libérer tout ce qui est encore attaché N minutes plus tard et quitter. Augmentez le délai d'arrêt de votre hôte avant de définir ceci. Voir Différer le drainage après le premier signal. 0 désactive. Nécessite Claude Code v2.1.238 ou ultérieur.
--drain-grace-sec <n> SELF_HOSTED_RUNNER_DRAIN_GRACE_MS 0 Jusqu'à ce que le runner reçoive un signal d'arrêt ou atteigne son heure de retraite, contrôle quand le runner se termine après la fin de ses sessions actives : 0 se termine immédiatement sans interrogation supplémentaire, et une valeur positive garde le runner actif et réinterroge la file d'attente du propriétaire verrouillé pendant ce nombre de secondes d'abord, au prix de l'isolation de conteneur par session décrite dans la section de renforcement. Après un premier signal que vous avez différé avec --defer-shutdown-max-min, le runner se termine dès qu'il ne détient aucune session, quelle que soit la valeur que vous définissez ici.
--drain-marker-file <path> SELF_HOSTED_RUNNER_DRAIN_MARKER_FILE non défini Fichier marqueur que votre hôte écrit pour annoncer un drainage gracieux avant d'envoyer SIGTERM. Quand le fichier existe au démarrage du drainage, le runner signale sa sortie à Anthropic comme un drainage d'hôte plutôt qu'un simple signal d'arrêt. Le drainage lui-même, y compris la retenue --drain-wait-sec, s'exécute de la même manière que sans le drapeau. Nommez un chemin sur un système de fichiers local que les sessions ne peuvent pas écrire. Nécessite Claude Code v2.1.271 ou ultérieur.
--drain-wait-sec <n> SELF_HOSTED_RUNNER_DRAIN_WAIT_MS 0 Une fois le drainage commencé, qui se fait sur SIGTERM sauf si vous définissez --defer-shutdown-max-min, attendez jusqu'à N secondes pour que le tour en vol de chaque session et les tâches de fond se terminent avant de terminer l'enfant. Pendant cette attente, le runner compte une tâche de fond qui vient de se terminer comme toujours en cours d'exécution jusqu'au tour de suivi qui lit son résultat commence, pendant au maximum la fenêtre SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS.
--environment-secret-file <path> SELF_HOSTED_RUNNER_ENVIRONMENT_SECRET requis Chemin vers un fichier contenant le secret d'environnement, ou, pour les runners générés par l'orchestrateur, le JWT de bon de travail à usage unique. SELF_HOSTED_RUNNER_ENVIRONMENT_SECRET porte la valeur secrète directement, pas un chemin de fichier. L'ancien drapeau --pool-secret-file et la variable SELF_HOSTED_RUNNER_POOL_SECRET fonctionnent toujours et impriment un avis de dépréciation sur stderr ; les builds de runner du programme d'aperçu plus anciens que 2.1.216 ne reconnaissent que ces anciens noms.
--exec-path <path> SELF_HOSTED_RUNNER_EXEC_PATH binaire propre Binaire ou script wrapper à générer pour chaque session. Voir Scripts wrapper.
--exit-if-unused-min <n> SELF_HOSTED_RUNNER_IDLE_SHUTDOWN_MS 0 Quitter après N minutes d'interrogation sans travail jamais assigné, pour la réduction d'échelle de l'autoscaler. 0 désactive.
--git-host-rewrite <from>=<to> aucune non défini Réécrire les URL sources https://<from>/... en https://<to>/... avant le clonage, pour DNS à horizon divisé. Répétable ; drapeau uniquement.
--git-ssh-rewrite <host> aucune non défini Réécrire les URL sources https://<host>/... en git@<host>:... avant le clonage, pour les hôtes git SSH uniquement. Répétable ; drapeau uniquement.
--health-port <port> SELF_HOSTED_RUNNER_HEALTH_PORT 8080 Port pour l'écouteur /healthz et /metrics. Définir 0 pour désactiver.
--hooks-dir <path> SELF_HOSTED_RUNNER_HOOKS_DIR non défini Répertoire des scripts de hook de cycle de vie. Voir Hooks de cycle de vie.
--host-config-snapshot <mode> SELF_HOSTED_RUNNER_HOST_CONFIG_SNAPSHOT disk Où le runner garde l'instantané de démarrage du répertoire de configuration d'hôte qu'il amorce chaque session à partir de. disk copie l'instantané dans un répertoire appartenant au runner sous --base-dir et, à chaque démarrage de session, vérifie chaque fichier par rapport à un digest en mémoire. Si un fichier dans la copie a été modifié, la session échoue et le runner refuse les sessions jusqu'à ce que vous le redémarriez. memory garde l'instantané entier sur le tas, limité à 64 MiB ; au-delà de la limite, les sessions démarrent sans configuration d'hôte et affichent un avis le disant. Quand le runner ne peut pas écrire l'instantané disque, il enregistre l'échec et utilise memory pour cette exécution. Nécessite Claude Code v2.1.271 ou ultérieur.
--kill-session-after-min <n> SELF_HOSTED_RUNNER_MAX_LIFETIME_MS 0 Limiter une session à N minutes en temps réel, comme limite de sécurité pour les sessions bloquées. Sur v2.1.260 ou ultérieur, le runner libère une session qui atteint la limite afin qu'elle puisse reprendre au prochain message de son utilisateur, et la termine uniquement si elle est toujours sur le runner quand la fenêtre de grâce SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS se termine. Avant v2.1.260, le runner terminait la session à la limite. Voir Certaines sessions ne comptent pas comme inactives pour les détails et comment choisir une valeur. 0 désactive.
--lock-to-account <id> SELF_HOSTED_RUNNER_LOCK_TO_ACCOUNT non défini Pré-verrouiller le runner à un compte spécifique au démarrage au lieu de verrouiller à la première session. Accepte une adresse e-mail ou un ID user_... dans l'organisation de l'environnement. Un runner pré-verrouillé ne récupère jamais les sessions du canal Claude Tag, qui n'ont pas de compte.
--log-file <path> SELF_HOSTED_RUNNER_LOG_FILE non défini Refléter les logs du runner vers un fichier en plus de stdout et stderr, créé avec les permissions 0600. Requis pour que self-hosted-runner doctor suive les logs localement.
--log-level <level> aucune info info ou debug
--post-session-hook-timeout-sec <n> SELF_HOSTED_RUNNER_POST_SESSION_HOOK_TIMEOUT_MS 60 Budget pour le hook post-session à la fin de chaque session, y compris l'arrêt du runner
--proxy-authorization-command <command> SELF_HOSTED_RUNNER_PROXY_AUTHORIZATION_COMMAND non défini Commande shell que le runner exécute pour chaque connexion à votre proxy de sortie, en utilisant sa stdout coupée comme valeur d'en-tête Proxy-Authorization. Nécessite HTTPS_PROXY ou HTTP_PROXY, et ne peut pas être combiné avec --proxy-authorization-file. Voir S'authentifier auprès d'un proxy de sortie. Nécessite Claude Code v2.1.238 ou ultérieur.
--proxy-authorization-file <path> SELF_HOSTED_RUNNER_PROXY_AUTHORIZATION_FILE non défini Fichier que le runner lit pour chaque connexion à votre proxy de sortie, en utilisant son contenu coupé comme valeur d'en-tête Proxy-Authorization. Utilisez ce drapeau pour un token qu'un autre processus fait tourner en place. Porte les mêmes exigences que --proxy-authorization-command, et ne peut pas être combiné avec lui. Voir S'authentifier auprès d'un proxy de sortie. Nécessite Claude Code v2.1.238 ou ultérieur.
--push-outcome-on-release SELF_HOSTED_RUNNER_PUSH_OUTCOME_ON_RELEASE désactivé À la fin d'une session initiée par le runner comme un drainage ou une libération inactive, pousser les branches de résultat suivies vers origin avant de supprimer l'espace de travail, afin que les commits en vol survivent à un redémarrage. Meilleur effort ; ajoute 30 secondes au budget d'arrêt, et nécessite git 2.29 ou plus récent pour reprendre à partir de la branche poussée. Restreindre l'accès en push aux refs claude/* avant d'activer ; voir Les sessions reprises perdent le travail non poussé. Les dépôts extraits via un hook de cycle de vie checkout ne sont pas poussés ; prenez des snapshots de ceux-ci à partir du hook post-session à la place.
--release-idle-session-min <n> SELF_HOSTED_RUNNER_SESSION_IDLE_MS 0 Libérer un créneau de session après N minutes d'inactivité une fois qu'un tour se termine ou que la session attend l'action de l'utilisateur. Une session qui est toujours au milieu d'un tour, y compris une qui détient une tâche de fond qui ne finit jamais ou une approbation demandée de l'intérieur d'un appel d'outil en cours d'exécution, ne compte pas comme inactive ; associer avec --kill-session-after-min comme butée dure. Après la fin de la tâche de fond d'une session, le runner considère la session comme occupée jusqu'au tour de suivi qui lit le résultat commence, pendant au maximum la fenêtre SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS. Jusqu'à ce que le runner reçoive un signal d'arrêt ou atteigne son heure de retraite, une libération qui laisse le runner sans sessions actives démarre le même chemin de sortie qu'un drainage normal, gouverné par --drain-grace-sec. Après un premier signal que vous avez différé avec --defer-shutdown-max-min, le runner se termine dès qu'une libération le laisse sans sessions. 0 désactive.
--remove-session-state [bool] SELF_HOSTED_RUNNER_REMOVE_SESSION_STATE désactivé Supprimer les répertoires par session d'une session sous <base-dir>/_sessions/ quand la session se termine sur ce runner, quel que soit le résultat. Réutiliser un checkout pré-chauffé décrit ce qu'ils contiennent et qui peut les lire quand ils restent. La suppression est meilleur effort : les répertoires par session restent en place quand le runner est tué ou atteint sa date limite de drainage avant que le nettoyage ne s'exécute. Avec le drapeau activé, le log de débogage d'une session échouée ou interrompue n'est pas conservé sur le disque. Nécessite Claude Code v2.1.268 ou ultérieur.
--retire-at <epoch-seconds> SELF_HOSTED_RUNNER_RETIRE_AT non défini Retirer le runner à un timestamp Unix absolu en secondes, pour l'infrastructure qui tue le runner à un moment connu ; Cycle de vie du runner décrit la séquence de libération et comment dimensionner la marge. Les valeurs avant 2001 ou après l'année 5138 sont rejetées par le drapeau et ignorées par la variable d'environnement.
--session-stop-grace-sec <n> SELF_HOSTED_RUNNER_SESSION_STOP_GRACE_MS 5 Combien de temps attendre que le processus Claude se termine proprement après la fin d'une session, avant de le tuer de force. Augmentez la valeur si les hooks SessionEnd propres de l'enfant ont besoin de plus de temps.
--startup-timeout-min <n> SELF_HOSTED_RUNNER_STARTUP_TIMEOUT_MS 15 Libérer un créneau de session si l'enfant n'a pas signalé qu'il s'était initialisé dans N minutes après le lancement. Effacé par le signal d'init de l'enfant sur le canal d'activité, pas par la sortie ordinaire, après quoi --release-idle-session-min prend le relais. 0 désactive.
--trust-workspace [bool] SELF_HOSTED_RUNNER_TRUST_WORKSPACE activé Amorcer la confiance persistante pour les chemins de dépôt de chaque session afin que les permissions.allow et additionalDirectories validés par le dépôt soient honorés. Définir false pour supprimer les subventions de permission validées par le dépôt et configurer les règles d'autorisation dans le settings.json de la configuration d'hôte à la place ; les paramètres sandbox.* validés par le dépôt s'appliquent toujours de toute façon, c'est pourquoi la garde de paramètres de dépôt les analyse indépendamment de ce drapeau.
--use-anthropic-git-proxy CLAUDE_RUNNER_USE_GIT_PROXY=1 désactivé Cloner via le proxy git Anthropic au lieu de l'authentification git gérée par le client. Nécessite --capacity 1 et git 2.32 ou plus récent ; le runner refuse de démarrer sinon. Remplace les drapeaux de réécriture.

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.

Drapeaux CLI de l'orchestrateur

La sous-commande self-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 :

Drapeau Par défaut Description
--hook-concurrency <n> 4 Nombre maximum de hooks spawn-runner s'exécutant en parallèle. Limite également le nombre de demandes de génération réclamées par interrogation.
--hook-timeout <sec> 60 Terminer l'arborescence des processus du hook après ce nombre de secondes. Le délai d'attente plus sa grâce de suppression de 5 secondes doit rester en dessous de --expected-spawn-seconds ; l'orchestrateur applique ceci au démarrage.
--expected-spawn-seconds <sec> 120 Temps de démarrage p99 attendu pour les runners générés, dans la plage appliquée par le serveur 10 à 3600. Envoyé à chaque interrogation comme le bail côté serveur ; si aucun runner ne s'enregistre avant son expiration, la session est re-proposée avec un nouvel ID de commande. Tous les réplicas doivent partager cette valeur.
--min-idle <n> 0 Garder au moins N créneaux de session inactifs libres en générant proactivement des runners de secours. 0 désactive le préchauffage. Associer avec le --exit-if-unused-min du runner afin que les runners de secours excédentaires se réclament eux-mêmes.
--debug-dir <path> non défini Écrire le bon de travail de chaque demande de génération et la stderr du hook sur le disque. Débogage uniquement ; ne jamais définir en production.

Drapeaux du connecteur SCM

L'orchestrateur peut maintenir une connexion WebSocket permanente au plan de contrôle d'Anthropic afin que les flux pré-session hébergés, comme le sélecteur de dépôt et le résolveur de branche ou de ref, puissent atteindre un hôte GitHub Enterprise Server qui n'est routable que de l'intérieur de votre réseau. Le connecteur reste désactivé sauf si vous définissez --scm-connector-host.

Drapeau Par défaut Description
--scm-connector-host <host[:port]> non défini Nom d'hôte GitHub Enterprise Server vers lequel transférer les demandes. Le port par défaut est 443. Définir ce drapeau active le connecteur.
--scm-connector-id <n> requis avec --scm-connector-host L'ID numérique de la connexion GitHub Enterprise Server de votre organisation. Contactez votre équipe de compte Anthropic pour la valeur quand vous activez le connecteur.
--scm-connector-provider <slug> ghe Segment de chemin identifiant le fournisseur, correspondant à ^[a-z0-9-]{1,32}$.
--scm-connector-ca-file <path> non défini Bundle CA supplémentaire, au format PEM, pour les connexions TLS à l'hôte GitHub Enterprise Server.
--scm-connector-host-rewrite <from>=<to_host:to_port> non défini Pour les tests de bout en bout uniquement : redirige la connexion TCP tout en gardant l'en-tête Host et TLS SNI comme --scm-connector-host.

Le connecteur s'authentifie avec le secret d'environnement existant de l'orchestrateur et se reconnecte automatiquement : avec backoff exponentiel sur une connexion abandonnée, ou un délai fixe de 30 secondes quand le plan de contrôle ferme la connexion parce qu'un autre réplica d'orchestrateur la détient déjà.

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 :

Variable d'env Par défaut Description
SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS 30000 Combien de temps le runner considère une session comme occupée après la fin d'une tâche de fond tandis que le tour de suivi qui lit le résultat n'a pas commencé. Les lignes --drain-wait-sec et --release-idle-session-min décrivent où la retenue s'applique au drainage et à la libération inactive, et Cycle de vie du runner décrit où elle s'applique à la retraite --retire-at. 0 ou une valeur inutilisable revient à la valeur par défaut, donc la retenue ne peut pas être désactivée. Nécessite Claude Code v2.1.228 ou ultérieur.
SELF_HOSTED_RUNNER_HOST_CONFIG_DIR ~/.claude Répertoire capturé dans le snapshot de démarrage du runner et amorcé dans le CLAUDE_CONFIG_DIR de chaque session ; les modifications sur le disque s'appliquent après un redémarrage du runner. Définir la variable déplace également l'endroit où le runner lit .claude.json pour l'amorçage MCP, donc le définir, y compris à sa propre valeur par défaut, relocalise cette recherche ; pointez vers un répertoire vide pour désactiver complètement l'amorçage.
SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS 900000 Combien de temps le runner attend après qu'une session atteigne sa limite --kill-session-after-min, pour qu'un tour en cours se termine ou que la libération se termine, avant de terminer la session
SELF_HOSTED_RUNNER_SIGKILL_GRACE_MS 30000 Combien de temps le runner attend que le système d'exploitation livre SIGKILL à un enfant bloqué dans les E/S non interruptibles avant de se terminer lui-même. Plancher à --post-session-hook-timeout-sec plus 15 secondes, et 30 de plus quand --push-outcome-on-release est défini, donc le minimum effectif est 75 secondes aux valeurs par défaut.
CLAUDE_RUNNER_FETCH_DEPTH 50 Profondeur de récupération git pour les clones frais. Définir un entier positif, ou full ou 0 pour une récupération complète. Les dépôts déjà présents dans l'espace de travail conservent leur profondeur existante.
CLAUDE_RUNNER_SKIP_GIT_VERIFY non défini Quand 1, ignorer la vérification de présence .git après l'exécution d'un hook checkout. Définir ceci quand votre hook matérialise une source non-git.
FORCE_AUTOUPDATE_PLUGINS non défini Quand 1, laisser les marchés de plugins se mettre à jour automatiquement même si le binaire est épinglé
CLAUDE_CODE_DISABLE_ARTIFACT non défini Quand 1, désactiver l'outil Artifact dans les sessions indépendamment du paramètre d'administration de l'organisation, et supprimer l'exigence de sortie *.frame.claudeusercontent.com

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

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

Utilisez 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.

L'orchestrateur sert son propre /healthz sur son port de santé. Son point de terminaison retourne toujours 200, et 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. 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 :

Série Notes
claude_code_self_hosted_runner_info{runner_id,version,client_label} Toujours 1 ; utile pour l'inventaire de la flotte et la détection de dérive de version
claude_code_self_hosted_runner_capacity --capacity configurée
claude_code_self_hosted_runner_active_sessions Sessions actuellement en cours d'exécution
claude_code_self_hosted_runner_locked_account{email} Présente une fois que le runner s'est verrouillé sur un utilisateur et qu'un jeton de session portant une revendication act.email a été émis. La série est absente sur un runner verrouillé sur un agent Claude Tag, dont les jetons de session ne portent pas act.email. La valeur du label est l'email du compte ; si votre magasin de métriques est largement lisible, supprimez ou hashifiez le label au moment du scrape, par exemple avec les metric_relabel_configs de Prometheus.
claude_code_self_hosted_runner_last_poll_age_seconds Secondes depuis le dernier poll réussi. Alertez si plus de 60.
claude_code_self_hosted_runner_poll_errors_total{error_kind} Cumul des échecs PollWork par type : transport, timeout, 5xx, 429, ou 4xx. Les cinq séries sont présentes depuis le démarrage du processus ; alertez sur rate(...[5m]) > 0.
claude_code_self_hosted_runner_sessions_started_total{client_platform} Processus enfants de session générés au cours de la durée de vie du runner, une série par origine de session telle que web_claude_ai, ios, android, desktop_app, ou claude_code_cli, ou unknown quand le serveur n'en a pas envoyé. Les sessions Slack portent soit claude_in_slack soit claude-in-slack selon l'intégration Slack qui les a créées, donc faites correspondre les deux avec un sélecteur regex tel que {client_platform=~"claude[-_]in[-_]slack"}. Utilisez sum() pour le total de la flotte.
claude_code_self_hosted_runner_sessions_completed_total{client_platform} Sessions qui se sont terminées correctement, étiquetées de la même manière. Plus large qu'une simple sortie propre : voir sémantique des compteurs du cycle de vie de la session pour ce qui compte.
claude_code_self_hosted_runner_sessions_failed_total{client_platform} Sessions qui se sont terminées en échec, étiquetées de la même manière. Même mise en garde : voir sémantique des compteurs du cycle de vie de la session.
claude_code_self_hosted_runner_sessions_interrupted_total{client_platform} Sessions que le runner a terminées pour une raison opérationnelle plutôt qu'un résultat de session, étiquetées de la même manière. Voir sémantique des compteurs du cycle de vie de la session.
claude_code_self_hosted_runner_initializing_sessions Sessions actuellement en phase d'initialisation, de l'assignation jusqu'à l'événement init de l'enfant
claude_code_self_hosted_runner_session_init_duration_seconds Histogramme des durées d'initialisation de session
claude_code_self_hosted_runner_session_init_errors_total Sessions qui ont échoué avant d'atteindre l'initialisation : un échec de hook de checkout, préparation git, problème de jeton, ou un crash enfant pré-init
claude_code_self_hosted_runner_session_start_hook_errors_total Hooks SessionStart qui ont signalé un résultat d'erreur, un par exécution de hook échouée
claude_code_self_hosted_runner_session_idle_seconds{session_id,client_platform} Jauge par session de secondes depuis que la session est devenue inactive. Utile pour terminer les sessions bloquées sur une invite de permission sans réponse.

L'orchestrateur expose ses propres séries à GET /metrics sur le même port que son /healthz :

Série Notes
claude_code_self_hosted_orchestrator_info{version,pool_id,orchestrator_uuid,hostname} Toujours 1
claude_code_self_hosted_orchestrator_connected 1 quand le poll le plus récent a réussi ; tombe à 0 après tout poll échoué, quel que soit le type d'échec
claude_code_self_hosted_orchestrator_last_poll_age_seconds Secondes depuis la dernière tentative de poll, succès ou échec, contrairement à la métrique identiquement nommée du runner, qui mesure depuis le dernier succès ; associez avec connected pour détecter les polls échouant. La boucle de poll de l'orchestrateur attend l'exécution du hook, donc alertez au-dessus de --hook-timeout plus une marge, environ 90 secondes par défaut, plutôt qu'un plat 60.
claude_code_self_hosted_orchestrator_poll_errors_total{error_kind} Cumul des échecs PollSpawnHints par type : transport, timeout, 5xx, 429, ou 4xx. Les cinq séries sont présentes depuis le démarrage du processus ; alertez sur rate(...[5m]) > 0.
claude_code_self_hosted_orchestrator_queue_pending_sessions Demandes de spawn revendicables maintenant
claude_code_self_hosted_orchestrator_queue_backing_off_sessions Demandes de spawn en retry backoff après un échec de hook réessayable
claude_code_self_hosted_orchestrator_queue_circuit_broken_sessions Demandes de spawn bloquées jusqu'à ce qu'un Owner les réessaie à partir de l'onglet Activity de l'environnement ; alertez si au-dessus de zéro
claude_code_self_hosted_orchestrator_pool_pending_sessions Total des sessions attendant un runner pour cet environnement. Agrégat à l'échelle de l'environnement, identique sur chaque instance d'orchestrateur : utilisez MAX plutôt que SUM entre les instances.
claude_code_self_hosted_orchestrator_pool_active_sessions Sessions actuellement assignées à un runner vivant dans cet environnement. Agrégat à l'échelle de l'environnement, identique sur chaque instance d'orchestrateur : utilisez MAX plutôt que SUM entre les instances.
claude_code_self_hosted_orchestrator_spawn_hooks_total{result} Cumul des résultats du hook spawn-runner : ok, retryable, non_retryable. Compte les invocations de hook d'orchestrateur, pas les enfants de session que les runners génèrent : non comparable à sessions_started_total, puisque la capacité au-dessus d'un, les pools chauds, et les runners générés à nouveau pour la même session divergent les deux.
claude_code_self_hosted_orchestrator_spawn_hook_duration_seconds Histogramme des durées de hook
claude_code_self_hosted_orchestrator_warm_hints_dispatched_total Demandes de spawn en attente dispatched depuis le démarrage du processus
claude_code_self_hosted_orchestrator_session_queue_wait_seconds Histogramme de secondes que chaque session a attendu dans la queue avant que l'orchestrateur la réclame pour spawn, enregistré à partir du timestamp d'attente en queue que le plan de contrôle envoie avec la demande de spawn de chaque session. Utilisez pour les alertes de temps d'attente en queue p50/p99. Les spawns de pré-warming ne sont pas échantillonnés.
claude_code_self_hosted_orchestrator_clock_skew_seconds Décalage d'horloge local moins serveur ; diagnostique, présent une fois mesuré
claude_code_self_hosted_orchestrator_scm_connector_connected 1 quand le connecteur SCM WebSocket est ouvert ; 0 pendant la composition ou le backoff. Absent quand --scm-connector-host n'est pas défini.
claude_code_self_hosted_orchestrator_scm_connector_requests_forwarded_total Cumul des requêtes HTTP proxifiées vers l'hôte SCM configuré depuis le démarrage du processus. Absent quand --scm-connector-host n'est pas défini.

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_sessions dans votre scaler HPA ou KEDA, pas queue_pending_sessions.
  • Scaling basé sur la capacité : mettez à l'échelle sur le ratio des active_sessions du runner à capacity.
  • Contrôle sur connected : filtrez la requête avec claude_code_self_hosted_orchestrator_connected == 1 par instance, afin qu'une valeur obsolète d'un replica déconnecté n'alimente pas le scaler.

Pendant une panne complète de poll, chaque replica déconnecté, la requête contrôlée ne retourne aucune donnée. HPA maintient le nombre de replicas actuel sur une métrique manquante, mais le scaler Prometheus de KEDA à son 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 :

# Exemple de PodMonitor Prometheus Operator pour le runner Claude Code
# auto-hébergé + orchestrateur. Ajustez les sélecteurs de namespace et de label
# pour correspondre à votre déploiement. Le runner et l'orchestrateur servent
# /metrics sur leur --health-port (par défaut 8080).
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
  name: claude-code-self-hosted-runner
  namespace: monitoring
spec:
  namespaceSelector:
    matchNames:
      - claude-runners
  selector:
    matchExpressions:
      # Correspond au Deployment du runner de la recette Kubernetes, plus tout
      # Job de runner à la demande et pods d'orchestrateur que vous étiquetez
      # de la même manière et donnez un containerPort 'health' nommé.
      - key: app.kubernetes.io/part-of
        operator: In
        values: [claude-code-self-hosted-runner]
  podMetricsEndpoints:
    - port: health
      path: /metrics
      interval: 30s

Ces règles d'alerte d'exemple sont un point de départ ; ajustez les seuils pour la taille de votre flotte :

# Exemple de règles d'alerte Prometheus pour le runner Claude Code auto-hébergé
# + orchestrateur. Ajustez les seuils pour la taille de votre flotte et vos 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 }} n'a pas pollé depuis >60s"
      - alert: ClaudeRunnerVersionDrift
        expr: count(count by (version) (claude_code_self_hosted_runner_info)) > 1
        for: 30m
        labels: {severity: info}
        annotations:
          summary: "Les runners exécutent des versions mixtes"
      - 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 échecs d'initialisation de session en 10m (hook de checkout / git / jeton / crash pré-init)"
      - 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 échouant ({{ $value | humanize }}/s sur 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 échecs 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: "L'orchestrateur {{ $labels.pod }} ne peut pas atteindre le plan de contrôle Anthropic"
      - alert: ClaudeOrchestratorPollStale
        expr: claude_code_self_hosted_orchestrator_last_poll_age_seconds > 90
        for: 2m
        labels: {severity: warning}
        annotations:
          summary: "L'orchestrateur {{ $labels.pod }} n'a pas pollé depuis >90s (la boucle de poll attend l'exécution du hook)"
      - alert: ClaudeOrchestratorCircuitBroken
        expr: claude_code_self_hosted_orchestrator_queue_circuit_broken_sessions > 0
        for: 1m
        labels: {severity: critical}
        annotations:
          summary: "{{ $value }} sessions circuit-broken — le hook spawn-runner est répétitivement non-réessayable ; corrigez l'infra puis réessayez à partir de l'onglet 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: "Orchestrateur {{ $labels.pod }} : PollSpawnHints échouant ({{ $value | humanize }}/s sur 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: "Orchestrateur {{ $labels.pod }} : >3 échecs de hook spawn-runner en 5m"

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.

Sémantique des compteurs du cycle de vie de la session

Les compteurs sessions_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 code 0, 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émente sessions_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émente sessions_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âce SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS après sa limite --kill-session-after-min s'est terminée. Un redémarrage roulant Kubernetes envoyant SIGTERM est un exemple de drain. Incrémente sessions_interrupted_total.

Avant v2.1.260, le runner terminait chaque session qui atteignait sa limite --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 signale une libération, un timeout de démarrage, et une désassignation serveur comme interrupted, parce que le runner a arrêté l'enfant. 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 :

Objectif Utiliser
Débit claude_code_self_hosted_orchestrator_spawn_hooks_total{result="ok"}, un compteur sur l'orchestrateur de longue durée qui incrémente une fois par hook spawn-runner réussi et reste significatif sous rate(). Il compte les invocations de hook plutôt que les sessions, donc le pré-warming et les spawns répétés pour la même session le divergent des comptages de session.
Utilisation sum(claude_code_self_hosted_runner_active_sessions) contre sum(claude_code_self_hosted_runner_capacity), les deux jauges valides à chaque scrape indépendamment de la durée de vie du runner
Arriéré claude_code_self_hosted_orchestrator_pool_pending_sessions pour la profondeur de queue, et claude_code_self_hosted_orchestrator_queue_circuit_broken_sessions, alertant si au-dessus de zéro
Échecs claude_code_self_hosted_runner_sessions_failed_total, meilleur effort : les vrais crashes après spawn l'incrémentent bien, et rate() est significatif sur les runners qui survivent à leurs sessions avec --drain-grace-sec au-dessus de 0. Un environnement one-shot a le même problème de fenêtre de scrape que les autres compteurs terminaux, donc traitez toute valeur non-zéro que vous voyez comme valant la peine d'être enquêtée. Les échecs avant spawn, comme un échec de hook de checkout, préparation git, ou un problème de jeton, n'apparaissent que dans session_init_errors_total.

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