Справочник самостоятельно размещаемых окружений
Полный справочник по самостоятельно размещаемому runner и orchestrator: флаги CLI, переменные окружения и метрики Prometheus.
Самостоятельно размещаемые окружения находятся в публичной бета-версии на планах Team и Enterprise; Owner включает их, активируя Allow self-hosted environments на странице администратора Cloud environments. Эта страница является справочником по флагам и метрикам; см. quickstart для настройки и Deploy to production для рецептов флота.
Эта страница является справочником для двух процессов, которые вы запускаете в самостоятельно размещаемом окружении: runner, который выполняет Claude Code cloud sessions на ваших хостах, и опциональный orchestrator автомасштабирования, который запускает runners по мере поступления sessions в очередь. Каждый имеет свою таблицу флагов. Оба работают на хостах Linux или macOS, для которых значения по умолчанию, такие как /workspace и ~/.claude, предполагаются. Запустите claude self-hosted-runner --help для авторитетного списка на вашей установленной версии.
Серии метрик и несколько полей API по-прежнему используют pool для того, что эти страницы называют окружением; оба термина обозначают одно и то же. ID окружения — это поле pool_id с формой ccpool_...: везде, где эти страницы показывают идентификатор pool, он обозначает окружение. Флаги CLI и переменные окружения пишут его как environment, например --environment-secret-file; устаревшие написания pool по-прежнему работают, как описывает строка --environment-secret-file.
Флаги CLI Runner
Большинство флагов имеют соответствующую переменную окружения. Когда установлены оба, флаг имеет приоритет. Флаги длительности принимают минуты или секунды в CLI, но связанная переменная окружения всегда в миллисекундах, обозначаемая суффиксом _MS, и столбец Default показывает единицу флага: --exit-if-unused-min 10 эквивалентно SELF_HOSTED_RUNNER_IDLE_SHUTDOWN_MS=600000, а значение Helm вроде SELF_HOSTED_RUNNER_STARTUP_TIMEOUT_MS: "15" означает 15 миллисекунд, а не 15-минутное значение по умолчанию.
| Флаг | Переменная окружения | По умолчанию | Описание |
|---|---|---|---|
--api-url <url> |
none | https://api.anthropic.com |
URL базы API. Переопределяйте только для тестирования. |
--base-dir <path> |
SELF_HOSTED_RUNNER_BASE_DIR |
/workspace; none на Windows |
Каталог для проверок репозитория и рабочих каталогов для каждого сеанса. Runner должен иметь доступ на запись к этому пути или его родительскому каталогу. Runner создает каталог при запуске и выходит с cannot create or write to base directory когда не может создать или записать в него. До v2.1.225 runner создавал каталог при запуске первого сеанса, поэтому неиспользуемый путь приводил к сбою сеансов, а не запуска. На Windows, который не является поддерживаемым хостом runner, нет значения по умолчанию: runner выходит при запуске, если вы не передадите флаг или не установите переменную. Используйте одно и то же значение на каждом runner в среде. См. Keep the base directory and capacity identical across runners. |
--capacity <n> |
none | 1 |
Максимальное количество одновременных сеансов, которые обрабатывает этот runner. Все сеансы принадлежат одному заблокированному owner. Используйте одно и то же значение на каждом runner в среде; см. Keep the base directory and capacity identical across runners. |
--client-label <label> |
SELF_HOSTED_RUNNER_CLIENT_LABEL |
имя хоста хоста | Метка, которую runner отправляет при регистрации. Runner также сообщает её как метку client_label claude_code_self_hosted_runner_info. Требует Claude Code v2.1.248 или позже. |
--configure-git |
SELF_HOSTED_RUNNER_CONFIGURE_GIT=1 |
off | При запуске запишите глобальную идентификацию git, включите подписание коммитов Anthropic, включите переговоры git push и установите hooks коммитов, которые добавляют трейлер Co-authored-by:. Переговоры push требуют Claude Code v2.1.257 или позже. См. Configure git. |
--confine-repo-settings <mode> |
SELF_HOSTED_RUNNER_CONFINE_REPO_SETTINGS |
warn |
Устанавливает режим защиты, которая помечает сеанс, когда параметры репозитория, зафиксированные в коммите, пытаются предоставить доступ на запись или чтение вне собственного рабочего пространства этого сеанса, установить переменные окружения или переопределить позицию sandbox или hooks оператора, например sandbox.enabled: false или disableAllHooks. По умолчанию warn регистрирует нарушение и все еще запускает сеанс, enforce отказывает в сеансе, а off отключает сканирование. См. Harden your deployment. |
--debug-token-dir <path> |
SELF_HOSTED_RUNNER_DEBUG_TOKEN_DIR |
unset | Запишите живые токены на диск для проверки. Только для отладки; не используйте в production. |
--defer-shutdown-max-min <n> |
SELF_HOSTED_RUNNER_DEFER_SHUTDOWN_MAX_MS |
0 |
При первом SIGTERM или SIGINT продолжайте обслуживать уже подключенные сеансы вместо их осушения, затем отпустите все еще подключенное через N минут и выйдите. Повысьте timeout остановки вашего хоста перед установкой этого. См. Defer the drain past the first signal. 0 отключает. Требует Claude Code v2.1.238 или позже. |
--drain-grace-sec <n> |
SELF_HOSTED_RUNNER_DRAIN_GRACE_MS |
0 |
До тех пор, пока runner не получит сигнал завершения или не достигнет времени выхода на пенсию, контролирует, когда runner выходит после завершения активных сеансов: 0 выходит немедленно без опроса на дополнительные, а положительное значение держит runner живым и повторно опрашивает очередь заблокированного owner в течение этого количества секунд, за счет изоляции контейнера для каждого сеанса, описанной в разделе hardening. После первого сигнала, который вы отложили с помощью --defer-shutdown-max-min, runner выходит, как только он не содержит сеансов, независимо от того, что вы установили здесь. |
--drain-marker-file <path> |
SELF_HOSTED_RUNNER_DRAIN_MARKER_FILE |
unset | Файл маркера, который ваш хост записывает для объявления корректного осушения перед отправкой SIGTERM. Когда файл существует в начале осушения, runner сообщает о своем выходе в Anthropic как об осушении хоста, а не как о простом сигнале завершения. Само осушение, включая удержание --drain-wait-sec, работает так же, как без флага. Назовите путь на локальной файловой системе, в которую сеансы не могут писать. Требует Claude Code v2.1.271 или позже. |
--drain-wait-sec <n> |
SELF_HOSTED_RUNNER_DRAIN_WAIT_MS |
0 |
После начала осушения, которое происходит на SIGTERM, если вы не установили --defer-shutdown-max-min, ждите до N секунд для завершения текущего хода каждого сеанса и фоновых задач перед завершением дочернего процесса. Во время этого ожидания runner считает фоновую задачу, которая только что завершилась, все еще работающей до тех пор, пока не начнется следующий ход, который читает её результат, в течение максимум окна SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS. |
--environment-secret-file <path> |
SELF_HOSTED_RUNNER_ENVIRONMENT_SECRET |
required | Путь к файлу, содержащему секрет среды, или, для runner, порожденных orchestrator, одноразовый JWT работного заказа. SELF_HOSTED_RUNNER_ENVIRONMENT_SECRET несет значение секрета напрямую, а не путь к файлу. Старый флаг --pool-secret-file и переменная SELF_HOSTED_RUNNER_POOL_SECRET по-прежнему работают и выводят уведомление об устаревании в stderr; сборки runner программы предварительного просмотра старше 2.1.216 распознают только эти старые имена. |
--exec-path <path> |
SELF_HOSTED_RUNNER_EXEC_PATH |
собственный бинарный файл | Бинарный файл или скрипт-обертка для порождения для каждого сеанса. См. Wrapper scripts. |
--exit-if-unused-min <n> |
SELF_HOSTED_RUNNER_IDLE_SHUTDOWN_MS |
0 |
Выйдите после N минут опроса без назначенной работы, для масштабирования автомасштабера. 0 отключает. |
--git-host-rewrite <from>=<to> |
none | unset | Переписать URL источников https://<from>/... на https://<to>/... перед клонированием для разделенного DNS горизонта. Повторяемо; только флаг. |
--git-ssh-rewrite <host> |
none | unset | Переписать URL источников https://<host>/... на git@<host>:... перед клонированием для хостов git только с SSH. Повторяемо; только флаг. |
--health-port <port> |
SELF_HOSTED_RUNNER_HEALTH_PORT |
8080 |
Порт для слушателя /healthz и /metrics. Установите 0 для отключения. |
--hooks-dir <path> |
SELF_HOSTED_RUNNER_HOOKS_DIR |
unset | Каталог скриптов hooks жизненного цикла. См. Lifecycle hooks. |
--host-config-snapshot <mode> |
SELF_HOSTED_RUNNER_HOST_CONFIG_SNAPSHOT |
disk |
Где runner хранит снимок при запуске каталога конфигурации хоста, который он засевает каждый сеанс. disk копирует снимок в каталог, принадлежащий runner, под --base-dir и при каждом запуске сеанса проверяет каждый файл по дайджесту в памяти. Если файл в копии был изменен, сеанс не удается и runner отказывает в сеансах, пока вы не перезагрузите его. memory держит весь снимок на куче, ограниченный 64 МиБ; сверх лимита сеансы запускаются без конфигурации хоста и показывают уведомление об этом. Когда runner не может записать снимок на диск, он регистрирует сбой и использует memory для этого запуска. Требует Claude Code v2.1.271 или позже. |
--kill-session-after-min <n> |
SELF_HOSTED_RUNNER_MAX_LIFETIME_MS |
0 |
Ограничьте сеанс N минутами настенного времени как предел безопасности для зависших сеансов. На v2.1.260 или позже runner отпускает сеанс, который достигает лимита, чтобы он мог возобновиться при следующем сообщении пользователя, и завершает его только если он все еще на runner, когда окончится окно благодати SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS. До v2.1.260 runner завершал сеанс на лимите. См. Some sessions don't count as idle для деталей и как выбрать значение. 0 отключает. |
--lock-to-account <id> |
SELF_HOSTED_RUNNER_LOCK_TO_ACCOUNT |
unset | Предварительно заблокируйте runner на конкретный аккаунт при запуске вместо блокировки при первом сеансе. Принимает адрес электронной почты или ID user_... в организации среды. Предварительно заблокированный runner никогда не подхватывает сеансы канала Claude Tag, у которых нет аккаунта. |
--log-file <path> |
SELF_HOSTED_RUNNER_LOG_FILE |
unset | Зеркалируйте логи runner в файл в дополнение к stdout и stderr, созданный с разрешениями 0600. Требуется для self-hosted-runner doctor для локального отслеживания логов. |
--log-level <level> |
none | info |
info или debug |
--post-session-hook-timeout-sec <n> |
SELF_HOSTED_RUNNER_POST_SESSION_HOOK_TIMEOUT_MS |
60 |
Бюджет для post-session hook при завершении каждого сеанса, включая завершение runner |
--proxy-authorization-command <command> |
SELF_HOSTED_RUNNER_PROXY_AUTHORIZATION_COMMAND |
unset | Команда shell, которую runner запускает для каждого подключения к вашему прокси выхода, используя его обрезанный stdout как значение заголовка Proxy-Authorization. Требует HTTPS_PROXY или HTTP_PROXY, и не может быть объединен с --proxy-authorization-file. См. Authenticate to an egress proxy. Требует Claude Code v2.1.238 или позже. |
--proxy-authorization-file <path> |
SELF_HOSTED_RUNNER_PROXY_AUTHORIZATION_FILE |
unset | Файл, который runner читает для каждого подключения к вашему прокси выхода, используя его обрезанное содержимое как значение заголовка Proxy-Authorization. Используйте этот флаг для токена, который другой процесс ротирует на месте. Несет те же требования, что и --proxy-authorization-command, и не может быть объединен с ним. См. Authenticate to an egress proxy. Требует Claude Code v2.1.238 или позже. |
--push-outcome-on-release |
SELF_HOSTED_RUNNER_PUSH_OUTCOME_ON_RELEASE |
off | При инициированном runner завершении сеанса, таком как осушение или отпуск при простое, отправьте отслеживаемые ветви результатов в origin перед удалением рабочего пространства, чтобы текущие коммиты пережили перезагрузку. Лучшее усилие; добавляет 30 секунд к бюджету завершения и требует git 2.29 или новее для возобновления с отправленной ветви. Ограничьте доступ на отправку к ссылкам claude/* перед включением; см. Resumed sessions lose unpushed work. Репозитории, проверенные через hook checkout жизненного цикла, не отправляются; снимите их с помощью post-session hook вместо этого. |
--release-idle-session-min <n> |
SELF_HOSTED_RUNNER_SESSION_IDLE_MS |
0 |
Отпустите слот сеанса после N минут неактивности после завершения хода или ожидания сеансом действия пользователя. Сеанс, который все еще находится в процессе хода, включая тот, который держит никогда не заканчивающуюся фоновую задачу или одобрение, запрошенное изнутри работающего вызова инструмента, не считается неактивным; объедините с --kill-session-after-min как жесткий упор. После завершения фоновой задачи сеанса runner считает сеанс занятым до тех пор, пока не начнется следующий ход, который читает результат, в течение максимум окна SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS. До тех пор, пока runner не получит сигнал завершения или не достигнет времени выхода на пенсию, отпуск, который оставляет runner без активных сеансов, запускает тот же путь выхода, что и нормальное осушение, управляемое --drain-grace-sec. После первого сигнала, который вы отложили с помощью --defer-shutdown-max-min, runner выходит, как только отпуск оставляет его без сеансов. 0 отключает. |
--remove-session-state [bool] |
SELF_HOSTED_RUNNER_REMOVE_SESSION_STATE |
off | Удалите каталоги сеанса для каждого сеанса под <base-dir>/_sessions/ когда сеанс заканчивается на этом runner, независимо от результата. Reuse a pre-warmed checkout описывает, что они содержат и кто может их читать, когда они остаются. Удаление является лучшим усилием: каталоги для каждого сеанса остаются на месте, когда runner убивается или достигает крайнего срока осушения перед запуском очистки. С флагом включенным, логи отладки неудачного или прерванного сеанса не сохраняются на диск. Требует Claude Code v2.1.268 или позже. |
--retire-at <epoch-seconds> |
SELF_HOSTED_RUNNER_RETIRE_AT |
unset | Выведите runner на пенсию в абсолютный временной штамп Unix в секундах для инфраструктуры, которая убивает runner в известное время; Runner lifecycle описывает последовательность отпуска и как определить размер маржи. Значения до 2001 или после года 5138 отклоняются флагом и игнорируются переменной окружения. |
--session-stop-grace-sec <n> |
SELF_HOSTED_RUNNER_SESSION_STOP_GRACE_MS |
5 |
Как долго ждать чистого выхода процесса Claude после завершения сеанса перед принудительным завершением. Повысьте значение, если собственные hooks SessionEnd дочернего процесса нуждаются в большем времени. |
--startup-timeout-min <n> |
SELF_HOSTED_RUNNER_STARTUP_TIMEOUT_MS |
15 |
Отпустите слот сеанса, если дочерний процесс не сигнализировал об инициализации в течение N минут после порождения. Очищается сигналом инициализации дочернего процесса на канале активности, а не обычным выводом, после чего --release-idle-session-min берет верх. 0 отключает. |
--trust-workspace [bool] |
SELF_HOSTED_RUNNER_TRUST_WORKSPACE |
on | Посейте сохраняемое доверие для путей репозитория каждого сеанса, чтобы зафиксированные в репо permissions.allow и additionalDirectories были соблюдены. Установите false для отпуска зафиксированных в репо грантов разрешений и вместо этого настройте правила разрешения в settings.json конфигурации хоста; параметры sandbox.* зафиксированные в репо все еще применяются в любом случае, поэтому защита repo-settings сканирует их независимо от этого флага. |
--use-anthropic-git-proxy |
CLAUDE_RUNNER_USE_GIT_PROXY=1 |
off | Клонируйте через прокси git Anthropic вместо управляемой клиентом аутентификации git. Требует --capacity 1 и git 2.32 или новее; runner отказывается запускаться в противном случае. Заменяет флаги переписи. |
Большинство флагов длительности имеют максимум, выбранный для сохранения каждого timeout в потолке 32-битного таймера runtime примерно 24,85 дня. Флаги --*-min ограничены 10080 минутами, 7 дней; --drain-grace-sec на 604800 секунд, также 7 дней; и --drain-wait-sec на 86400 секунд, 24 часа. --session-stop-grace-sec и --post-session-hook-timeout-sec не ограничены. Превышение лимита ведет себя по-разному в зависимости от поверхности:
- Флаг: запуск не удается с ошибкой.
- Переменная окружения: runner зажимает значение до потолка таймера вместо его отклонения.
Флаги CLI Orchestrator
Подкоманда self-hosted-runner orchestrator, которая порождает on-demand runners, принимает --api-url, --environment-secret-file, --hooks-dir, --health-port и --log-level с теми же значениями по умолчанию, что и runner и, где флаг runner имеет один, ту же переменную окружения, за исключением того, что --hooks-dir требуется и должен содержать hook spawn-runner. Он также принимает свои собственные флаги:
| Флаг | По умолчанию | Описание |
|---|---|---|
--hook-concurrency <n> |
4 |
Максимум hooks spawn-runner, работающих параллельно. Также ограничивает, сколько запросов на порождение претендуют на опрос. |
--hook-timeout <sec> |
60 |
Завершите дерево процессов hook после этого количества секунд. Timeout плюс его 5-секундная благодать убийства должны оставаться ниже --expected-spawn-seconds; orchestrator обеспечивает это при запуске. |
--expected-spawn-seconds <sec> |
120 |
Ожидаемое время загрузки p99 для порожденных runner в диапазоне, обеспеченном сервером, от 10 до 3600. Отправляется при каждом опросе как аренда на стороне сервера; если ни один runner не регистрируется до его истечения, сеанс переоформляется с новым ID заказа. Все реплики должны совместно использовать это значение. |
--min-idle <n> |
0 |
Держите по крайней мере N свободных слотов сеанса в режиме ожидания, активно порождая резервные runner. 0 отключает предварительное прогревание. Объедините с --exit-if-unused-min runner, чтобы избыточные резервные runner восстановили себя. |
--debug-dir <path> |
unset | Запишите рабочий заказ каждого запроса на порождение и stderr hook на диск. Только для отладки; никогда не устанавливайте в production. |
Флаги SCM connector
Orchestrator может держать постоянное подключение WebSocket к плоскости управления Anthropic, чтобы размещенные предсеансовые потоки, такие как средство выбора репозитория и средство разрешения ветви или ссылки, могли достичь хоста GitHub Enterprise Server, который маршрутизируется только изнутри вашей сети. Соединитель остается отключенным, если вы не установите --scm-connector-host.
| Флаг | По умолчанию | Описание |
|---|---|---|
--scm-connector-host <host[:port]> |
unset | Имя хоста GitHub Enterprise Server для перенаправления запросов. Порт по умолчанию 443. Установка этого флага включает соединитель. |
--scm-connector-id <n> |
required with --scm-connector-host |
Числовой ID подключения GitHub Enterprise Server вашей организации. Свяжитесь с командой вашего аккаунта Anthropic для значения при включении соединителя. |
--scm-connector-provider <slug> |
ghe |
Сегмент пути, идентифицирующий поставщика, соответствующий ^[a-z0-9-]{1,32}$. |
--scm-connector-ca-file <path> |
unset | Дополнительный пакет CA в формате PEM для подключений TLS к хосту GitHub Enterprise Server. |
--scm-connector-host-rewrite <from>=<to_host:to_port> |
unset | Только для сквозного тестирования: перенаправляет подключение TCP, сохраняя заголовок Host и TLS SNI как --scm-connector-host. |
Соединитель аутентифицируется с существующим секретом среды orchestrator и автоматически переподключается: с экспоненциальной задержкой при разорванном подключении или фиксированной 30-секундной задержкой, когда плоскость управления закрывает подключение, потому что другая реплика orchestrator уже его держит.
Параметры только для переменных окружения
Эти параметры runner читаются только из окружения и охватывают поведение, которое большинство развертываний оставляют по умолчанию:
| Переменная окружения | По умолчанию | Описание |
|---|---|---|
SELF_HOSTED_RUNNER_BG_RESULT_GRACE_MS |
30000 |
Как долго runner считает сеанс занятым после завершения фоновой задачи, пока не начнется следующий ход, который читает результат. Строки --drain-wait-sec и --release-idle-session-min описывают, где применяется удержание при осушении и отпуске при простое, и Runner lifecycle описывает, где оно применяется при выходе на пенсию --retire-at. 0 или неиспользуемое значение возвращается к значению по умолчанию, поэтому удержание не может быть отключено. Требует Claude Code v2.1.228 или позже. |
SELF_HOSTED_RUNNER_HOST_CONFIG_DIR |
~/.claude |
Каталог, захваченный в снимок запуска runner и посеянный в CLAUDE_CONFIG_DIR каждого сеанса; изменения на диске применяются после перезагрузки runner. Установка переменной также перемещает, где runner читает .claude.json для MCP seeding, поэтому установка её, включая её собственное значение по умолчанию, перемещает этот поиск; укажите на пустой каталог для полного отключения посева. |
SELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MS |
900000 |
Как долго runner ждет после того, как сеанс достигает своего лимита --kill-session-after-min, чтобы текущий ход завершился или отпуск завершился, перед завершением сеанса |
SELF_HOSTED_RUNNER_SIGKILL_GRACE_MS |
30000 |
Как долго runner ждет, пока ОС доставит SIGKILL дочернему процессу, застрявшему в неперерываемом I/O, перед выходом самого себя. Минимум --post-session-hook-timeout-sec плюс 15 секунд, и 30 больше, когда установлен --push-outcome-on-release, поэтому эффективный минимум составляет 75 секунд при значениях по умолчанию. |
CLAUDE_RUNNER_FETCH_DEPTH |
50 |
Глубина выборки Git для свежих клонов. Установите положительное целое число или full или 0 для полной выборки. Репозитории, уже присутствующие в рабочем пространстве, сохраняют свою существующую глубину. |
CLAUDE_RUNNER_SKIP_GIT_VERIFY |
unset | Когда 1, пропустите проверку наличия .git после запуска hook checkout. Установите это, когда ваш hook материализует источник, не являющийся git. |
FORCE_AUTOUPDATE_PLUGINS |
unset | Когда 1, позвольте маркетплейсам плагинов автоматически обновляться, несмотря на то, что бинарный файл закреплен |
CLAUDE_CODE_DISABLE_ARTIFACT |
unset | Когда 1, отключите инструмент Artifact в сеансах независимо от параметра администратора организации и отпустите требование выхода *.frame.claudeusercontent.com |
Телеметрия
Дочерние процессы сеанса отправляют операционную телеметрию в Anthropic, если вы её не отключите. Никакой код или содержимое репозитория не отправляется. Установите переменные телеметрии на процесс runner; runner переустанавливает их после применения переменных окружения, предоставленных сервером, поэтому параметр оператора всегда имеет приоритет.
Один элемент управления специфичен для самостоятельно размещаемых сред: CLAUDE_CODE_BYOC_ENABLE_DATADOG=1 выбирает метрики операционной деятельности Datadog, которые по умолчанию отключены в самостоятельно размещаемых средах. Общие элементы управления телеметрией Claude Code, DISABLE_TELEMETRY, DO_NOT_TRACK, DISABLE_ERROR_REPORTING и CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, применяются к дочерним процессам сеанса, как задокументировано в справочнике переменных окружения. DISABLE_GROWTHBOOK связан, но отличается: установка DISABLE_GROWTHBOOK=1 отключает выборку флагов функций, и телеметрия остается включенной, если также не установлен DISABLE_TELEMETRY.
CLAUDE_CODE_ENABLE_TELEMETRY не связан: он включает экспорт OpenTelemetry на ваш собственный сборщик, как описано в Monitoring, и не контролирует аналитику Anthropic.
Конечная точка здоровья
Runner служит GET /healthz на настроенном порту здоровья. Ответ 200 OK всякий раз, когда процесс живой, независимо от состояния цикла опроса, поэтому зонд HTTP на этой конечной точке обнаруживает только мертвый процесс. Тело JSON описывает текущее состояние:
{
"status": "ok",
"runner_id": "ccrunner_...",
"active_sessions": 2,
"last_poll_at": "2026-03-31T18:04:11.220Z",
"last_poll_age_ms": 842
}
Используйте last_poll_age_ms как сигнал живости в пользовательских зондах; значение, которое растет без ограничений, указывает на то, что цикл опроса застрял. Оба last_poll_at и last_poll_age_ms равны null до завершения первого опроса.
Orchestrator служит своему собственному /healthz на его порту здоровья. Его конечная точка всегда возвращает 200, и тело несет поле connected, сообщающее, успешен ли последний опрос, плюс количество очереди порождения для каждого состояния в queue_counts. Ограничьте готовность и оповещение на connected вместо кода состояния.
Когда SCM connector настроен, тело /healthz orchestrator также несет scm_connector_connected и объект scm_connector с connected, last_connected_at, last_error, reconnects и requests_forwarded. Оба поля равны null, когда --scm-connector-host не установлен.
Метрики Prometheus
Каждый runner служит метрикам Prometheus в GET /metrics на том же порту, что и /healthz. Ключевые серии:
| Серия | Примечания |
|---|---|
claude_code_self_hosted_runner_info{runner_id,version,client_label} |
Всегда 1; полезно для инвентаризации флота и обнаружения дрейфа версий |
claude_code_self_hosted_runner_capacity |
Настроенный --capacity |
claude_code_self_hosted_runner_active_sessions |
Сеансы, в настоящее время работающие |
claude_code_self_hosted_runner_locked_account{email} |
Присутствует после того, как runner заблокировался на пользователя и был выдан токен сеанса, несущий претензию act.email. Серия отсутствует на runner, заблокированном на агента Claude Tag, чьи токены сеанса не несут act.email. Значение метки — это адрес электронной почты аккаунта; если ваше хранилище метрик широко читаемо, отпустите или хешируйте метку во время скребка, например с помощью Prometheus metric_relabel_configs. |
claude_code_self_hosted_runner_last_poll_age_seconds |
Секунды с момента последнего успешного опроса. Оповещение, если более 60. |
claude_code_self_hosted_runner_poll_errors_total{error_kind} |
Кумулятивные сбои PollWork по типу: transport, timeout, 5xx, 429 или 4xx. Все пять серий присутствуют с начала процесса; оповещение на rate(...[5m]) > 0. |
claude_code_self_hosted_runner_sessions_started_total{client_platform} |
Дочерние процессы сеанса, порожденные за время жизни runner, одна серия на источник сеанса, такой как web_claude_ai, ios, android, desktop_app или claude_code_cli, или unknown, когда сервер не отправил один. Сеансы Slack несут либо claude_in_slack, либо claude-in-slack в зависимости от того, какая интеграция Slack их создала, поэтому совпадайте с обоими с помощью селектора regex, такого как {client_platform=~"claude[-_]in[-_]slack"}. Используйте sum() для общего количества флота. |
claude_code_self_hosted_runner_sessions_completed_total{client_platform} |
Сеансы, которые завершились чисто, помеченные так же. Шире, чем простой чистый выход: см. session lifecycle counter semantics для того, что считается. |
claude_code_self_hosted_runner_sessions_failed_total{client_platform} |
Сеансы, которые завершились в отказе, помеченные так же. Та же оговорка: см. session lifecycle counter semantics. |
claude_code_self_hosted_runner_sessions_interrupted_total{client_platform} |
Сеансы, которые runner завершил по операционной причине, а не по результату сеанса, помеченные так же. См. session lifecycle counter semantics. |
claude_code_self_hosted_runner_initializing_sessions |
Сеансы, в настоящее время находящиеся в фазе инициализации, от назначения до события инициализации дочернего процесса |
claude_code_self_hosted_runner_session_init_duration_seconds |
Гистограмма длительности инициализации сеанса |
claude_code_self_hosted_runner_session_init_errors_total |
Сеансы, которые не удалось инициализировать: сбой hook checkout, подготовка git, проблема с токеном или сбой дочернего процесса до инициализации |
claude_code_self_hosted_runner_session_start_hook_errors_total |
Hooks SessionStart, которые сообщили об ошибке результата, один на каждое неудачное выполнение hook |
claude_code_self_hosted_runner_session_idle_seconds{session_id,client_platform} |
Датчик для каждого сеанса секунд с момента простоя сеанса. Полезно для завершения сеансов, застрявших на неотвеченном запросе разрешения. |
Orchestrator служит своим собственным сериям в GET /metrics на том же порту, что и его /healthz:
| Серия | Примечания |
|---|---|
claude_code_self_hosted_orchestrator_info{version,pool_id,orchestrator_uuid,hostname} |
Всегда 1 |
claude_code_self_hosted_orchestrator_connected |
1, когда последний опрос успешен; падает до 0 после любого неудачного опроса, независимо от типа сбоя |
claude_code_self_hosted_orchestrator_last_poll_age_seconds |
Секунды с момента последней попытки опроса, успеха или сбоя, в отличие от идентично названной метрики runner, которая измеряет с момента последнего успеха; объедините с connected для перехвата неудачных опросов. Цикл опроса orchestrator ждет выполнения hook, поэтому оповещение выше --hook-timeout плюс маржа, около 90 секунд при значениях по умолчанию, вместо плоских 60. |
claude_code_self_hosted_orchestrator_poll_errors_total{error_kind} |
Кумулятивные сбои PollSpawnHints по типу: transport, timeout, 5xx, 429 или 4xx. Все пять серий присутствуют с начала процесса; оповещение на rate(...[5m]) > 0. |
claude_code_self_hosted_orchestrator_queue_pending_sessions |
Запросы на порождение, претендующие прямо сейчас |
claude_code_self_hosted_orchestrator_queue_backing_off_sessions |
Запросы на порождение в отступлении повтора после повторяемого сбоя hook |
claude_code_self_hosted_orchestrator_queue_circuit_broken_sessions |
Запросы на порождение, заблокированные до тех пор, пока Owner не повторит их с вкладки Activity среды; оповещение, если выше нуля |
claude_code_self_hosted_orchestrator_pool_pending_sessions |
Всего сеансов, ожидающих runner для этой среды. Совокупность на уровне среды, идентичная на каждом экземпляре orchestrator: используйте MAX вместо SUM по экземплярам. |
claude_code_self_hosted_orchestrator_pool_active_sessions |
Сеансы, в настоящее время назначенные живому runner в этой среде. Совокупность на уровне среды, идентичная на каждом экземпляре orchestrator: используйте MAX вместо SUM по экземплярам. |
claude_code_self_hosted_orchestrator_spawn_hooks_total{result} |
Кумулятивные результаты hook spawn-runner: ok, retryable, non_retryable. Подсчитывает вызовы hook orchestrator, а не дочерние процессы сеанса, которые порождают runner: не сравнимо с sessions_started_total, так как емкость выше одного, теплые пулы и runner, порожденные снова для того же сеанса, все расходятся в двух. |
claude_code_self_hosted_orchestrator_spawn_hook_duration_seconds |
Гистограмма длительности hook |
claude_code_self_hosted_orchestrator_warm_hints_dispatched_total |
Запросы на порождение резервного копирования, отправленные с начала процесса |
claude_code_self_hosted_orchestrator_session_queue_wait_seconds |
Гистограмма секунд, которые каждый сеанс ждал в очереди перед тем, как orchestrator претендовал на него для порождения, записанная из временной метки очереди ожидания, которую плоскость управления отправляет с каждым запросом на порождение сеанса. Используйте для оповещения времени очереди p50/p99. Порождения предварительного прогрева не отбираются. |
claude_code_self_hosted_orchestrator_clock_skew_seconds |
Перекос часов локальный минус сервер; диагностический, присутствует один раз измеренный |
claude_code_self_hosted_orchestrator_scm_connector_connected |
1, когда WebSocket SCM connector открыт; 0 во время набора номера или отступления. Отсутствует, когда --scm-connector-host не установлен. |
claude_code_self_hosted_orchestrator_scm_connector_requests_forwarded_total |
Кумулятивные HTTP запросы, проксированные на настроенный хост SCM с начала процесса. Отсутствует, когда --scm-connector-host не установлен. |
Для автомасштабирования выберите серию, которая соответствует вашему стилю масштабирования, и ограничьте её перед подачей в масштабер:
- Масштабирование глубины очереди: подайте
claude_code_self_hosted_orchestrator_pool_pending_sessionsв ваш HPA или KEDA масштабер, а неqueue_pending_sessions. - Масштабирование емкости: масштабируйте по соотношению
active_sessionsrunner кcapacity. - Ограничение на
connected: отфильтруйте запрос с помощьюclaude_code_self_hosted_orchestrator_connected == 1на экземпляр, поэтому устаревшее значение отключенной реплики не подается в масштабер.
Во время полного отключения опроса каждая реплика отключена, гейтированный запрос не возвращает данные. HPA удерживает текущее количество реплик на отсутствующей метрике, но Prometheus масштабер KEDA при его значении по умолчанию ignoreNullValues: "true" читает пустой результат как ноль и масштабирует; установите ignoreNullValues: "false" на ScaledObject, опционально с полом реплики fallback.
Следующий Prometheus Operator PodMonitor охватывает оба процесса. Он выбирает pods по метке app.kubernetes.io/part-of: claude-code-self-hosted-runner и именованному порту health, который устанавливает рецепт Kubernetes; отрегулируйте пространства имен в соответствии с вашим развертыванием:
# 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
Эти примеры правил оповещения — это отправная точка; настройте пороги для размера вашего флота:
# 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"
Пропустить метрики дочернего процесса сеанса
Каждый сеанс работает в своем собственном дочернем процессе с собственными метриками OpenTelemetry; при --capacity выше одного runner переписывает, как эти метрики дочернего процесса выставляются. Установка OTEL_METRICS_EXPORTER=prometheus на хосте runner и CLAUDE_CODE_ENABLE_TELEMETRY=1 в окружении сеанса, например из вашего скрипта-обертки или собственного окружения runner, которое сеансы наследуют, переоткрывает счетчики и датчики каждого дочернего процесса на собственной конечной точке /metrics runner, наряду с сериями runner. Runner переписывает экспортер дочернего процесса для отправки по OTLP на приемник только для loopback на порту здоровья, помечает каждую серию метками session_id и client_platform и вытесняет серии сеанса при завершении этого сеанса. Гистограммы не проходят, и метрика дочернего процесса, чье имя будет конфликтовать с собственным префиксом runner, отпускается.
При значении по умолчанию --capacity 1 переписывание не применяется: дочерний процесс сеанса привязывает свою собственную конечную точку Prometheus на порту 9464 как обычно.
Семантика счетчика жизненного цикла сеанса
Счетчики sessions_started_total, sessions_completed_total, sessions_failed_total и sessions_interrupted_total классифицируют каждый сеанс по тому, как он завершился. Каждый порожденный дочерний процесс сеанса увеличивает sessions_started_total во время порождения, и ровно один из трех других увеличивается при выходе, поэтому sessions_started_total минус сумма трех других равна количеству дочерних процессов сеанса, в настоящее время работающих.
completed: сеанс завершился чисто. Это охватывает дочерний процесс, выходящий самостоятельно с кодом0, сеанс, архивируемый или удаляемый, пока дочерний процесс был все еще подключен, и runner, передающий слот чисто: отпуск сеанса при timeout простоя, времени выхода на пенсию или лимите--kill-session-after-min; startup timeout; или деассайн на стороне сервера, который цикл опроса заметил перед выходом дочернего процесса. Увеличиваетsessions_completed_total.failed: дочерний процесс выходит самостоятельно с ненулевым кодом, либо сбой, либо сбой настройки после порождения. Увеличиваетsessions_failed_total.interrupted: runner завершил дочерний процесс по операционной причине, которая не является ни успехом сеанса, ни ошибкой runner, такой как осушение или завершение сеанса, который все еще был на runner, когда окончилось окно благодатиSELF_HOSTED_RUNNER_MAX_LIFETIME_GRACE_MSпосле его лимита--kill-session-after-min. Перезагрузка Kubernetes, отправляющаяSIGTERM, является одним примером осушения. Увеличиваетsessions_interrupted_total.
До v2.1.260 runner завершал каждый сеанс, который достигал своего лимита --kill-session-after-min, и подсчитывал его в sessions_interrupted_total.
Hook post-session классифицирует чистые передачи по-другому через CLAUDE_RUNNER_EXIT_REASON. Hook сообщает об отпуске, startup timeout и деассайне сервера как interrupted, потому что runner остановил дочерний процесс. Эти счетчики записывают те же события, что и completed, потому что слот был передан чисто.
Если вы согласовываете квитанции hook непосредственно с sessions_completed_total, вы недосчитываетесь завершений. Используйте hook для гарантий для каждого сеанса и счетчики для совокупных ставок.
В одноразовой среде --capacity 1 с значением по умолчанию --drain-grace-sec 0 каждый процесс runner выходит через несколько мгновений после завершения его одного сеанса. sessions_completed_total, sessions_failed_total и sessions_interrupted_total увеличиваются только при завершении сеанса, прямо перед этим выходом, поэтому скребок Prometheus каждые 15-60 секунд редко ловит увеличение перед исчезновением серии runner; эти три счетчика конца сеанса — это терминальные счетчики, на которые ссылается остальная часть этого раздела. sessions_started_total увеличивается при порождении и остается видимым в течение жизни сеанса, поэтому он надежно показывается, но в одноразовой среде он читается ближе к "сеансам, в настоящее время работающим", чем к совокупному подсчету.
Используйте серию в этой таблице для соответствующей цели вместо терминальных счетчиков:
| Цель | Использование |
|---|---|
| Пропускная способность | claude_code_self_hosted_orchestrator_spawn_hooks_total{result="ok"}, счетчик на долгоживущем orchestrator, который увеличивается один раз на успешный hook spawn-runner и остается значимым под rate(). Он подсчитывает вызовы hook, а не сеансы, поэтому предварительное прогревание и повторные порождения для того же сеанса расходятся в нем от подсчетов сеансов. |
| Использование | sum(claude_code_self_hosted_runner_active_sessions) против sum(claude_code_self_hosted_runner_capacity), оба датчика действительны при каждом скребке независимо от времени жизни runner |
| Невыполненные заказы | claude_code_self_hosted_orchestrator_pool_pending_sessions для глубины очереди и claude_code_self_hosted_orchestrator_queue_circuit_broken_sessions, оповещение, если выше нуля |
| Сбои | claude_code_self_hosted_runner_sessions_failed_total, лучшее усилие: реальные сбои после порождения действительно увеличивают его, и rate() значим на runner, которые пережили свои сеансы с --drain-grace-sec выше 0. Одноразовая среда имеет ту же проблему окна скребка, что и другие терминальные счетчики, поэтому рассматривайте любое ненулевое значение, которое вы видите, как стоящее исследования. Сбои перед порождением, такие как сбой hook checkout, подготовка git или проблема с токеном, появляются только в session_init_errors_total. |
Строки orchestrator_* существуют только в средах, работающих с on-demand orchestrator. На фиксированном флоте, чьи runner пережили свои сеансы, с --drain-grace-sec выше 0, используйте sum(rate(claude_code_self_hosted_runner_sessions_started_total[5m])) для пропускной способности; в одноразовом флоте эта серия имеет ту же проблему окна скребка, что и терминальные счетчики, поэтому полагайтесь на подсчет сеансов в очереди вместо этого. Проверьте невыполненные заказы на вкладке Activity среды, на странице администратора Cloud environments: runner не экспортируют серию глубины очереди.
Для отчетности результатов для каждого сеанса используйте вместо этого hook post-session: он срабатывает при каждом завершении сеанса, где был порожден дочерний процесс, кроме резкого завершения runner, такого как вытеснение VM, в соответствии с собственным контрактом hook.
Что дальше
- Self-hosted environments: среда, runner и модель сеанса; quickstart и Deploy to production содержат настройку и операции
- Customize sessions: скрипты-обертки, hooks жизненного цикла и on-demand runner
- Verify session identity: токен сеанса, его претензии и как его проверить