31| Variable | Descripción |31| Variable | Descripción |
32| :- | :- |32| :- | :- |
33| `CLAUDE_CODE_SESSION_ACCESS_TOKEN` | El JWT de la sesión, con prefijo `sk-ant-cc-`. Su reclamación `act` identifica al creador de la sesión, con el correo electrónico del creador cuando la superficie de creación lo registró. El valor es el token en el momento de la generación; los refrescos llegan a través del stdin del hijo, por lo que un contenedor solo ve el valor inicial. Consulta [Verificar identidad de sesión](/docs/es/self-hosted-environments-identity). |33| `CLAUDE_CODE_SESSION_ACCESS_TOKEN` | El JWT de la sesión, con prefijo `sk-ant-cc-`. Su reclamación `act` identifica al creador de la sesión, con el correo electrónico del creador cuando la superficie de creación lo registró. El valor es el token en el momento de la generación; los refrescos llegan a través del stdin del hijo, por lo que un contenedor solo ve el valor inicial. Consulta [Verificar identidad de sesión](/docs/es/self-hosted-environments-identity). |
34| `CCR_SESSION_ACCOUNT_EMAIL` | El correo electrónico del creador de la sesión, preextraído por el ejecutor de la reclamación `act.email` del token sin verificación de firma. Adecuado para etiquetado, como trailers de commit. Cuando el correo electrónico controla la emisión de credenciales, verifica el token y lee la reclamación de él en su lugar; consulta [Aprovisionar credenciales limitadas al creador de la sesión](#provision-credentials-scoped-to-the-session-creator). No está establecida cuando el token no lleva correo electrónico del creador. Trátala como información de identificación personal. |34| `CCR_SESSION_ACCOUNT_EMAIL` | El correo electrónico del creador de la sesión, preextraído por el ejecutor de la reclamación `act.email` del token sin verificación de firma. Adecuado para etiquetado, como trailers de commit. Cuando el correo electrónico controla la emisión de credenciales, verifica el token y lee la reclamación de él en su lugar. Consulta [Aprovisionar credenciales limitadas al creador de la sesión](#provision-credentials-scoped-to-the-session-creator). No está establecida cuando el token no lleva correo electrónico del creador, por ejemplo en sesiones que crea la identidad de servicio de tu organización. Trátala como información de identificación personal. |
35| `CLAUDE_RUNNER_CLIENT_PLATFORM` | La superficie del cliente que creó la sesión, como `web_claude_ai`, `desktop_app`, `ios`, `claude_code_cli` o `scheduled_trigger`. Anthropic registra el valor una vez en la creación de la sesión, por lo que el contenedor y cada hook de ciclo de vida ven el mismo valor. Úsala solo para análisis de adopción y etiquetado, no como señal de autorización. No está establecida cuando la sesión no tiene una superficie registrada o reconocida, así que haz referencia a ella como `${CLAUDE_RUNNER_CLIENT_PLATFORM:-}` bajo `set -u`. Requiere Claude Code v2.1.229 o posterior. |35| `CLAUDE_RUNNER_CLIENT_PLATFORM` | La superficie del cliente que creó la sesión, como `web_claude_ai`, `desktop_app`, `ios`, `claude_code_cli` o `scheduled_trigger`. Anthropic registra el valor una vez en la creación de la sesión, por lo que el contenedor y cada hook de ciclo de vida ven el mismo valor. Úsala solo para análisis de adopción y etiquetado, no como señal de autorización. No está establecida cuando la sesión no tiene una superficie registrada o reconocida. Requiere Claude Code v2.1.229 o posterior. |
36| `CLAUDE_RUNNER_CLAUDE_BIN` | Ruta absoluta al binario de Claude Code propio del ejecutor. Termina tu contenedor con `exec "$CLAUDE_RUNNER_CLAUDE_BIN" "$@"` para entregar el control al binario fijado sin codificar una ruta de instalación. |36| `CLAUDE_RUNNER_CLAUDE_BIN` | Ruta absoluta al binario de Claude Code propio del ejecutor. Termina tu contenedor con `exec "$CLAUDE_RUNNER_CLAUDE_BIN" "$@"` para entregar el control al binario fijado sin codificar una ruta de instalación. |
37| `CLAUDE_CODE_REMOTE_SESSION_ID` | ID de sesión en forma etiquetada `cse_...`. Esta es la misma sesión que los [hooks de ciclo de vida](#lifecycle-hooks) ven como `CLAUDE_RUNNER_SESSION_ID` en forma `session_...`; las variables UUID coinciden en ambas, y sustituir el prefijo `cse_` con `session_` produce el ID que se muestra en la URL de la sesión. |37| `CLAUDE_CODE_REMOTE_SESSION_ID` | ID de sesión en forma etiquetada `cse_...`. Esta es la misma sesión que los [hooks de ciclo de vida](#lifecycle-hooks) ven como `CLAUDE_RUNNER_SESSION_ID` en forma `session_...`; las variables UUID coinciden en ambas, y sustituir el prefijo `cse_` con `session_` produce el ID que se muestra en la URL de la sesión. |
38| `CLAUDE_CODE_REMOTE_SESSION_UUID` | El mismo ID de sesión en forma UUID canónica, para sistemas que usan UUID como clave. |38| `CLAUDE_CODE_REMOTE_SESSION_UUID` | El mismo ID de sesión en forma UUID canónica, para sistemas que usan UUID como clave. |
39| `CLAUDE_CODE_REMOTE_SLACK_THREAD_URL` | Para una sesión de [Claude Tag](https://claude.com/docs/claude-tag/overview) que pertenece a un hilo de Slack, el enlace a ese hilo. No está establecida para otras sesiones, y también puede no estar establecida para una sesión de hilo. |
40| `CLAUDE_CODE_REMOTE_SLACK_THREAD_TS` | Para una sesión de Claude Tag que pertenece a un hilo de Slack, la marca de tiempo de Slack de ese hilo, como `1700000000.000100`. Puede no estar establecida, y puede estar establecida cuando `CLAUDE_CODE_REMOTE_SLACK_THREAD_URL` no lo está, así que comprueba cada variable por separado. |
39| `CLAUDE_SESSION_INGRESS_TOKEN_FILE` | Ruta absoluta a un archivo por sesión que contiene el JWT de sesión actual, mantenido actualizado en los refrescos de token. Los subprocesos de shell lo leen para su encabezado `Authorization` al descargar archivos adjuntos que el usuario agregó a la sesión. `exec` preserva la variable automáticamente; un contenedor que reconstruye el entorno del hijo debe conservar la variable, o las descargas de archivos adjuntos dejan de funcionar silenciosamente. |41| `CLAUDE_SESSION_INGRESS_TOKEN_FILE` | Ruta absoluta a un archivo por sesión que contiene el JWT de sesión actual, mantenido actualizado en los refrescos de token. Los subprocesos de shell lo leen para su encabezado `Authorization` al descargar archivos adjuntos que el usuario agregó a la sesión. `exec` preserva la variable automáticamente; un contenedor que reconstruye el entorno del hijo debe conservar la variable, o las descargas de archivos adjuntos dejan de funcionar silenciosamente. |
40| `CLAUDE_CONFIG_DIR` | Directorio de configuración de Claude por sesión, escrito al inicio de la sesión desde la instantánea de la configuración del host del ejecutor que el ejecutor captura al inicio; consulta [Permisos y aprobación de herramientas](#permissions-and-tool-approval). Las escrituras aquí se aíslan a esta sesión. El directorio permanece bajo `<base-dir>/_sessions/` después de que la sesión finaliza a menos que inicies el ejecutor con [`--remove-session-state`](/docs/es/self-hosted-environments-reference#runner-cli-flags); consulta [Reutilizar un checkout precalentado](/docs/es/self-hosted-environments-deploy#reuse-a-pre-warmed-checkout). |42| `CLAUDE_CONFIG_DIR` | Directorio de configuración de Claude por sesión, escrito al inicio de la sesión desde la instantánea de la configuración del host del ejecutor que el ejecutor captura al inicio; consulta [Permisos y aprobación de herramientas](#permissions-and-tool-approval). Las escrituras aquí se aíslan a esta sesión. El directorio permanece bajo `<base-dir>/_sessions/` después de que la sesión finaliza a menos que inicies el ejecutor con [`--remove-session-state`](/docs/es/self-hosted-environments-reference#runner-cli-flags); consulta [Reutilizar un checkout precalentado](/docs/es/self-hosted-environments-deploy#reuse-a-pre-warmed-checkout). |
41| `ANTHROPIC_BASE_URL` | La URL base de API que el hijo usará, entregada por el plano de control por sesión y normalmente `https://api.anthropic.com`. No la sobrescribas: la credencial de inferencia de la sesión es un token OAuth emitido por Anthropic que otros proveedores no aceptan. |43| `ANTHROPIC_BASE_URL` | La URL base de API que el hijo usará, entregada por el plano de control por sesión y normalmente `https://api.anthropic.com`. No la sobrescribas: la credencial de inferencia de la sesión es un token OAuth emitido por Anthropic que otros proveedores no aceptan. |
43 45
44El contenedor también hereda el resto del entorno administrado del hijo, incluida cualquier variable de entorno proporcionada por el servidor. `exec` lo propaga todo automáticamente; si tu contenedor genera el hijo de otra manera, reenvía el entorno completo.46El contenedor también hereda el resto del entorno administrado del hijo, incluida cualquier variable de entorno proporcionada por el servidor. `exec` lo propaga todo automáticamente; si tu contenedor genera el hijo de otra manera, reenvía el entorno completo.
45 47
48`CLAUDE_CODE_REMOTE_SLACK_THREAD_URL` y `CLAUDE_CODE_REMOTE_SLACK_THREAD_TS` llegan a tu contenedor o [hook `command`](#command). También llegan a lo que ejecuta la sesión, como comandos de shell, hooks de git y hooks de Claude Code. Los hooks `checkout`, `post-session` y `spawn-runner` no las reciben.
49
50<h3 id="give-a-default-to-variables-that-can-be-unset">
51 Dar un valor predeterminado a las variables que pueden no estar establecidas
52</h3>
53
54`CCR_SESSION_ACCOUNT_EMAIL`, `CLAUDE_RUNNER_CLIENT_PLATFORM`, `CLAUDE_CODE_REMOTE_SLACK_THREAD_URL` y `CLAUDE_CODE_REMOTE_SLACK_THREAD_TS` pueden no estar establecidas. Si tu script usa `set -u`, Bash se detiene con `unbound variable` cuando expande una que no está establecida, así que expándelas con un valor predeterminado, como `${CCR_SESSION_ACCOUNT_EMAIL:-}`.
55
56Dondequiera que un shell expanda el enlace del hilo de Slack, toma estas precauciones:
57
58* **Ponlo entre comillas**: el enlace puede contener caracteres que un shell interpreta, como `?` y `&`, así que pon la variable entre comillas, como en `"${CLAUDE_CODE_REMOTE_SLACK_THREAD_URL:-}"`.
59* **Mantén su valor fuera de las cadenas de `eval` y `sh -c`**: no sustituyas su valor en una cadena que ejecuta `eval` o `sh -c`, ni siquiera entre comillas. En su lugar, haz que esa cadena haga referencia a la variable.
60
46<h3 id="keep-stdin-and-file-descriptor-3-attached">61<h3 id="keep-stdin-and-file-descriptor-3-attached">
47 Mantener stdin y descriptor de archivo 3 adjuntos62 Mantener stdin y descriptor de archivo 3 adjuntos
48</h3>63</h3>
49 64
50El stdin del hijo es el canal de control del ejecutor. Las rotaciones de token y las señales de fin de sesión llegan por él. El ejecutor también abre una tubería en el descriptor de archivo 3 y lee de ella las señales de actividad del hijo para controlar los tiempos de espera de inactividad e inicio. Un simple `exec "$CLAUDE_RUNNER_CLAUDE_BIN" "$@"` preserva ambos automáticamente.65El stdin del hijo es el canal de control del ejecutor. Las rotaciones de token y las señales de fin de sesión llegan por él. El ejecutor también abre una tubería en el descriptor de archivo 3 y lee de ella las señales de actividad del hijo para controlar los tiempos de espera de inactividad e inicio. Un simple `exec "$CLAUDE_RUNNER_CLAUDE_BIN" "$@"` preserva ambos automáticamente.
51 66
52Si tu contenedor coloca el hijo en segundo plano con un simple `&`, corta el stdin del hijo: la sesión se ve saludable hasta que expira la vida útil de aproximadamente 30 minutos del token OAuth inicial, y luego cada llamada de API falla con `401 authentication_error`. Si tu contenedor debe colocar el hijo en segundo plano, por ejemplo para mantener viva una trampa de desmontaje, guarda stdin en el descriptor de archivo 4 o superior y vuelve a adjuntarlo explícitamente:67Si tu contenedor coloca el hijo en segundo plano con un simple `&`, corta el stdin del hijo. La sesión se ve saludable hasta que expira la vida útil de aproximadamente 30 minutos del token OAuth inicial, y luego cada llamada de API que usa el token falla con `401 authentication_error`. Si tu contenedor debe colocar el hijo en segundo plano, por ejemplo para mantener viva una trampa de desmontaje, guarda stdin en el descriptor de archivo 4 o superior y vuelve a adjuntarlo explícitamente:
53 68
54```bash theme={null}69```bash theme={null}
55exec 4<&070exec 4<&0
59wait "$CHILD"74wait "$CHILD"
60```75```
61 76
62No cierres ni reutilices el descriptor de archivo 3 en el contenedor. Redirigir stdout y stderr del hijo está bien.77Puedes redirigir el stdout del hijo. Mantén el descriptor de archivo 3 y stderr adjuntos al ejecutor:
78
79* **Descriptor de archivo 3**: lleva las señales de actividad del hijo al ejecutor. No lo cierres ni lo reutilices en el contenedor.
80* **stderr**: cuando el contenedor o el hijo salen con un código distinto de cero, el ejecutor publica las últimas líneas de stderr en la sesión y las imprime en su propio registro. El usuario de la sesión ve esas líneas, así que no imprimas secretos en stderr y quita `set -x` antes de implementar el contenedor. Si rediriges stderr, las sesiones siguen ejecutándose, pero el ejecutor informa un fallo solo con el código de salida.
63 81
64<h3 id="pass-the-system-prompt-flags-through">82<h3 id="pass-the-system-prompt-flags-through">
65 Transmitir los flags del prompt del sistema83 Transmitir los flags del prompt del sistema
108 checkout126 checkout
109</h3>127</h3>
110 128
111Se ejecuta una vez por repositorio, en lugar del clon y fetch integrados del ejecutor. Usa el hook para clonar desde un espejo de lectura, sembrar un árbol de trabajo desde un archivo, o aplicar autenticación git por sesión. El ejecutor establece estas variables, y puede establecer otras variables `CLAUDE_RUNNER_` que la tabla no enumera:129Se ejecuta una vez por repositorio, en lugar del clon y fetch integrados del ejecutor. Usa el hook para clonar desde un espejo de lectura al que accedes por HTTPS o SSH, sembrar una copia de trabajo desde un archivo, o aplicar autenticación git por sesión. El ejecutor establece estas variables, y puede establecer otras variables `CLAUDE_RUNNER_` que la tabla no enumera:
112 130
113| Variable | Descripción |131| Variable | Descripción |
114| :- | :- |132| :- | :- |
115| `CLAUDE_RUNNER_REPO_URL` | URL del repositorio a clonar, después de que se hayan aplicado `--git-host-rewrite` y `--git-ssh-rewrite` |133| `CLAUDE_RUNNER_REPO_URL` | URL del repositorio a clonar, después de que se hayan aplicado `--git-host-rewrite` y `--git-ssh-rewrite` |
116| `CLAUDE_RUNNER_REPO_REF` | Revisión a verificar: rama, etiqueta o SHA de commit como la sesión lo solicitó. Vacío significa la rama predeterminada del repositorio. |134| `CLAUDE_RUNNER_REPO_REF` | Revisión a extraer, tal como la sesión la solicitó: una rama, una etiqueta, un SHA de commit o un nombre de referencia completo como `refs/pull/<number>/head`. Vacío significa la rama predeterminada del repositorio. |
117| `CLAUDE_RUNNER_CHECKOUT_PATH` | Ruta absoluta donde el árbol de trabajo debe dejarse |135| `CLAUDE_RUNNER_CHECKOUT_PATH` | Ruta absoluta donde el árbol de trabajo debe dejarse |
118| `CLAUDE_RUNNER_SESSION_ID` | ID de sesión en forma etiquetada `session_...`, para registro y correlación |136| `CLAUDE_RUNNER_SESSION_ID` | ID de sesión en forma etiquetada `session_...`, para registro y correlación |
119| `CLAUDE_RUNNER_SESSION_UUID` | El mismo ID de sesión en forma UUID canónica |137| `CLAUDE_RUNNER_SESSION_UUID` | El mismo ID de sesión en forma UUID canónica |
120| `CLAUDE_RUNNER_API_BASE_URL` | URL base de API de Anthropic para llamadas limitadas a sesión |138| `CLAUDE_RUNNER_API_BASE_URL` | URL base de API de Anthropic para llamadas limitadas a sesión |
121| `CLAUDE_RUNNER_CLIENT_PLATFORM` | La superficie del cliente que creó la sesión, como `web_claude_ai`, `desktop_app` o `ios`. No establecido cuando la sesión no tiene una superficie registrada o reconocida. |139| `CLAUDE_RUNNER_CLIENT_PLATFORM` | La superficie del cliente que creó la sesión, como `web_claude_ai`, `desktop_app` o `ios`. No se establece cuando la sesión no tiene una superficie registrada o reconocida, así que haz referencia a ella como `${CLAUDE_RUNNER_CLIENT_PLATFORM:-}` con `set -u`. Requiere Claude Code v2.1.229 o posterior. |
122| `CLAUDE_CODE_SESSION_ACCESS_TOKEN` | El token de acceso de sesión, para llamadas de API limitadas a sesión |140| `CLAUDE_CODE_SESSION_ACCESS_TOKEN` | El token de acceso de sesión, para llamadas de API limitadas a sesión |
123| `GIT_CONFIG_COUNT`, `GIT_CONFIG_KEY_n`, `GIT_CONFIG_VALUE_n` | Ajustes de Git que el ejecutor fija para el git que ejecuta tu hook. [Configuración de Git dentro de los hooks de ciclo de vida](#git-configuration-inside-lifecycle-hooks) los describe. Requiere Claude Code v2.1.280 o posterior. |141| `GIT_CONFIG_COUNT`, `GIT_CONFIG_KEY_n`, `GIT_CONFIG_VALUE_n` | Ajustes de Git que el ejecutor fija para el git que ejecuta tu hook. [Configuración de Git dentro de los hooks de ciclo de vida](#git-configuration-inside-lifecycle-hooks) los describe. Requiere Claude Code v2.1.280 o posterior. |
124 142
125El script debe dejar un árbol de trabajo en `CLAUDE_RUNNER_CHECKOUT_PATH` verificado en la revisión solicitada. HEAD desacoplado está bien; el ejecutor crea la rama de trabajo de la sesión encima. El ejecutor verifica que la ruta contenga un `.git` después; si su hook materializa una fuente no git como Perforce o un tarball desempaquetado, establezca `CLAUDE_RUNNER_SKIP_GIT_VERIFY=1` en el entorno del ejecutor para omitir esa verificación. Los flujos basados en git como la creación de rama de trabajo y el envío de resultados requieren un checkout de git, por lo que exporte resultados de árboles no git con un hook [`post-session`](#post-session).143El script debe dejar una copia de trabajo en `CLAUDE_RUNNER_CHECKOUT_PATH` extraída en la revisión solicitada. Un HEAD desacoplado funciona, porque el ejecutor crea la rama de trabajo de la sesión encima.
126 144
127El ejecutor no pasa una credencial git al hook. En su lugar, acuñe una credencial de clon por sesión de la identidad de la sesión: verifique `CLAUDE_CODE_SESSION_ACCESS_TOKEN` con una biblioteca JWT estándar contra el punto final JWKS bajo `CLAUDE_RUNNER_API_BASE_URL`, como se describe en [Verificar el token desde su servicio](/docs/es/self-hosted-environments-identity#verify-the-token-from-your-service), luego haga que su servicio de credenciales emita una credencial de clon de corta duración para la identidad en la reclamación `act` del token. `CLAUDE_RUNNER_CLAUDE_BIN` no se establece en el entorno del hook de checkout, por lo que el subcomando `decode-token` no está disponible aquí. Volver a la autenticación git que el host ya tiene, como un agente SSH, ayudante de credenciales o `.netrc`, también es una opción.145Después de que tu hook regresa, el ejecutor verifica que `CLAUDE_RUNNER_CHECKOUT_PATH` contenga un `.git`. Si tu hook materializa una fuente no git como Perforce o un tarball desempaquetado, establece `CLAUDE_RUNNER_SKIP_GIT_VERIFY=1` en el entorno del ejecutor para omitir esa verificación. Los flujos basados en git como la creación de la rama de trabajo y el envío de resultados requieren un checkout de git, así que exporta los resultados de copias no git con un [hook `post-session`](#post-session).
128 146
129Cuando el hook sale con código distinto de cero, o sale con 0 sin dejar un checkout utilizable detrás, lo que hace el ejecutor depende del repositorio:147<h4 id="get-git-credentials-in-the-hook">
148 Obtener credenciales de git en el hook
149</h4>
130 150
131* **Un repositorio al que la sesión envía resultados**: el ejecutor falla la sesión, y en una salida distinta de cero muestra la cola del stderr del script al usuario.151El ejecutor no pasa una credencial git al hook. El subcomando `decode-token` tampoco está disponible aquí, porque `CLAUDE_RUNNER_CLAUDE_BIN` no se establece en el entorno del hook de checkout. En su lugar, genera una credencial de clon por sesión a partir de la identidad de la sesión, o recurre a la autenticación git propia del host:
132* **Un repositorio que la sesión solo lee**, como un repositorio agregado a una sesión en ejecución: el ejecutor registra una línea `[runner:warn]` con el detalle de falla, publica un paso `Skipped` a la sesión, elimina lo que el hook dejó en la ruta de checkout y continúa con los repositorios restantes. Cuando el ejecutor no puede eliminar la ruta inmediatamente, reintenta la eliminación al final de la sesión. Si omitir deja la sesión sin repositorio en absoluto, el ejecutor falla la sesión de todas formas.
133 152
134Antes de v2.1.228, el ejecutor fallaba la sesión en un fallo de hook para cualquier repositorio, por lo que un repositorio de solo lectura que el hook no podía servir fallaba la sesión nuevamente en cada ejecutor nuevo en el que la sesión se reanudaba.153* **Credencial de clon por sesión**: verifica `CLAUDE_CODE_SESSION_ACCESS_TOKEN` con una biblioteca JWT estándar contra el endpoint JWKS bajo `CLAUDE_RUNNER_API_BASE_URL`, como se describe en [Verificar el token desde tu servicio](/docs/es/self-hosted-environments-identity#verify-the-token-from-your-service). Luego haz que tu servicio de credenciales emita una credencial de clon de corta duración para la identidad en la reclamación `act` del token. Asocia esa credencial a `act.sub`, y no exijas `act.email`.
154* **Autenticación git del host**: usa la autenticación git que el host ya tenga, como un agente SSH, un ayudante de credenciales o `.netrc`.
135 155
136El ejecutor elimina la ruta de checkout después de que la sesión termina.156<h4 id="when-the-hook-fails">
157 Cuando el hook falla
158</h4>
159
160El hook falla cuando sale con código distinto de cero, o sale con 0 sin dejar un checkout utilizable:
161
162* **Un repositorio al que la sesión envía resultados**: el ejecutor falla la sesión, y en una salida distinta de cero muestra la cola del stderr del script al usuario.
163* **Un repositorio que la sesión solo lee**, como un repositorio agregado a una sesión en ejecución: el ejecutor registra una línea `[runner:warn]` con el detalle del fallo, publica un paso `Skipped` en la sesión, elimina lo que el hook haya dejado en la ruta de checkout y continúa con los repositorios restantes. Si al omitirlo la sesión queda sin ningún repositorio, el ejecutor falla la sesión de todas formas.
164
165Cuando el hook tiene éxito, el ejecutor elimina la ruta de checkout después de que la sesión termina.
137 166
138<h3 id="post-session">167<h3 id="post-session">
139 post-session168 post-session
151| `CLAUDE_RUNNER_WORKSPACE_PATHS` | Rutas absolutas separadas por dos puntos de los árboles de trabajo de la sesión. Vacío para sesiones sin repositorio. |180| `CLAUDE_RUNNER_WORKSPACE_PATHS` | Rutas absolutas separadas por dos puntos de los árboles de trabajo de la sesión. Vacío para sesiones sin repositorio. |
152| `CLAUDE_RUNNER_DEBUG_LOG_PATH` | Ruta al registro de depuración de la sesión, aún en disco mientras se ejecuta el hook |181| `CLAUDE_RUNNER_DEBUG_LOG_PATH` | Ruta al registro de depuración de la sesión, aún en disco mientras se ejecuta el hook |
153| `CLAUDE_RUNNER_API_BASE_URL` | URL base de API de Anthropic para llamadas limitadas a sesión |182| `CLAUDE_RUNNER_API_BASE_URL` | URL base de API de Anthropic para llamadas limitadas a sesión |
154| `CLAUDE_RUNNER_CLIENT_PLATFORM` | La superficie del cliente que creó la sesión, como `web_claude_ai`, `desktop_app` o `ios`. No establecido cuando la sesión no tiene una superficie registrada o reconocida. Requiere Claude Code v2.1.229 o posterior. |183| `CLAUDE_RUNNER_CLIENT_PLATFORM` | La superficie del cliente que creó la sesión, como `web_claude_ai`, `desktop_app` o `ios`. No se establece cuando la sesión no tiene una superficie registrada o reconocida, así que haz referencia a ella como `${CLAUDE_RUNNER_CLIENT_PLATFORM:-}` con `set -u`. Requiere Claude Code v2.1.229 o posterior. |
155| `CLAUDE_CODE_SESSION_ACCESS_TOKEN` | El token de acceso de sesión, para llamadas de API limitadas a sesión |184| `CLAUDE_CODE_SESSION_ACCESS_TOKEN` | El token de acceso de sesión, para llamadas de API limitadas a sesión |
156| `GIT_CONFIG_COUNT`, `GIT_CONFIG_KEY_n`, `GIT_CONFIG_VALUE_n` | Ajustes de Git que el ejecutor fija para el git que ejecuta tu hook. [Configuración de Git dentro de los hooks de ciclo de vida](#git-configuration-inside-lifecycle-hooks) los describe. Requiere Claude Code v2.1.280 o posterior. |185| `GIT_CONFIG_COUNT`, `GIT_CONFIG_KEY_n`, `GIT_CONFIG_VALUE_n` | Ajustes de Git que el ejecutor fija para el git que ejecuta tu hook. [Configuración de Git dentro de los hooks de ciclo de vida](#git-configuration-inside-lifecycle-hooks) los describe. Requiere Claude Code v2.1.280 o posterior. |
157 186
158`CLAUDE_RUNNER_EXIT_REASON` toma uno de cuatro valores:187`CLAUDE_RUNNER_EXIT_REASON` toma uno de cuatro valores:
159 188
160* `completed`: la sesión terminó limpiamente. El proceso de Claude Code salió normalmente, o la sesión fue archivada o eliminada mientras aún se estaba ejecutando.189* `completed`: la sesión terminó limpiamente. El proceso de Claude Code salió normalmente, o salió por sí mismo después de que la sesión fue archivada o eliminada.
161* `failed`: el proceso de Claude Code se bloqueó, o la configuración falló después de que comenzó.190* `failed`: el proceso de Claude Code se bloqueó, o la configuración falló después de que comenzó.
162* `interrupted`: el ejecutor detuvo la sesión. Liberó la sesión para liberar la ranura, la sesión agotó el tiempo de espera al inicio, el servidor movió la sesión fuera de este ejecutor, el ejecutor estaba drenando, o la sesión superó su límite [`--kill-session-after-min`](/docs/es/self-hosted-environments-reference#runner-cli-flags).191* `interrupted`: el ejecutor detuvo la sesión, en uno de estos casos:
192 * El ejecutor liberó la sesión para liberar la ranura.
193 * Se agotó el tiempo de espera de la sesión al inicio.
194 * El servidor movió la sesión fuera de este ejecutor.
195 * El sondeo del ejecutor detectó un archivado o una eliminación antes de que el proceso saliera.
196 * El ejecutor estaba drenando.
197 * La sesión superó su límite de [`--kill-session-after-min`](/docs/es/self-hosted-environments-reference#runner-cli-flags).
163* `abandoned`: reservado para una sesión que otro ejecutor reclamó. El hook actualmente no se dispara en ese caso.198* `abandoned`: reservado para una sesión que otro ejecutor reclamó. El hook actualmente no se dispara en ese caso.
164 199
165Los [contadores de ciclo de vida de sesión](/docs/es/self-hosted-environments-reference#session-lifecycle-counter-semantics) cuentan una liberación, un tiempo de espera de inicio y un movimiento de servidor como `completed` en lugar de `interrupted`, porque el ejecutor devolvió la ranura limpiamente. Espere esa diferencia si compara recibos de hook con los contadores.200Si comparas los recibos del hook con los [contadores de ciclo de vida de sesión](/docs/es/self-hosted-environments-reference#session-lifecycle-counter-semantics), espera que algunos recibos `interrupted` cuenten allí como `completed`. Los contadores cuentan como `completed` una liberación, un tiempo de espera agotado al inicio, un movimiento de servidor y un archivado o eliminación que el sondeo del ejecutor detectó primero, porque el ejecutor devolvió la ranura limpiamente.
166 201
167El estado de salida del hook nunca afecta el resultado de la sesión; un fallo se registra e ignora. El ejecutor espera hasta `--post-session-hook-timeout-sec`, 60 segundos por defecto, en cada fin de sesión incluido el apagado del ejecutor. Este ejemplo guarda trabajo no confirmado en una rama de rescate:202El estado de salida del hook nunca afecta el resultado de la sesión; un fallo se registra e ignora. El ejecutor espera hasta `--post-session-hook-timeout-sec`, 60 segundos por defecto, en cada fin de sesión incluido el apagado del ejecutor. Este ejemplo guarda trabajo no confirmado en una rama de rescate:
168 203
169```bash theme={null}204```bash theme={null}
170#!/usr/bin/env bash205#!/usr/bin/env bash
171set -u206set -u
207export GIT_ALLOW_PROTOCOL=${GIT_ALLOW_PROTOCOL:-https:http:ssh}
172IFS=':'208IFS=':'
173# Las sobrescrituras -c prevalecen sobre los ajustes a nivel de repositorio, lo que impide209# -c overrides beat repo-local settings, blocking session-written fsmonitor,
174# que la configuración de fsmonitor, ruta de hooks y programa gpg escrita por la sesión210# hook-path, and gpg-program config from executing code with the hook's
175# ejecute código con los privilegios del hook. -c commit.gpgsign=false también deja211# privileges. -c commit.gpgsign=false also leaves these rescue commits
176# estos commits de rescate sin firmar con --configure-git.212# unsigned under --configure-git.
177# credential.helper y pushurl a nivel de repositorio aún se aplican, y en un ejecutor213# Repo-local credential.helper and pushurl still apply, and on a runner
178# anterior a v2.1.280 también core.sshCommand; si el hook tiene credenciales que214# before v2.1.280 so does core.sshCommand; if the hook holds credentials
179# la sesión no tenía, consulta la nota debajo del script.215# the session didn't, see the note below the script.
180g() { git -c core.fsmonitor=false -c core.hooksPath=/dev/null \216g() { git -c core.fsmonitor=false -c core.hooksPath=/dev/null \
181 -c commit.gpgsign=false "$@"; }217 -c commit.gpgsign=false "$@"; }
182for ws in $CLAUDE_RUNNER_WORKSPACE_PATHS; do218for ws in $CLAUDE_RUNNER_WORKSPACE_PATHS; do
188done224done
189```225```
190 226
227La línea `GIT_ALLOW_PROTOCOL` del script limita git a remotos HTTPS, HTTP y SSH. Si el entorno del ejecutor ya establece su propia lista `GIT_ALLOW_PROTOCOL` no vacía, el script conserva esa lista.
228
191El hook hace push con las credenciales git que estén disponibles en su propio entorno en el host del ejecutor. Con la [postura de no credenciales en la imagen](/docs/es/self-hosted-environments-deploy#configure-git), incluido cuando el clon integrado pasa por el proxy git de Anthropic, no hay ninguna, así que genera una credencial de push de corta duración dentro del hook antes de hacer push: intercambia el token de sesión que el hook recibe en `CLAUDE_CODE_SESSION_ACCESS_TOKEN` con tu propio servicio de tokens, verificándolo como se describe en [Verificar la identidad de sesión](/docs/es/self-hosted-environments-identity). Cuando el hook tiene una credencial que la sesión no tenía, reemplaza `origin` con una URL proporcionada por el operador y pasa `-c credential.helper=` más tu propio ayudante. [Configuración de Git dentro de los hooks de ciclo de vida](#git-configuration-inside-lifecycle-hooks) describe lo que la configuración escrita por la sesión aún puede afectar.229El hook hace push con las credenciales git que estén disponibles en su propio entorno en el host del ejecutor. Con la [postura de no credenciales en la imagen](/docs/es/self-hosted-environments-deploy#configure-git), incluido cuando el clon integrado pasa por el proxy git de Anthropic, no hay ninguna, así que genera una credencial de push de corta duración dentro del hook antes de hacer push: intercambia el token de sesión que el hook recibe en `CLAUDE_CODE_SESSION_ACCESS_TOKEN` con tu propio servicio de tokens, verificándolo como se describe en [Verificar la identidad de sesión](/docs/es/self-hosted-environments-identity). Cuando el hook tiene una credencial que la sesión no tenía, reemplaza `origin` con una URL proporcionada por el operador y pasa `-c credential.helper=` más tu propio ayudante. [Configuración de Git dentro de los hooks de ciclo de vida](#git-configuration-inside-lifecycle-hooks) describe lo que la configuración escrita por la sesión aún puede afectar.
192 230
193<h4 id="hook-timing-when-the-runner-releases-a-session">231<h4 id="hook-timing-when-the-runner-releases-a-session">
264| `CLAUDE_RUNNER_ORDER_ID` | Clave de idempotencia opaca, única por solicitud de generación y segura para nombres de recursos de Kubernetes. Úsela como clave de deduplicación de su aprovisionador. |302| `CLAUDE_RUNNER_ORDER_ID` | Clave de idempotencia opaca, única por solicitud de generación y segura para nombres de recursos de Kubernetes. Úsela como clave de deduplicación de su aprovisionador. |
265| `CLAUDE_RUNNER_SESSION_ID` | La sesión para la que es esta solicitud. Se repite en cada resolicitud de la sesión, por lo que úsela para registro y enrutamiento, no como clave de deduplicación. Vacío para solicitudes de precalentamiento, que arrancan un ejecutor en espera antes de cualquier sesión específica cuando [`--min-idle`](/docs/es/self-hosted-environments-reference#orchestrator-cli-flags) se establece, por lo que no asuma que la variable se establece. |303| `CLAUDE_RUNNER_SESSION_ID` | La sesión para la que es esta solicitud. Se repite en cada resolicitud de la sesión, por lo que úsela para registro y enrutamiento, no como clave de deduplicación. Vacío para solicitudes de precalentamiento, que arrancan un ejecutor en espera antes de cualquier sesión específica cuando [`--min-idle`](/docs/es/self-hosted-environments-reference#orchestrator-cli-flags) se establece, por lo que no asuma que la variable se establece. |
266| `CLAUDE_RUNNER_SESSION_UUID` | El mismo ID de sesión en forma UUID canónica. Vacío para solicitudes de precalentamiento. |304| `CLAUDE_RUNNER_SESSION_UUID` | El mismo ID de sesión en forma UUID canónica. Vacío para solicitudes de precalentamiento. |
267| `CLAUDE_RUNNER_ATTEMPT` | Cuántas solicitudes de generación ha tenido esta sesión. `0` para solicitudes de precalentamiento. |305| `CLAUDE_RUNNER_ATTEMPT` | Un contador por sesión para usar en el registro. No es un recuento de reintentos ni un recuento de solicitudes. `0` para solicitudes de precalentamiento, aunque una solicitud para una sesión también puede llevar `0`. |
268| `CLAUDE_RUNNER_ORDER_SERVER_TIME` | Hora del servidor del encabezado HTTP `Date` de la respuesta de sondeo. Cuando el hook verifica el `exp` del JWT de orden de trabajo, compare contra este valor en lugar del reloj local para tolerar sesgo. Vacío cuando la puerta de enlace omitió el encabezado. |306| `CLAUDE_RUNNER_ORDER_SERVER_TIME` | Hora del servidor del encabezado HTTP `Date` de la respuesta de sondeo. Cuando el hook verifica el `exp` del JWT de orden de trabajo, compare contra este valor en lugar del reloj local para tolerar sesgo. Vacío cuando la puerta de enlace omitió el encabezado. |
269| `CLAUDE_RUNNER_POOL_ID` | El ID del entorno al que el nuevo ejecutor debe unirse, en forma `ccpool_...` |307| `CLAUDE_RUNNER_POOL_ID` | El ID del entorno al que el nuevo ejecutor debe unirse, en forma `ccpool_...` |
270| `CLAUDE_RUNNER_ACCOUNT_ID` | ID etiquetado de la cuenta que encoló la sesión, para enrutamiento por cuenta, cuota o contracargo. Vacío cuando no está disponible, y siempre vacío para sesiones de canal Claude Tag, que ninguna cuenta encola. |308| `CLAUDE_RUNNER_ACCOUNT_ID` | ID etiquetado de la cuenta que encoló la sesión, para enrutamiento por cuenta, cuota o contracargo. Vacío cuando no está disponible, y siempre vacío para sesiones de canal Claude Tag, que ninguna cuenta encola. |
271| `CLAUDE_RUNNER_ACCOUNT_EMAIL` | Correo electrónico de la cuenta que encoló la sesión. Vacío cuando no está disponible. Trate el correo electrónico como información de identificación personal y no lo registre. |309| `CLAUDE_RUNNER_ACCOUNT_EMAIL` | Correo electrónico de la cuenta que encoló la sesión. Vacío cuando no está disponible. Trate el correo electrónico como información de identificación personal y no lo registre. |
272| `CLAUDE_RUNNER_PRIMARY_REPO_URL` | URL de la primera fuente git de la sesión, para enrutamiento a un ejecutor con ese repositorio precalentado. Vacío cuando la sesión no tiene fuentes git. |310| `CLAUDE_RUNNER_PRIMARY_REPO_URL` | URL de la primera fuente git de la sesión, para enrutamiento a un ejecutor con ese repositorio precalentado. Vacío cuando la sesión no tiene fuentes git. |
273| `CLAUDE_RUNNER_PRIMARY_REPO_REVISION` | Revisión de la primera fuente git de la sesión: rama, SHA o etiqueta. Vacío cuando no se especifica. |311| `CLAUDE_RUNNER_PRIMARY_REPO_REVISION` | Revisión de la primera fuente git de la sesión: rama, SHA, etiqueta o nombre de referencia completo. Vacío cuando no se especifica. |
274| `CLAUDE_RUNNER_REPO_SOURCES` | Matriz JSON de `{url, revision}` para todas las fuentes git de la sesión, para hooks que enrutan en un repositorio secundario. Vacío cuando no hay fuentes. |312| `CLAUDE_RUNNER_REPO_SOURCES` | Matriz JSON de `{url, revision}` para todas las fuentes git de la sesión, para hooks que enrutan en un repositorio secundario. Vacío cuando no hay fuentes. |
275| `CLAUDE_RUNNER_CORRELATION_ID` | El ID de correlación proporcionado en la creación de sesión, devuelto para que el hook pueda asignar esta orden de trabajo a la solicitud que creó la sesión. Vacío cuando la sesión no tiene ninguno. |313| `CLAUDE_RUNNER_CORRELATION_ID` | El ID de correlación proporcionado en la creación de sesión, devuelto para que el hook pueda asignar esta orden de trabajo a la solicitud que creó la sesión. Vacío cuando la sesión no tiene ninguno. |
276| `CLAUDE_RUNNER_CLIENT_PLATFORM` | La superficie del cliente que creó la sesión, como `web_claude_ai`, `desktop_app`, `ios` o `scheduled_trigger`, para análisis de adopción. No establecido cuando la sesión no tiene una superficie registrada o reconocida, y para solicitudes de precalentamiento; verifíquelo con `[ -n "${CLAUDE_RUNNER_CLIENT_PLATFORM:-}" ]`, que permanece seguro bajo `set -u`. |314| `CLAUDE_RUNNER_CLIENT_PLATFORM` | La superficie del cliente que creó la sesión, como `web_claude_ai`, `desktop_app`, `ios` o `scheduled_trigger`, para análisis de adopción. No establecido cuando la sesión no tiene una superficie registrada o reconocida, y para solicitudes de precalentamiento; verifíquelo con `[ -n "${CLAUDE_RUNNER_CLIENT_PLATFORM:-}" ]`, que permanece seguro bajo `set -u`. |
282* **Use `--capacity 1` en ejecutores generados**: una orden de trabajo vinculada a sesión registra exactamente un ejecutor vinculado a esa sesión, por lo que una capacidad más alta agrega espacios que nunca reciben trabajo, y el ejecutor registra una advertencia al inicio.320* **Use `--capacity 1` en ejecutores generados**: una orden de trabajo vinculada a sesión registra exactamente un ejecutor vinculado a esa sesión, por lo que una capacidad más alta agrega espacios que nunca reciben trabajo, y el ejecutor registra una advertencia al inicio.
283* **Las órdenes de trabajo de precalentamiento registran sin vincular**: el ejecutor en espera no está vinculado a una sesión y reclama trabajo en cola como un ejecutor de flota fija.321* **Las órdenes de trabajo de precalentamiento registran sin vincular**: el ejecutor en espera no está vinculado a una sesión y reclama trabajo en cola como un ejecutor de flota fija.
284 322
285El contrato tiene cuatro reglas agnósticas del aprovisionador:323El contrato tiene cuatro reglas, sea cual sea la plataforma en la que tu hook aprovisiona:
286 324
2871. **Sea idempotente en `CLAUDE_RUNNER_ORDER_ID`.** La reentrega de la misma solicitud debe generar como máximo un ejecutor. Derive un nombre de recurso determinista del ID de orden y deje que su plataforma rechace el duplicado. No use `CLAUDE_RUNNER_SESSION_ID` como clave en su lugar. Cada resolicitud de una sesión lleva el mismo ID de sesión con un nuevo ID de orden, por lo que una carga de trabajo nombrada o deduplicada por el ID de sesión se crea una vez y nunca más para esa sesión.3251. **Sea idempotente en `CLAUDE_RUNNER_ORDER_ID`.** La reentrega de la misma solicitud debe generar como máximo un ejecutor. Derive un nombre de recurso determinista del ID de orden y deje que su plataforma rechace el duplicado. No use `CLAUDE_RUNNER_SESSION_ID` como clave en su lugar. Cada resolicitud de una sesión lleva el mismo ID de sesión con un nuevo ID de orden, por lo que una carga de trabajo nombrada o deduplicada por el ID de sesión se crea una vez y nunca más para esa sesión.
2882. **No reintente la carga de trabajo.** Un ID de orden significa como máximo una carga de trabajo creada. Si el ejecutor nunca se registra, Anthropic reintenta con un ID de orden nuevo después de `--expected-spawn-seconds`.3262. **No reintente la carga de trabajo.** Un ID de orden significa como máximo una carga de trabajo creada. Si el ejecutor nunca se registra, Anthropic reintenta con un ID de orden nuevo después de `--expected-spawn-seconds`.
2893. **Use el contrato de código de salida.** Salida 0 significa enviado. Salida 1 significa fallo reintentable; la sesión retrocede y se reintenta. Salida 2 o superior significa no reintentable; la sesión se bloquea de generar nuevamente hasta que un [Propietario](/docs/es/cloud-environments#organization-shared-environments) selecciona **Retry** en ella en la pestaña **Activity** del entorno. En salida distinta de cero, la cola del stderr del hook aparece allí como la razón de falla, por lo que escriba el error procesable a stderr y nunca secretos. Para una solicitud de precalentamiento no hay sesión para fallar: el orquestador registra una salida distinta de cero localmente solamente, y el servidor reintenta la generación después del arrendamiento.3273. **Usa el contrato de código de salida.** Sal con el estado que corresponda al resultado:
2904. **Establezca `--expected-spawn-seconds` a al menos su tiempo de arranque p99.** Este es el arrendamiento del lado del servidor. Todas las réplicas del orquestador deben usar el mismo valor.328
329 * **Salida 0**: enviado.
330 * **Salida 1**: fallo reintentable. La sesión espera un tiempo y se vuelve a ofrecer.
331 * **Salida 2 o superior**: fallo no reintentable. La sesión queda bloqueada para generar nuevamente hasta que un usuario le envíe un mensaje nuevo o un [Propietario](/docs/es/cloud-environments#organization-shared-environments) seleccione **Retry** en ella en la pestaña **Activity** del entorno.
332
333 En una salida distinta de cero, el final del stderr del hook aparece en la pestaña **Activity** como la razón del fallo, así que escribe el error procesable en stderr y nunca escribas secretos allí. En un hook de shell, [mantén los fallos transitorios reintentables](#keep-transient-failures-retryable-in-a-shell-hook).
334
335 Una solicitud de precalentamiento no tiene sesión que pueda fallar: el orquestador registra una salida distinta de cero solo localmente, y el servidor vuelve a solicitar la generación después de que expira el arrendamiento de `--expected-spawn-seconds`.
3364. **Establece `--expected-spawn-seconds` en al menos tu tiempo p99 desde la solicitud de generación hasta el registro del ejecutor.** Mide desde el momento en que el orquestador recibe la solicitud de generación, e incluye cualquier espera de capacidad en tu plataforma además del tiempo de arranque. Este valor es el arrendamiento del lado del servidor, y la orden de trabajo expira con él, por lo que un ejecutor cuya carga de trabajo tarde más no puede registrarse. Todas las réplicas del orquestador deben usar el mismo valor.
291 337
292Todo lo que el hook escribe a stdout o stderr aparece en el registro del orquestador con credenciales automáticamente redactadas. Si las sesiones permanecen en cola, verifique el cuerpo `/healthz` del orquestador para contar colas, luego abra la pestaña **Activity** de su entorno en la [página de administración **Cloud environments**](https://claude.ai/admin-settings/cloud-environments): expanda una sesión fallida allí para su error de generación, y seleccione **Retry** para reintentarla.338Todo lo que el hook escribe a stdout o stderr aparece en el registro del orquestador con credenciales automáticamente redactadas. Si las sesiones permanecen en cola, verifique el cuerpo `/healthz` del orquestador para contar colas, luego abra la pestaña **Activity** de su entorno en la [página de administración **Cloud environments**](https://claude.ai/admin-settings/cloud-environments): expanda una sesión fallida allí para su error de generación, y seleccione **Retry** para reintentarla.
293 339
294Una sesión que permanece en cola sin error de generación en la pestaña **Activity** puede significar que el hook está codificado en el ID de sesión. Para confirmar, verifique si su plataforma tiene una carga de trabajo para la primera solicitud de generación de esa sesión y ninguna para las resolicitudes. Si es así, codifique la carga de trabajo en `CLAUDE_RUNNER_ORDER_ID` en su lugar.340Una sesión que permanece en cola sin error de generación en la pestaña **Activity** puede significar que el hook está codificado en el ID de sesión. Para confirmar, verifique si su plataforma tiene una carga de trabajo para la primera solicitud de generación de esa sesión y ninguna para las resolicitudes. Si es así, codifique la carga de trabajo en `CLAUDE_RUNNER_ORDER_ID` en su lugar.
295 341
342<h4 id="keep-transient-failures-retryable-in-a-shell-hook">
343 Mantén los fallos transitorios reintentables en un hook de shell
344</h4>
345
346En un hook de shell que usa `set -e`, un fallo que un reintento podría haber resuelto puede bloquear la sesión. El hook se detiene en el comando que falla y sale con el estado propio de ese comando, y el orquestador aplica el contrato de código de salida a ese estado. Muchos fallos devuelven un estado de 2 o superior, como `127` cuando un comando no está instalado y `22` de `curl --fail` ante un error HTTP, por lo que bloquean la sesión en su primer fallo.
347
348Una sesión que el hook ya bloqueó permanece bloqueada hasta que un usuario le envíe un mensaje nuevo o un [Propietario](/docs/es/cloud-environments#organization-shared-environments) seleccione **Retry** en ella en la pestaña **Activity** del entorno.
349
350Para convertir ese tipo de fallo en una salida 1, coloca estas líneas justo debajo de la línea `#!` del hook, por encima de cualquier cosa que pueda fallar:
351
352```bash theme={null}
353set -e
354PERMANENT=; permanent() { printf '%s\n' "$*" >&2; PERMANENT=1; exit 2; }
355trap 'rc=$?; [ "$rc" -eq 0 ] || [ -n "${PERMANENT:-}" ] || exit 1' EXIT
356```
357
358Estas líneas cambian cómo se comporta el resto del hook, así que revísalo en busca de cada uno de estos patrones después de agregarlas:
359
360* **`exit 2` o superior a secas**: con el trap establecido, se convierte en salida 1. Para un error que ningún reintento puede corregir, llama a `permanent` con el motivo en su lugar, como `permanent "namespace claude-runners does not exist"`. Llámalo en el shell principal, no dentro de `$( )`, `( )` ni de una tubería.
361* **`exec`**: no inicies el último comando del hook con `exec`, porque `exec` reemplaza el shell y el trap no se ejecuta.
362* **Segundo trap `EXIT`**: un segundo `trap ... EXIT` reemplaza al primero, así que combina los dos en un solo trap. Coloca tus comandos de limpieza justo después de `rc=$?;` y termina cada uno con `|| true;`. Así la limpieza se ejecuta tanto en caso de fallo como de éxito, y un comando de limpieza que falla no establece el estado de salida del hook. Este trap combinado muestra la forma, con `your-cleanup-command` en lugar de tu propio comando:
363
364 ```bash theme={null}
365 trap 'rc=$?; your-cleanup-command || true; [ "$rc" -eq 0 ] || [ -n "${PERMANENT:-}" ] || exit 1' EXIT
366 ```
367* **Comandos a los que se les permite fallar**: si el hook no usaba `set -e` antes, ahora se detiene en el primer comando que devuelve un valor distinto de cero, como una búsqueda que no encuentra nada o un envío duplicado que tu plataforma rechaza. Si el hook actúa según el resultado, convierte ese comando en la condición de un `if`. Si ignora el resultado, añade `|| true` después del comando.
368
369Para confirmar que el trap funciona, agrega justo debajo de la línea `trap` una línea que llame a un comando que no existe, como `no-such-command`. Ejecuta el archivo del hook desde tu shell y comprueba que `echo $?` imprima `1`; luego elimina la línea.
370
296<h2 id="send-model-requests-to-bedrock-or-agent-platform">371<h2 id="send-model-requests-to-bedrock-or-agent-platform">
297 Enviar solicitudes de modelo a Bedrock o Agent Platform372 Enviar solicitudes de modelo a Bedrock o Agent Platform
298</h2>373</h2>
381Una sesión que envía solicitudes de modelo a Amazon Bedrock o a Agent Platform de Google Cloud difiere de una sesión en la API de Anthropic en estos aspectos:456Una sesión que envía solicitudes de modelo a Amazon Bedrock o a Agent Platform de Google Cloud difiere de una sesión en la API de Anthropic en estos aspectos:
382 457
383* **Políticas de claude.ai**: la [configuración administrada por el servidor](/docs/es/server-managed-settings) no llega a estas sesiones. Tampoco llegan las políticas de organización que un Owner establece en la configuración de administración de Claude Code, por lo que Claude Code no las aplica dentro de la sesión. Coloca las reglas de las que dependes en el [archivo de configuración administrada](/docs/es/managed-settings#delivery-mechanisms) de la imagen del runner.458* **Políticas de claude.ai**: la [configuración administrada por el servidor](/docs/es/server-managed-settings) no llega a estas sesiones. Tampoco llegan las políticas de organización que un Owner establece en la configuración de administración de Claude Code, por lo que Claude Code no las aplica dentro de la sesión. Coloca las reglas de las que dependes en el [archivo de configuración administrada](/docs/es/managed-settings#delivery-mechanisms) de la imagen del runner.
459* **Skills de la cuenta**: estas sesiones no descargan los skills habilitados para la cuenta de claude.ai de una persona. Consulta [Cómo se ensambla la configuración de cada sesión](#how-each-session’s-config-is-assembled).
384* **Archivos**: los archivos que las personas adjuntan a una sesión en claude.ai o en la aplicación móvil o de escritorio no llegan a ella, y Claude no puede devolver archivos con la [herramienta `SendUserFile`](/docs/es/tools-reference). En su lugar, coloca los archivos de entrada en el repositorio o en el runner.460* **Archivos**: los archivos que las personas adjuntan a una sesión en claude.ai o en la aplicación móvil o de escritorio no llegan a ella, y Claude no puede devolver archivos con la [herramienta `SendUserFile`](/docs/es/tools-reference). En su lugar, coloca los archivos de entrada en el repositorio o en el runner.
385* **Selección de modelo**: el plano de control de Anthropic envía el modelo de cada sesión y, cuando una sesión se inicia sin uno, Claude Code usa su modelo predeterminado para el proveedor. El runner elimina `ANTHROPIC_MODEL` y `ANTHROPIC_DEFAULT_MODEL` del entorno que pasa a las sesiones. Los ejemplos de las páginas de los proveedores establecen `ANTHROPIC_MODEL`, pero en el entorno del runner ninguna de las dos variables tiene efecto. Las variables por familia de Fijar versiones de modelos para [Amazon Bedrock](/docs/es/amazon-bedrock#4-pin-model-versions) y [Agent Platform](/docs/es/google-vertex-ai#5-pin-model-versions) sí llegan a las sesiones. Deciden a qué se resuelve un alias como `opus`, no a qué se resuelve un ID de modelo completo.461* **Selección de modelo**: el plano de control de Anthropic envía el modelo de cada sesión y, cuando una sesión se inicia sin uno, Claude Code usa su modelo predeterminado para el proveedor. No puedes elegir el modelo con `ANTHROPIC_MODEL` ni con `ANTHROPIC_DEFAULT_MODEL` en el entorno del runner, pero sí puedes fijar a qué se resuelve un alias:
462 * **`ANTHROPIC_MODEL` y `ANTHROPIC_DEFAULT_MODEL`**: el runner las elimina del entorno que pasa a las sesiones, aunque los ejemplos de las páginas de los proveedores establezcan `ANTHROPIC_MODEL`.
463 * **Variables de fijación por familia**: las variables de Fijar versiones de modelos para [Amazon Bedrock](/docs/es/amazon-bedrock#4-pin-model-versions) y [Agent Platform](/docs/es/google-vertex-ai#5-pin-model-versions) sí llegan a las sesiones. Deciden a qué se resuelve un alias como `opus`, no a qué se resuelve un ID de modelo completo.
386* **Modelos que tu cuenta no ofrece**: una sesión puede fallar en un mensaje con un error que nombra el modelo. Habilita los modelos que tus desarrolladores pueden elegir, el modelo en segundo plano descrito en Fijar versiones de modelos y el modelo clasificador que usa el [modo automático](/docs/es/permission-modes#enable-auto-mode-on-bedrock-agent-platform-or-foundry). En Amazon Bedrock, permite cada uno de ellos en tu política.464* **Modelos que tu cuenta no ofrece**: una sesión puede fallar en un mensaje con un error que nombra el modelo. Habilita los modelos que tus desarrolladores pueden elegir, el modelo en segundo plano descrito en Fijar versiones de modelos y el modelo clasificador que usa el [modo automático](/docs/es/permission-modes#enable-auto-mode-on-bedrock-agent-platform-or-foundry). En Amazon Bedrock, permite cada uno de ellos en tu política.
387* **Búsqueda web y modo rápido**: la [búsqueda web](/docs/es/tools-reference#websearch-tool-behavior) no está disponible en Amazon Bedrock, y el [modo rápido](/docs/es/fast-mode) no está disponible en ninguno de los dos proveedores. Para otras capacidades que varían según el proveedor, consulta [Capacidades de la CLI que varían según el proveedor](/docs/es/feature-availability#cli-capabilities-that-vary-by-provider).465* **Búsqueda web y modo rápido**: la [búsqueda web](/docs/es/tools-reference#websearch-tool-behavior) no está disponible en Amazon Bedrock, y el [modo rápido](/docs/es/fast-mode) no está disponible en ninguno de los dos proveedores. Para otras capacidades que varían según el proveedor, consulta [Capacidades de la CLI que varían según el proveedor](/docs/es/feature-availability#cli-capabilities-that-vary-by-provider).
388 466
411 489
412Las sesiones heredan el entorno del runner, así que define [`ENABLE_TOOL_SEARCH`](/docs/es/mcp#scale-with-mcp-tool-search) allí para controlar la búsqueda de herramientas MCP en cada sesión que inicie un runner; la página de MCP describe los valores.490Las sesiones heredan el entorno del runner, así que define [`ENABLE_TOOL_SEARCH`](/docs/es/mcp#scale-with-mcp-tool-search) allí para controlar la búsqueda de herramientas MCP en cada sesión que inicie un runner; la página de MCP describe los valores.
413 491
492<a id="connection-timing" />
493
494<h3 id="wait-for-mcp-servers-before-the-first-turn">
495 Esperar a los servidores MCP antes del primer turno
496</h3>
497
498Una sesión autohospedada espera brevemente a los servidores MCP que aún se están conectando, en dos momentos distintos. Si un servidor no llega a tiempo a una de las esperas, sus herramientas faltan cuando comienza el primer turno, y quedan disponibles más tarde sin que tengas que hacer nada. Las dos esperas son:
499
500* **Inicio de la sesión**: antes de que se tome la lista de herramientas por primera vez, la sesión espera de forma predeterminada hasta 5 segundos a un servidor HTTP o SSE cuya entrada defina [`alwaysLoad: true`](/docs/es/mcp#exempt-a-server-from-deferral), o a todos los servidores cuando defines [`MCP_CONNECTION_NONBLOCKING=0`](/docs/es/env-vars) en el entorno del runner. En los demás casos, los servidores HTTP y SSE se conectan en segundo plano. Mientras la sesión espera aquí, tarda más en inicializarse. [`MCP_CONNECT_TIMEOUT_MS`](/docs/es/env-vars) cambia el valor predeterminado de 5 segundos.
501* **Primer turno**: después de que llega el mensaje, el primer turno espera hasta 2 segundos a los servidores stdio que aún se están conectando. Mientras la sesión espera aquí, la primera respuesta tarda más. Para cambiar cuánto dura esta espera, define [`CLAUDE_CODE_MCP_STARTUP_WAIT_MS`](/docs/es/env-vars) en el entorno del runner. No cambia qué servidores abarca la espera. Requiere Claude Code v2.1.274 o posterior.
502
503`claude mcp add` no tiene un flag `alwaysLoad`. Para definir la clave, agrega el servidor con `claude mcp add-json`, que la recibe en el JSON del servidor y la escribe en `.claude.json`. En tu Dockerfile:
504
505```dockerfile theme={null}
506RUN claude mcp add-json core '{"type":"http","url":"https://mcp.example.com/mcp","alwaysLoad":true}' --scope user
507```
508
509Si las herramientas de un servidor tampoco aparecen en turnos posteriores, comprueba si el servidor llegó a la sesión, como se describe en [Servidores MCP](#mcp-servers).
510
414<h3 id="turn-off-built-in-session-tools">511<h3 id="turn-off-built-in-session-tools">
415 Desactivar las herramientas de sesión integradas512 Desactivar las herramientas de sesión integradas
416</h3>513</h3>
571 668
572Establezca `SELF_HOSTED_RUNNER_HOST_CONFIG_DIR` para sembrar desde una ruta diferente, o apúntelo a un directorio vacío para deshabilitar la siembra.669Establezca `SELF_HOSTED_RUNNER_HOST_CONFIG_DIR` para sembrar desde una ruta diferente, o apúntelo a un directorio vacío para deshabilitar la siembra.
573 670
574El `.claude/settings.json` confirmado en el repositorio se superpone como configuración del proyecto. En una sesión con varios repositorios, [como máximo tiene efecto el archivo de un solo repositorio](#repository-settings-in-sessions-with-several-repositories). Las sesiones también leen [`managed-settings.json`](/docs/es/settings#where-settings-live) desde la ruta estándar del sistema en tu imagen del ejecutor. Si sus claves se aplican junto con la [configuración administrada por el servidor](/docs/es/server-managed-settings) depende de [cómo Claude Code combina las fuentes administradas](/docs/es/managed-settings#how-claude-code-combines-managed-sources): de forma predeterminada, cuando tu organización entrega cualquier clave administrada por el servidor, las sesiones ignoran el archivo de la imagen del ejecutor, salvo las [claves que Claude Code lee de todas las fuentes de administrador](/docs/es/managed-settings#keys-read-from-every-admin-source), como el bloque `env`, los bloqueos del sandbox, las rutas de los binarios del sandbox y `forceRemoteSettingsRefresh`. Consulta [precedencia de configuración](/docs/es/settings#settings-precedence).671Las sesiones también leen estos archivos de configuración:
672
673* **Configuración del proyecto**: un `.claude/settings.json` confirmado en el repositorio se superpone a la línea de base a nivel de usuario. En una sesión con varios repositorios, [como máximo tiene efecto el archivo de un solo repositorio](#repository-settings-in-sessions-with-several-repositories).
674* **Configuración administrada**: las sesiones leen [`managed-settings.json`](/docs/es/settings#where-settings-live) desde la ruta estándar del sistema en tu imagen del ejecutor. Para saber si sus claves se aplican junto con la [configuración administrada por el servidor](/docs/es/server-managed-settings), consulta [cómo Claude Code combina las fuentes administradas](/docs/es/managed-settings#how-claude-code-combines-managed-sources).
675
676Para conocer el orden en que se aplican estas fuentes, consulta [precedencia de configuración](/docs/es/settings#settings-precedence).
575 677
576Cuando el plano de control de Anthropic proporciona una sesión con [hooks de Claude Code](/docs/es/hooks), el ejecutor los instala junto a, no sobre, su propia configuración. Requiere Claude Code v2.1.229 o posterior.678Cuando el plano de control de Anthropic proporciona una sesión con [hooks de Claude Code](/docs/es/hooks), el ejecutor los instala junto a, no sobre, su propia configuración. Requiere Claude Code v2.1.229 o posterior.
577 679
579* **Quién los autor**: el plano de control puebla los scripts desde constantes fijas en su propia implementación, nunca desde entrada por sesión o de terceros.681* **Quién los autor**: el plano de control puebla los scripts desde constantes fijas en su propia implementación, nunca desde entrada por sesión o de terceros.
580* **Qué aún los rige**: los hooks entregados a través de `--settings` entran en la configuración de hook ordinaria fusionada, no en el nivel administrado, por lo que su configuración administrada aún se aplica. `disableAllHooks` los deshabilita, y no están entre las categorías que [`allowManagedHooksOnly`](/docs/es/settings-reference#allowmanagedhooksonly) mantiene cargadas.682* **Qué aún los rige**: los hooks entregados a través de `--settings` entran en la configuración de hook ordinaria fusionada, no en el nivel administrado, por lo que su configuración administrada aún se aplica. `disableAllHooks` los deshabilita, y no están entre las categorías que [`allowManagedHooksOnly`](/docs/es/settings-reference#allowmanagedhooksonly) mantiene cargadas.
581 683
684Cuando una persona inicia su propia sesión, Claude Code también descarga los [skills habilitados para su cuenta de claude.ai](/docs/es/skills#skills-in-cowork-and-cloud-sessions) en el directorio de configuración de esa sesión. Una ejecución de una [rutina](/docs/es/routines) no recibe los skills de su propietario, y una sesión que [envía solicitudes de modelo a Bedrock o Agent Platform](#send-model-requests-to-bedrock-or-agent-platform) no descarga ninguno. Para un skill que esas sesiones necesiten, haz commit de él en el `.claude/skills/` del repositorio o agrégalo a tu imagen del ejecutor.
685
582Fuera de las sesiones de [Claude Tag](https://claude.com/docs/claude-tag/overview), una sesión en un entorno autohospedado se ejecuta con la [memoria automática](/docs/es/memory#auto-memory) desactivada de forma predeterminada. Para instrucciones que deban mantenerse entre sesiones, usa el `CLAUDE.md` de tu imagen del ejecutor o del repositorio.686Fuera de las sesiones de [Claude Tag](https://claude.com/docs/claude-tag/overview), una sesión en un entorno autohospedado se ejecuta con la [memoria automática](/docs/es/memory#auto-memory) desactivada de forma predeterminada. Para instrucciones que deban mantenerse entre sesiones, usa el `CLAUDE.md` de tu imagen del ejecutor o del repositorio.
583 687
584La instantánea del `~/.claude/` del host que toma el ejecutor excluye el directorio `projects/`. La ubicación de almacenamiento predeterminada de la memoria automática está dentro de ese directorio. Si colocas archivos de memoria allí, el ejecutor no los copia a las sesiones, y no activan la memoria automática.688La instantánea del `~/.claude/` del host que toma el ejecutor excluye el directorio `projects/`. La ubicación de almacenamiento predeterminada de la memoria automática está dentro de ese directorio. Si colocas archivos de memoria allí, el ejecutor no los copia a las sesiones, y no activan la memoria automática.