10 Para una guía de inicio rápido con ejemplos, consulte [Automatizar acciones con hooks](/docs/es/hooks-guide).10 Para una guía de inicio rápido con ejemplos, consulte [Automatizar acciones con hooks](/docs/es/hooks-guide).
11</Tip>11</Tip>
12 12
13Los hooks son comandos de shell definidos por el usuario, puntos finales HTTP o prompts de LLM que se ejecutan automáticamente en puntos específicos del ciclo de vida de Claude Code. Utilice esta referencia para buscar esquemas de eventos, opciones de configuración, formatos de entrada/salida JSON y características avanzadas como hooks asincronos, hooks HTTP y hooks de herramientas MCP. Si está configurando hooks por primera vez, comience con la [guía](/docs/es/hooks-guide) en su lugar.13Los hooks son comandos de shell definidos por el usuario, puntos finales HTTP, llamadas a herramientas MCP, prompts de LLM o subagentes que se ejecutan automáticamente en puntos específicos del ciclo de vida de Claude Code. Claude Code dispara los mismos eventos de hooks dondequiera que se ejecute: sesiones en la terminal, extensiones de IDE, la [aplicación de escritorio](/docs/es/desktop-quickstart) y [Claude Code en la web](/docs/es/claude-code-on-the-web). Utilice esta referencia para buscar esquemas de eventos, opciones de configuración, formatos de entrada/salida JSON y características avanzadas como hooks asincronos, hooks HTTP y hooks de herramientas MCP.
14 14
15<h2 id="hook-lifecycle">15<h2 id="hook-lifecycle">
16 Ciclo de vida de los hooks16 Ciclo de vida de los hooks
17</h2>17</h2>
18 18
19Los hooks se activan en puntos específicos durante una sesión de Claude Code. Cuando se activa un evento y un matcher coincide, Claude Code pasa contexto JSON sobre el evento a su controlador de hook. Para hooks de comando, la entrada llega en stdin. Para hooks HTTP, llega como el cuerpo de la solicitud POST. Su controlador puede entonces inspeccionar la entrada, tomar medidas y opcionalmente devolver una decisión.19Claude Code ejecuta hooks en puntos específicos durante una sesión. Cuando se activa un evento y un matcher coincide, Claude Code pasa contexto JSON sobre el evento a su controlador de hook. Para hooks de comando, la entrada llega en stdin. Para hooks HTTP, llega como el cuerpo de la solicitud POST. Su controlador puede entonces inspeccionar la entrada, tomar medidas y opcionalmente devolver una decisión.
20 20
21Los eventos se dividen en tres cadencias:21Los eventos se dividen en tres cadencias:
22 22
23* una vez por sesión: `SessionStart` y `SessionEnd`23* por sesión: `SessionStart` y `SessionEnd`
24* una vez por turno: `UserPromptSubmit`, `Stop` y `StopFailure`24* por turno: `UserPromptSubmit`, `Stop` y `StopFailure`
25* en cada llamada a herramienta dentro del bucle agentico: `PreToolUse` y `PostToolUse`25* en cada llamada a herramienta dentro del bucle agentico: `PreToolUse` y `PostToolUse`, excepto las llamadas [`EndConversation`](/docs/es/tools-reference#endconversation-tool-behavior), que omiten ambas
26 26
27<div style={{maxWidth: "500px", margin: "0 auto"}}>27<div style={{maxWidth: "500px", margin: "0 auto"}}>
28 <Frame>28 <Frame>
29 <img src="https://mintcdn.com/claude-code/x7pO8l4XcvAXCoVc/images/hooks-lifecycle.svg?fit=max&auto=format&n=x7pO8l4XcvAXCoVc&q=85&s=81b9256c1bbe8832553485f5d9e9c746" alt="Diagrama del ciclo de vida de hooks que muestra Setup opcional alimentando a SessionStart, luego un bucle por turno que contiene UserPromptSubmit, UserPromptExpansion para slash commands, el bucle agentico anidado (PreToolUse, PermissionRequest, PostToolUse, PostToolUseFailure, PostToolBatch, SubagentStart/Stop, TaskCreated, TaskCompleted), y Stop o StopFailure, seguido de TeammateIdle, PreCompact, PostCompact y SessionEnd, con Elicitation y ElicitationResult anidados dentro de la ejecución de herramientas MCP, PermissionDenied como una rama lateral de PermissionRequest para denegaciones en modo automático, WorktreeCreate, WorktreeRemove, Notification, ConfigChange, InstructionsLoaded, CwdChanged y FileChanged como eventos asincronos independientes, y MessageDisplay como un evento de solo visualización que se ejecuta mientras el texto del mensaje del asistente se transmite" width="520" height="1336" data-path="images/hooks-lifecycle.svg" />29 <img src="https://mintcdn.com/claude-code/x7pO8l4XcvAXCoVc/images/hooks-lifecycle.svg?fit=max&auto=format&n=x7pO8l4XcvAXCoVc&q=85&s=81b9256c1bbe8832553485f5d9e9c746" className="dark:hidden" alt="Diagrama del ciclo de vida de hooks que muestra Setup opcional alimentando a SessionStart, luego un bucle por turno que contiene UserPromptSubmit, UserPromptExpansion para slash commands, el bucle agentico anidado (PreToolUse, PermissionRequest, PostToolUse, PostToolUseFailure, PostToolBatch, SubagentStart/Stop, TaskCreated, TaskCompleted), y Stop o StopFailure, seguido de TeammateIdle, PreCompact, PostCompact y SessionEnd, con Elicitation y ElicitationResult anidados dentro de la ejecución de herramientas MCP, PermissionDenied como una rama lateral de PermissionRequest para denegaciones en modo automático, WorktreeCreate, WorktreeRemove, Notification, ConfigChange, InstructionsLoaded, CwdChanged, FileChanged y DirectoryAdded como eventos asincronos independientes, PreModelSwitch como un evento secuencial independiente que se ejecuta antes de un cambio de modelo solicitado, PostModelSwitch como un evento asincrónico independiente que se ejecuta después de que cambia el modelo de la sesión, y MessageDisplay como un evento de solo visualización que se ejecuta mientras el texto del mensaje del asistente se transmite" width="520" height="1336" data-path="images/hooks-lifecycle.svg" />
30
31 <img src="https://mintcdn.com/claude-code/x7pO8l4XcvAXCoVc/images/hooks-lifecycle-dark.svg?fit=max&auto=format&n=x7pO8l4XcvAXCoVc&q=85&s=c9b3d88487335f58cce0b52e2f9e7531" className="hidden dark:block" alt="Diagrama del ciclo de vida de hooks que muestra Setup opcional alimentando a SessionStart, luego un bucle por turno que contiene UserPromptSubmit, UserPromptExpansion para slash commands, el bucle agentico anidado (PreToolUse, PermissionRequest, PostToolUse, PostToolUseFailure, PostToolBatch, SubagentStart/Stop, TaskCreated, TaskCompleted), y Stop o StopFailure, seguido de TeammateIdle, PreCompact, PostCompact y SessionEnd, con Elicitation y ElicitationResult anidados dentro de la ejecución de herramientas MCP, PermissionDenied como una rama lateral de PermissionRequest para denegaciones en modo automático, WorktreeCreate, WorktreeRemove, Notification, ConfigChange, InstructionsLoaded, CwdChanged, FileChanged y DirectoryAdded como eventos asincronos independientes, PreModelSwitch como un evento secuencial independiente que se ejecuta antes de un cambio de modelo solicitado, PostModelSwitch como un evento asincrónico independiente que se ejecuta después de que cambia el modelo de la sesión, y MessageDisplay como un evento de solo visualización que se ejecuta mientras el texto del mensaje del asistente se transmite" width="520" height="1336" data-path="images/hooks-lifecycle-dark.svg" />
30 </Frame>32 </Frame>
31</div>33</div>
32 34
33La tabla a continuación resume cuándo se activa cada evento. La sección [Hook events](#hook-events) documenta el esquema de entrada completo y las opciones de control de decisión para cada uno.35La tabla a continuación resume cuándo se activa cada evento. La sección [Hook events](#hook-events) documenta el esquema de entrada completo y las opciones de control de decisión para cada uno.
34 36
35| Event | When it fires |37| Evento | Cuándo se dispara |
36| :-------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |38| :-------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
37| `SessionStart` | When a session begins or resumes |39| `SessionStart` | Cuando una sesión comienza o se reanuda |
38| `Setup` | When you start Claude Code with `--init-only`, or with `--init` or `--maintenance` in `-p` mode. For one-time preparation in CI or scripts |40| `Setup` | Cuando inicia Claude Code con `--init-only`, o con `--init` o `--maintenance` en modo `-p`. Para preparación única en CI o scripts |
39| `UserPromptSubmit` | When you submit a prompt, before Claude processes it |41| `UserPromptSubmit` | Cuando envía un prompt, antes de que Claude lo procese |
40| `UserPromptExpansion` | When a user-typed command expands into a prompt, before it reaches Claude. Can block the expansion |42| `UserPromptExpansion` | Cuando un comando escrito por el usuario se expande en un prompt, antes de que llegue a Claude. Puede bloquear la expansión |
41| `PreToolUse` | Before a tool call executes. Can block it |43| `PreToolUse` | Antes de que se ejecute una llamada a herramienta. Puede bloquearlo |
42| `PermissionRequest` | When a tool call needs a permission decision |44| `PermissionRequest` | Cuando una llamada a herramienta necesita una decisión de permiso |
43| `PermissionDenied` | When auto mode denies a tool call, including denials without a classifier verdict. Use JSON `hookSpecificOutput.retry: true` to tell the model it may retry the denied tool call. Claude Code ignores `retry` when the classifier produced no verdict |45| `PermissionDenied` | Cuando el modo automático deniega una llamada a herramienta, incluidas las denegaciones sin un veredicto del clasificador. Use JSON `hookSpecificOutput.retry: true` para indicar al modelo que puede reintentar la llamada a herramienta denegada. Claude Code ignora `retry` cuando el clasificador no produjo veredicto |
44| `PostToolUse` | After a tool call succeeds |46| `PostToolUse` | Después de que una llamada a herramienta se ejecuta correctamente |
45| `PostToolUseFailure` | After a tool call fails |47| `PostToolUseFailure` | Después de que una llamada a herramienta falla |
46| `PostToolBatch` | After a full batch of parallel tool calls resolves, before the next model call |48| `PostToolBatch` | Después de que se resuelve un lote completo de llamadas a herramientas paralelas, antes de la siguiente llamada al modelo |
47| `Notification` | When Claude Code sends a notification |49| `Notification` | Cuando Claude Code envía una notificación |
48| `MessageDisplay` | While assistant message text is displayed |50| `MessageDisplay` | Mientras se muestra el texto del mensaje del asistente |
49| `SubagentStart` | When a subagent is spawned |51| `SubagentStart` | Cuando se genera un subagente |
50| `SubagentStop` | When a subagent finishes |52| `SubagentStop` | Cuando un subagente finaliza |
51| `TaskCreated` | When a task is being created via `TaskCreate` |53| `TaskCreated` | Cuando se está creando una tarea a través de `TaskCreate` |
52| `TaskCompleted` | When a task is being marked as completed |54| `TaskCompleted` | Cuando se marca una tarea como completada |
53| `Stop` | When Claude finishes responding |55| `Stop` | Cuando Claude termina de responder |
54| `StopFailure` | When the turn ends due to an API error |56| `StopFailure` | Cuando el turno termina debido a un error de API |
55| `TeammateIdle` | When an [agent team](/docs/en/agent-teams) teammate is about to go idle |57| `TeammateIdle` | Cuando un compañero de [equipo de agentes](/docs/es/agent-teams) está a punto de quedarse inactivo |
56| `InstructionsLoaded` | When a CLAUDE.md or `.claude/rules/*.md` file is loaded into context. Fires at session start and when files are lazily loaded during a session |58| `InstructionsLoaded` | Cuando se carga un archivo CLAUDE.md o `.claude/rules/*.md` en el contexto. Se dispara al inicio de la sesión y cuando los archivos se cargan de forma diferida durante una sesión |
57| `ConfigChange` | When a configuration file changes during a session |59| `ConfigChange` | Cuando un archivo de configuración cambia durante una sesión |
58| `CwdChanged` | When the working directory changes, for example when Claude executes a `cd` command. Useful for reactive environment management with tools like direnv |60| `CwdChanged` | Cuando el directorio de trabajo cambia, por ejemplo cuando Claude ejecuta un comando `cd`. Útil para la gestión reactiva del entorno con herramientas como direnv |
59| `DirectoryAdded` | When a working directory is added mid-session via `/add-dir` or the SDK `register_repo_root` control request |61| `DirectoryAdded` | Cuando se agrega un directorio de trabajo a mitad de sesión a través de `/add-dir` o la solicitud de control `register_repo_root` del SDK |
60| `FileChanged` | When a watched file changes on disk. The `matcher` field specifies which filenames to watch |62| `FileChanged` | Cuando un archivo observado cambia en el disco. El campo `matcher` especifica qué nombres de archivo observar |
61| `WorktreeCreate` | When a worktree is being created via `--worktree`, `isolation: "worktree"`, or for a background session. Replaces default git behavior |63| `WorktreeCreate` | Cuando se está creando un worktree a través de `--worktree`, `isolation: "worktree"`, o para una sesión en segundo plano. Reemplaza el comportamiento predeterminado de git |
62| `WorktreeRemove` | When a worktree is being removed at session exit, when a subagent finishes, or when you delete a background session |64| `WorktreeRemove` | Cuando se está eliminando un worktree al salir de la sesión, cuando un subagente finaliza, o cuando elimina una sesión en segundo plano |
63| `PreCompact` | Before context compaction |65| `PreCompact` | Antes de la compactación de contexto |
64| `PostCompact` | After context compaction completes |66| `PostCompact` | Después de que se completa la compactación de contexto |
65| `PreModelSwitch` | Before Claude Code applies a model switch that you or a client requested. Can block the switch |67| `PreModelSwitch` | Antes de que Claude Code aplique un cambio de modelo que usted o un cliente solicitó. Puede bloquear el cambio |
66| `PostModelSwitch` | After the session's model changes, including changes Claude Code makes on its own, such as restoring the model when you resume a session |68| `PostModelSwitch` | Después de que cambia el modelo de la sesión, incluidos los cambios que Claude Code realiza por su cuenta, como restaurar el modelo cuando reanuda una sesión |
67| `Elicitation` | When an MCP server requests user input during a tool call |69| `Elicitation` | Cuando un servidor MCP solicita entrada del usuario durante una llamada a herramienta |
68| `ElicitationResult` | After a user responds to an MCP elicitation, before the response is sent back to the server |70| `ElicitationResult` | Después de que un usuario responde a una solicitud de MCP, antes de que la respuesta se envíe de vuelta al servidor |
69| `SessionEnd` | When a session terminates |71| `SessionEnd` | Cuando una sesión termina |
70 72
71<h3 id="how-a-hook-resolves">73<h3 id="how-a-hook-resolves">
72 Cómo se resuelve un hook74 Cómo se resuelve un hook
73</h3>75</h3>
74 76
75Para ver cómo encajan estas piezas, considere este hook `PreToolUse` que bloquea comandos de shell destructivos. El `matcher` se reduce a llamadas a herramientas Bash y la condición `if` se reduce aún más a subcomandos Bash que coinciden con `rm *`, por lo que `block-rm.sh` solo se genera cuando ambos filtros coinciden:77Para ver cómo encajan el evento, el matcher y el controlador, considere este hook `PreToolUse` que bloquea comandos de shell destructivos.
76 78
77```json theme={null}79<Tabs>
78{80 <Tab title="macOS/Linux">
81 El `matcher` se reduce a llamadas a herramientas Bash y la condición `if` se reduce aún más a subcomandos Bash que coinciden con `rm *`, por lo que `block-rm.sh` solo se genera cuando ambos filtros coinciden:
82
83 ```json theme={null}
84 {
79 "hooks": {85 "hooks": {
80 "PreToolUse": [86 "PreToolUse": [
81 {87 {
91 }97 }
92 ]98 ]
93 }99 }
94}100 }
95```101 ```
96 102
97El script lee la entrada JSON desde stdin, extrae el comando y devuelve una `permissionDecision` de `"deny"` si contiene `rm -rf`:103 El script lee la entrada JSON desde stdin, extrae el comando y devuelve una `permissionDecision` de `"deny"` si contiene `rm -rf`. Guárdelo en `.claude/hooks/block-rm.sh` en su proyecto y hágalo ejecutable con `chmod +x .claude/hooks/block-rm.sh` para que Claude Code pueda ejecutarlo:
98 104
99```bash theme={null}105 ```bash theme={null}
100#!/bin/bash106 #!/bin/bash
101# .claude/hooks/block-rm.sh107 # .claude/hooks/block-rm.sh
102COMMAND=$(jq -r '.tool_input.command')108 COMMAND=$(jq -r '.tool_input.command')
103 109
104if echo "$COMMAND" | grep -q 'rm -rf'; then110 if echo "$COMMAND" | grep -q 'rm -rf'; then
105 jq -n '{111 jq -n '{
106 hookSpecificOutput: {112 hookSpecificOutput: {
107 hookEventName: "PreToolUse",113 hookEventName: "PreToolUse",
109 permissionDecisionReason: "Destructive command blocked by hook"115 permissionDecisionReason: "Destructive command blocked by hook"
110 }116 }
111 }'117 }'
112else118 else
113 exit 0 # no decision; normal permission flow applies119 exit 0 # no decision; normal permission flow applies
114fi120 fi
115```121 ```
122
123 Este script, como los otros ejemplos de Bash en esta página que analizan entrada JSON, utiliza `jq`, así que instale `jq` y asegúrese de que esté en su `PATH` antes de intentarlos.
124 </Tab>
125
126 <Tab title="Windows (PowerShell)">
127 El matcher `Bash|PowerShell` cubre la [herramienta PowerShell](#powershell) así como Bash. Una única regla `if` coincide solo con las llamadas de una herramienta, por lo que cada herramienta obtiene su propio controlador: el primero se reduce a subcomandos Bash que coinciden con `rm *`, el segundo a comandos PowerShell que coinciden con `Remove-Item *`. Ambos ejecutan el mismo script a través de `powershell.exe`:
128
129 ```json theme={null}
130 {
131 "hooks": {
132 "PreToolUse": [
133 {
134 "matcher": "Bash|PowerShell",
135 "hooks": [
136 {
137 "type": "command",
138 "if": "Bash(rm *)",
139 "command": "powershell.exe",
140 "args": [
141 "-NoProfile",
142 "-ExecutionPolicy",
143 "Bypass",
144 "-File",
145 "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.ps1"
146 ]
147 },
148 {
149 "type": "command",
150 "if": "PowerShell(Remove-Item *)",
151 "command": "powershell.exe",
152 "args": [
153 "-NoProfile",
154 "-ExecutionPolicy",
155 "Bypass",
156 "-File",
157 "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.ps1"
158 ]
159 }
160 ]
161 }
162 ]
163 }
164 }
165 ```
166
167 La bandera `-NoProfile` omite cargar su perfil de PowerShell para que el hook se inicie rápidamente, y `-ExecutionPolicy Bypass` permite que PowerShell ejecute el archivo de script local.
116 168
117Ahora suponga que Claude Code decide ejecutar `Bash "rm -rf /tmp/build"`. Esto es lo que sucede:169 El script lee la entrada JSON desde stdin, extrae el comando y devuelve una `permissionDecision` de `"deny"` si contiene `rm -rf` o `Remove-Item` seguido de `-Recurse`. Guárdelo en `.claude/hooks/block-rm.ps1` en su proyecto:
170
171 ```powershell theme={null}
172 # .claude/hooks/block-rm.ps1
173 $callInput = [Console]::In.ReadToEnd() | ConvertFrom-Json
174 $command = $callInput.tool_input.command
175
176 if ($command -match 'rm -rf|Remove-Item.*-Recurse') {
177 @{
178 hookSpecificOutput = @{
179 hookEventName = "PreToolUse"
180 permissionDecision = "deny"
181 permissionDecisionReason = "Destructive command blocked by hook"
182 }
183 } | ConvertTo-Json
184 } else {
185 exit 0 # no decision; normal permission flow applies
186 }
187 ```
188 </Tab>
189</Tabs>
190
191Ahora suponga que Claude Code decide ejecutar `Bash "rm -rf /tmp/build"` contra la configuración de macOS/Linux. Esto es lo que sucede:
118 192
119<Frame>193<Frame>
120 <img src="https://mintcdn.com/claude-code/ikqp3_70mqIahteV/images/hook-resolution.svg?fit=max&auto=format&n=ikqp3_70mqIahteV&q=85&s=be0bf3053550c26de5f54cd64674c197" alt="Diagrama de resolución de hooks: PreToolUse se activa, el matcher verifica la coincidencia de Bash, luego la condición if verifica la coincidencia de Bash(rm *). Si ambos coinciden, el comando del hook se ejecuta y devuelve permissionDecision deny, por lo que la llamada a la herramienta se bloquea y Claude Code continúa. Si alguna verificación no coincide, el hook se omite y la llamada a la herramienta se permite continuar." width="930" height="270" data-path="images/hook-resolution.svg" />194 <img src="https://mintcdn.com/claude-code/ikqp3_70mqIahteV/images/hook-resolution.svg?fit=max&auto=format&n=ikqp3_70mqIahteV&q=85&s=be0bf3053550c26de5f54cd64674c197" className="dark:hidden" alt="Diagrama de resolución de hooks: PreToolUse se activa, el matcher verifica la coincidencia de Bash, luego la condición if verifica la coincidencia de Bash(rm *). Si ambos coinciden, el comando del hook se ejecuta y devuelve permissionDecision deny, por lo que la llamada a la herramienta se bloquea y Claude Code continúa. Si alguna verificación no coincide, el hook se omite y la llamada a la herramienta se permite continuar." width="930" height="270" data-path="images/hook-resolution.svg" />
195
196 <img src="https://mintcdn.com/claude-code/_xqph1dUOslCOwsj/images/hook-resolution-dark.svg?fit=max&auto=format&n=_xqph1dUOslCOwsj&q=85&s=e80af91f8507cee6bd51ac3c2dd92f63" className="hidden dark:block" alt="Diagrama de resolución de hooks: PreToolUse se activa, el matcher verifica la coincidencia de Bash, luego la condición if verifica la coincidencia de Bash(rm *). Si ambos coinciden, el comando del hook se ejecuta y devuelve permissionDecision deny, por lo que la llamada a la herramienta se bloquea y Claude Code continúa. Si alguna verificación no coincide, el hook se omite y la llamada a la herramienta se permite continuar." width="930" height="270" data-path="images/hook-resolution-dark.svg" />
121</Frame>197</Frame>
122 198
123<Steps>199<Steps>
166 242
167Los hooks se definen en archivos de configuración JSON. La configuración tiene tres niveles de anidamiento:243Los hooks se definen en archivos de configuración JSON. La configuración tiene tres niveles de anidamiento:
168 244
1691. Elija un [hook event](#hook-events) al que responder, como `PreToolUse` o `Stop`2451. Elige un [evento de hook](#hook-events) al que responder, como `PreToolUse` o `Stop`
1702. Agregue un [matcher group](#matcher-patterns) para filtrar cuándo se activa, como "solo para la herramienta Bash"2462. Añade un [grupo de matcher](#matcher-patterns) para filtrar cuándo se activa, como "solo para la herramienta Bash"
1713. Defina uno o más [hook handlers](#hook-handler-fields) para ejecutar cuando coincida2473. Define uno o más [manejadores de hook](#hook-handler-fields) para ejecutar cuando coincida
172 248
173Consulte [Cómo se resuelve un hook](#how-a-hook-resolves) arriba para un recorrido completo con un ejemplo anotado.249Consulta [Cómo se resuelve un hook](#how-a-hook-resolves) arriba para un recorrido completo con un ejemplo anotado.
174 250
175<Note>251<Note>
176 Esta página utiliza términos específicos para cada nivel: **hook event** para el punto del ciclo de vida, **matcher group** para el filtro y **hook handler** para el comando de shell, punto final HTTP, herramienta MCP, prompt o agente que se ejecuta. "Hook" por sí solo se refiere a la característica general.252 Esta página utiliza términos específicos para cada nivel: **evento de hook** para el punto del ciclo de vida, **grupo de matcher** para el filtro, y **manejador de hook** para el comando de shell, punto final HTTP, herramienta MCP, prompt o agente que se ejecuta. "Hook" por sí solo se refiere a la característica general.
177</Note>253</Note>
178 254
179<h3 id="hook-locations">255<h3 id="hook-locations">
180 Ubicaciones de hooks256 Ubicaciones de hooks
181</h3>257</h3>
182 258
183Dónde defina un hook determina su alcance:259Dónde definas un hook determina su alcance:
184 260
185| Ubicación | Alcance | Compartible |261| Ubicación | Alcance | Compartible |
186| :-------------------------------------------------------- | :--------------------------------- | :---------------------------------------------- |262| :--------------------------------------- | :---------------------------------------------------------------------------------------------------------------------- | :--------------------------------------------------------------------- |
187| `~/.claude/settings.json` | Todos sus proyectos | No, local en su máquina |263| `~/.claude/settings.json` | Todos tus proyectos | No, local en tu máquina |
188| `.claude/settings.json` | Proyecto único | Sí, puede ser confirmado en el repositorio |264| `.claude/settings.json` | Proyecto único | Sí, puede confirmarse en el repositorio |
189| `.claude/settings.local.json` | Proyecto único | No, ignorado por git cuando Claude Code lo crea |265| `.claude/settings.local.json` | Proyecto único | No, ignorado por git cuando Claude Code guarda una configuración en él |
190| Configuración de política administrada | Toda la organización | Sí, controlado por administrador |266| Configuración de política administrada | Toda la organización | Sí, controlado por administrador |
191| [Plugin](/docs/es/plugins) `hooks/hooks.json` | Cuando el plugin está habilitado | Sí, incluido con el plugin |267| [Plugin](/docs/es/plugins) `hooks/hooks.json` | Cuando el plugin está habilitado | Sí, incluido con el plugin |
192| [Skill](/docs/es/skills) o [agent](/docs/es/sub-agents) frontmatter | Mientras el componente está activo | Sí, definido en el archivo del componente |268| [Skill](/docs/es/skills) frontmatter | El resto de la sesión una vez que se invoca la skill. Consulta [Hooks en skills y agentes](#hooks-in-skills-and-agents) | Sí, definido en el archivo de skill |
269| [Subagente](/docs/es/sub-agents) frontmatter | Mientras ese subagente se está ejecutando | Sí, definido en el archivo del subagente |
270
271Las [sesiones en la nube](/docs/es/claude-code-on-the-web) no leen tu `~/.claude/settings.json` local; los hooks allí provienen del repositorio, lo que significa su `.claude/settings.json` en una sesión con un repositorio y los plugins que declara en cualquier sesión, y de la configuración administrada por servidor de tu organización. En un [entorno autohospedado](/docs/es/self-hosted-environments-configuration#permissions-and-tool-approval), Claude Code también ejecuta los hooks que el operador sembró desde `~/.claude/` del host del ejecutor, y ejecuta los hooks en el archivo de configuración administrada de la imagen del ejecutor cuando ese archivo está entre las [fuentes administradas que Claude Code aplica](/docs/es/managed-settings#how-claude-code-combines-managed-sources), lo que por defecto significa solo cuando ni la configuración administrada por servidor ni una política de Claude Code entregada por MDM suministran el nivel administrado. Consulta [qué se transfiere de tu configuración](/docs/es/cloud-environments#what-carries-over-from-your-setup) para saber qué archivos llegan a una sesión en la nube.
193 272
194Para obtener detalles sobre la resolución de archivos de configuración, consulte [settings](/docs/es/settings).273Para obtener detalles sobre la resolución de archivos de configuración, consulta [configuración](/docs/es/settings).
195 274
196Los administradores empresariales pueden usar `allowManagedHooksOnly` para bloquear hooks de usuario, proyecto y plugin. Los hooks de plugins habilitados forzosamente en la configuración administrada `enabledPlugins` están exentos, por lo que los administradores pueden distribuir hooks verificados a través de un mercado de la organización. Consulte [Hook configuration](/docs/es/settings#hook-configuration).275Los hooks de archivos de configuración, configuración de política administrada y plugins también se ejecutan dentro de [subagentes](/docs/es/sub-agents). Cuando un subagente llama a una herramienta, eventos de herramienta como `PreToolUse` y `PostToolUse` activan los mismos hooks configurados que en la conversación principal, y la entrada lleva los campos de entrada comunes `agent_id` y `agent_type` [](#common-input-fields) que identifican al subagente.
276
277Los administradores empresariales pueden usar `allowManagedHooksOnly` para restringir qué hooks se ejecutan:
278
279* Tus hooks de usuario, proyecto, local y plugin están bloqueados. Los hooks de plugins forzados a habilitarse en la configuración administrada `enabledPlugins` están exentos
280* Claude Code también reduce tu configuración [`statusLine`](/docs/es/statusline), [`fileSuggestion`](/docs/es/settings-reference#filesuggestion) y [`subagentStatusLine`](/docs/es/statusline#subagent-status-lines) a la configuración administrada
281* Claude Code también deshabilita plugins con una [fuente `command`](/docs/es/plugin-marketplaces#command-sources), incluidos los plugins forzados a habilitarse en la configuración administrada `enabledPlugins`, a menos que [`disableCommandPluginSources`](/docs/es/settings-reference#disablecommandpluginsources) esté explícitamente establecido en `false`. Las fuentes `command` requieren Claude Code v2.1.229 o posterior
282* Claude Code también bloquea los comandos [`headersHelper`](/docs/es/plugin-marketplaces#authenticate-archive-downloads) del marketplace a menos que [`disableCommandPluginSources`](/docs/es/settings-reference#disablecommandpluginsources) esté explícitamente establecido en `false`, excepto para un marketplace que la propia configuración administrada declare
283
284Consulta [qué se ejecuta bajo `allowManagedHooksOnly`](/docs/es/settings-reference#what-runs-under-allowmanagedhooksonly).
285
286Las entradas de hook se fusionan entre niveles de configuración en lugar de reemplazarse entre sí: la configuración de usuario, proyecto y local añaden sus propios hooks sin eliminar los administrados, y la configuración [`disableAllHooks`](#disable-or-remove-hooks) no puede deshabilitar hooks administrados desde fuera de la configuración administrada.
287
288Las [listas de permitidos de hooks HTTP](/docs/es/settings-reference#hook-and-skill-settings) se aplican a hooks de todas las fuentes, incluida la configuración de política administrada:
289
290* `allowedHttpHookUrls`: cuando se define en cualquier nivel de configuración, Claude Code ejecuta un manejador de hook HTTP solo si su URL coincide con la lista de permitidos fusionada
291* `httpHookAllowedEnvVars`: cuando se define, Claude Code interpola solo las variables de entorno en esa lista en los encabezados de hook
197 292
198<h3 id="matcher-patterns">293<h3 id="matcher-patterns">
199 Patrones de matcher294 Patrones de matcher
200</h3>295</h3>
201 296
202El campo `matcher` filtra cuándo se activan los hooks. Cómo se evalúa un matcher depende de los caracteres que contenga:297El campo `matcher` filtra cuándo se activan los hooks. Cómo se evalúa un matcher depende de los caracteres que contiene:
203 298
204| Valor del matcher | Evaluado como | Ejemplo |299| Valor de matcher | Evaluado como | Ejemplo |
205| :--------------------------------------------------- | :------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |300| :--------------------------------------------------- | :------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
206| `"*"`, `""` u omitido | Coincidir todo | se activa en cada ocurrencia del evento |301| `"*"`, `""` u omitido | Coincidir con todo | se activa en cada ocurrencia del evento |
207| Solo letras, dígitos, `_`, `-`, espacios, `,` y `\|` | Cadena exacta, o lista de cadenas exactas separadas por `\|` o `,` con espacios en blanco opcionales alrededor | `Bash` coincide solo con la herramienta Bash; `Edit\|Write` y `Edit, Write` cada uno coincide con cualquiera de las herramientas exactamente; `code-reviewer` coincide solo con ese tipo de agente |302| Solo letras, dígitos, `_`, `-`, espacios, `,` y `\|` | Cadena exacta, o lista de cadenas exactas separadas por `\|` o `,` con espacios en blanco opcionales alrededor | `Bash` coincide solo con la herramienta Bash; `Edit\|Write` y `Edit, Write` cada una coincide con cualquiera de las herramientas exactamente; `code-reviewer` coincide solo con ese tipo de agente |
208| Contiene cualquier otro carácter | Expresión regular de JavaScript, sin anclar | `^Notebook` coincide con cualquier herramienta cuyo nombre comience con Notebook; `mcp__memory__.*` coincide con cada herramienta del servidor `memory` |303| Contiene cualquier otro carácter | Expresión regular de JavaScript, sin anclar | `^Notebook` coincide con cualquier herramienta cuyo nombre comienza con `Notebook`; `mcp__memory__.*` coincide con cada herramienta del servidor `memory` |
209 304
210Un matcher en la ruta de expresión regular se prueba con `RegExp.prototype.test` de JavaScript, que tiene éxito en una coincidencia en cualquier lugar del valor. `Edit.*` coincide tanto con `Edit` como con `NotebookEdit`; envuelva el patrón en `^` y `$`, como en `^Edit$`, cuando necesite una coincidencia de cadena completa.305Un matcher en la ruta de expresión regular se prueba con `RegExp.prototype.test` de JavaScript, que tiene éxito en una coincidencia en cualquier lugar del valor. `Edit.*` coincide tanto con `Edit` como con `NotebookEdit`; envuelve el patrón en `^` y `$`, como en `^Edit$`, cuando necesites una coincidencia de cadena completa.
211 306
212Los separadores de coma y la tolerancia de espacios en blanco circundantes requieren Claude Code v2.1.191 o posterior.307Los separadores de coma y la tolerancia de espacios en blanco circundantes requieren Claude Code v2.1.191 o posterior.
213 308
214Los guiones en el conjunto de coincidencia exacta requieren Claude Code v2.1.195 o posterior. En versiones anteriores, un nombre con guiones como `code-reviewer` se evalúa como una expresión regular sin anclar, por lo que también se activa para `senior-code-reviewer`; anclelo como `^code-reviewer$` en esas versiones para coincidir solo con ese nombre.309Los guiones en el conjunto de coincidencia exacta requieren Claude Code v2.1.195 o posterior. En versiones anteriores, un nombre con guiones como `code-reviewer` se evalúa como una expresión regular sin anclar, por lo que también se activa para `senior-code-reviewer`; anclalo como `^code-reviewer$` en esas versiones para coincidir solo con ese nombre.
215 310
216`FileChanged` y `StopFailure` utilizan un conjunto de coincidencia exacta más estrecho de solo letras, dígitos, `_` y `|`. Un guión, espacio o coma en un matcher para esos dos eventos lo mantiene en la ruta de expresión regular, y solo `|` separa alternativas. Todos los demás eventos con soporte de matcher en la tabla que sigue aceptan `|` o `,`.311`FileChanged` y `StopFailure` utilizan un conjunto de coincidencia exacta más estrecho de solo letras, dígitos, `_` y `|`. Un guión, espacio o coma en un matcher para esos dos eventos lo mantiene en la ruta de expresión regular, y solo `|` separa alternativas. Todos los demás eventos con soporte de matcher en la tabla que sigue aceptan `|` o `,`.
217 312
218El evento `FileChanged` no sigue estas reglas al construir su lista de vigilancia. Consulte [FileChanged](#filechanged).313El evento `FileChanged` no sigue estas reglas al construir su lista de vigilancia. Consulta [FileChanged](#filechanged).
219 314
220Cada tipo de evento coincide en un campo diferente:315Cada tipo de evento coincide en un campo diferente:
221 316
222| Evento | En qué filtra el matcher | Valores de matcher de ejemplo |317| Evento | Qué filtra el matcher | Valores de matcher de ejemplo |
223| :------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |318| :------------------------------------------------------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
224| `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, `PermissionDenied` | nombre de la herramienta | `Bash`, `Edit\|Write`, `mcp__.*` |319| `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, `PermissionDenied` | nombre de la herramienta | `Bash`, `Edit\|Write`, `mcp__.*` |
225| `SessionStart` | cómo comenzó la sesión | `startup`, `resume`, `clear`, `compact` |320| `SessionStart` | cómo comenzó la sesión | `startup`, `resume`, `clear`, `compact`, `fork` |
226| `Setup` | qué bandera CLI desencadenó la configuración | `init`, `maintenance` |321| `Setup` | qué bandera CLI activó la configuración | `init`, `maintenance` |
227| `SessionEnd` | por qué terminó la sesión | `clear`, `resume`, `logout`, `prompt_input_exit`, `bypass_permissions_disabled`, `other` |322| `SessionEnd` | por qué terminó la sesión | `clear`, `resume`, `logout`, `prompt_input_exit`, `other` |
228| `Notification` | tipo de notificación | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog`, `elicitation_complete`, `elicitation_response`, `agent_needs_input`, `agent_completed` |323| `Notification` | tipo de notificación | `permission_prompt`, `idle_prompt`, `auth_success`, `elicitation_dialog`, `elicitation_url_dialog`, `elicitation_complete`, `elicitation_response`, `agent_needs_input`, `agent_completed`, `quota_auto_resume_fired`, `quota_auto_resume_stale`, `quota_auto_resume_disabled` |
229| `SubagentStart` | tipo de agente | `general-purpose`, `Explore`, `Plan`, nombres de agentes personalizados, o nombres con alcance de plugin como `^my-plugin:reviewer$` |324| `SubagentStart` | tipo de agente | `general-purpose`, `Explore`, `Plan`, nombres de agentes personalizados, o nombres con alcance de plugin como `^my-plugin:reviewer$` |
230| `PreCompact`, `PostCompact` | qué desencadenó la compactación | `manual`, `auto` |325| `PreCompact`, `PostCompact` | qué activó la compactación | `manual`, `auto` |
326| `PreModelSwitch`, `PostModelSwitch` | nombre canónico del modelo al que cambia la sesión, como se describe en [PreModelSwitch](#premodelswitch) | `claude-opus-5`, `claude-opus-4-6\|claude-opus-5`, `.*opus.*` |
231| `SubagentStop` | tipo de agente | los mismos valores que `SubagentStart` |327| `SubagentStop` | tipo de agente | los mismos valores que `SubagentStart` |
232| `ConfigChange` | fuente de configuración | `user_settings`, `project_settings`, `local_settings`, `policy_settings`, `skills` |328| `ConfigChange` | fuente de configuración | `user_settings`, `project_settings`, `local_settings`, `policy_settings`, `skills` |
233| `CwdChanged` | sin soporte de matcher | siempre se activa en cada cambio de directorio |329| `CwdChanged` | sin soporte de matcher | siempre se activa en cada ocurrencia |
234| `FileChanged` | nombres de archivo literales a vigilar (consulte [FileChanged](#filechanged)) | `.envrc\|.env` |330| `DirectoryAdded` | cómo se añadió el directorio | `slash_command`, `register_repo_root` |
235| `StopFailure` | tipo de error | `rate_limit`, `overloaded`, `authentication_failed`, `oauth_org_not_allowed`, `billing_error`, `invalid_request`, `model_not_found`, `server_error`, `max_output_tokens`, `unknown` |331| `FileChanged` | nombres de archivo literales a vigilar (consulta [FileChanged](#filechanged)) | `.envrc\|.env` |
332| `StopFailure` | tipo de error | `rate_limit`, `overloaded`, `authentication_failed`, `oauth_org_not_allowed`, `account_on_hold`, `billing_error`, `invalid_request`, `model_not_found`, `server_error`, `max_output_tokens`, `cloud_credential_error`, `unknown` |
236| `InstructionsLoaded` | razón de carga | `session_start`, `nested_traversal`, `path_glob_match`, `include`, `compact` |333| `InstructionsLoaded` | razón de carga | `session_start`, `nested_traversal`, `path_glob_match`, `include`, `compact` |
237| `UserPromptExpansion` | nombre del comando | sus nombres de skill o comando |334| `UserPromptExpansion` | nombre del comando | tus nombres de skill o comando |
238| `Elicitation` | nombre del servidor MCP | sus nombres de servidor MCP configurados |335| `Elicitation` | nombre del servidor MCP | tus nombres de servidor MCP configurados |
239| `ElicitationResult` | nombre del servidor MCP | los mismos valores que `Elicitation` |336| `ElicitationResult` | nombre del servidor MCP | los mismos valores que `Elicitation` |
240| `UserPromptSubmit`, `PostToolBatch`, `Stop`, `TeammateIdle`, `TaskCreated`, `TaskCompleted`, `WorktreeCreate`, `WorktreeRemove`, `MessageDisplay` | sin soporte de matcher | siempre se activa en cada ocurrencia |337| `UserPromptSubmit`, `PostToolBatch`, `Stop`, `TeammateIdle`, `TaskCreated`, `TaskCompleted`, `WorktreeCreate`, `WorktreeRemove`, `MessageDisplay` | sin soporte de matcher | siempre se activa en cada ocurrencia |
241 338
242El matcher se ejecuta contra un campo de la [entrada JSON](#hook-input-and-output) que Claude Code envía a su hook en stdin. Para eventos de herramientas, ese campo es `tool_name`. Cada sección [hook event](#hook-events) enumera el conjunto completo de valores de matcher y el esquema de entrada para ese evento.339Hacer coincidir `StopFailure` en `cloud_credential_error` requiere Claude Code v2.1.267 o posterior, la primera versión que reporta fallos de carga de credenciales bajo ese valor en lugar de `server_error` o `unknown`.
340
341Para la mayoría de eventos, Claude Code evalúa el matcher contra un campo de la [entrada JSON](#hook-input-and-output) que envía a tu hook en stdin. Para eventos de herramienta, ese campo es `tool_name`. Para `PreModelSwitch` y `PostModelSwitch`, Claude Code evalúa el matcher contra el nombre canónico que deriva de `to_model`, como se describe en [PreModelSwitch](#premodelswitch). Cada sección de [evento de hook](#hook-events) lista el conjunto completo de valores de matcher y el esquema de entrada para ese evento.
243 342
244Este ejemplo ejecuta un script de linting solo cuando Claude escribe o edita un archivo:343Este ejemplo ejecuta un script de linting solo cuando Claude escribe o edita un archivo:
245 344
261}360}
262```361```
263 362
264`UserPromptSubmit`, `PostToolBatch`, `Stop`, `TeammateIdle`, `TaskCreated`, `TaskCompleted`, `WorktreeCreate`, `WorktreeRemove`, `MessageDisplay` y `CwdChanged` no admiten matchers y siempre se activan en cada ocurrencia. Si agrega un campo `matcher` a estos eventos, se ignora silenciosamente.363Si añades un campo `matcher` a un evento sin soporte de matcher, se ignora silenciosamente.
265 364
266Para eventos de herramientas, puede filtrar más estrechamente estableciendo el campo [`if`](#common-fields) en controladores de hooks individuales. `if` utiliza [sintaxis de regla de permiso](/docs/es/permissions) para coincidir con el nombre de la herramienta y los argumentos juntos, por lo que `"Bash(git *)"` se ejecuta cuando cualquier subcomando de la entrada de Bash coincide con `git *` y `"Edit(*.ts)"` se ejecuta solo para archivos TypeScript.365Para eventos de herramienta, puedes filtrar más estrictamente estableciendo el campo [`if`](#common-fields) en manejadores de hook individuales. `if` utiliza [sintaxis de regla de permisos](/docs/es/permissions) para coincidir contra el nombre de la herramienta y los argumentos juntos, por lo que `"Bash(git *)"` se ejecuta cuando cualquier subcomando de la entrada de Bash coincide con `git *` y `"Edit(*.ts)"` se ejecuta solo para archivos TypeScript.
267 366
268<h4 id="match-mcp-tools">367<h4 id="match-mcp-tools">
269 Coincidir herramientas MCP368 Coincidir herramientas MCP
270</h4>369</h4>
271 370
272Las herramientas del servidor [MCP](/docs/es/mcp) aparecen como herramientas normales en eventos de herramientas (`PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, `PermissionDenied`), por lo que puede hacerlas coincidir de la misma manera que cualquier otro nombre de herramienta.371Las herramientas del servidor [MCP](/docs/es/mcp) aparecen como herramientas regulares en eventos de herramienta (`PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, `PermissionDenied`), por lo que puedes hacerlas coincidir de la misma manera que cualquier otro nombre de herramienta.
273 372
274Las herramientas MCP siguen el patrón de nomenclatura `mcp__<server>__<tool>`, por ejemplo:373Las herramientas MCP siguen el patrón de nomenclatura `mcp__<server>__<tool>`, por ejemplo:
275 374
277* `mcp__filesystem__read_file`: herramienta leer archivo del servidor Filesystem376* `mcp__filesystem__read_file`: herramienta leer archivo del servidor Filesystem
278* `mcp__github__search_repositories`: herramienta de búsqueda del servidor GitHub377* `mcp__github__search_repositories`: herramienta de búsqueda del servidor GitHub
279 378
280Para coincidir con cada herramienta de un servidor, agregue `.*` al prefijo del servidor. El `.*` es requerido: un matcher como `mcp__memory` o `mcp__brave-search` contiene solo caracteres de coincidencia exacta, por lo que se compara como una cadena exacta y no coincide con ninguna herramienta.379Para coincidir con cada herramienta de un servidor, añade `.*` al prefijo del servidor. El `.*` es obligatorio: un matcher como `mcp__memory` o `mcp__brave-search` contiene solo caracteres de coincidencia exacta, por lo que se compara como una cadena exacta y no coincide con ninguna herramienta.
281 380
282* `mcp__memory__.*` coincide con todas las herramientas del servidor `memory`381* `mcp__memory__.*` coincide con todas las herramientas del servidor `memory`
283* `mcp__brave-search__.*` coincide con todas las herramientas de un servidor cuyo nombre contiene un guión382* `mcp__brave-search__.*` coincide con todas las herramientas de un servidor cuyo nombre contiene un guión
284* `mcp__.*__write.*` coincide con cualquier herramienta cuyo nombre comience con `write` de cualquier servidor383* `mcp__.*__write.*` coincide con cualquier herramienta cuyo nombre comienza con `write` de cualquier servidor
285 384
286Los guiones en el conjunto de coincidencia exacta requieren Claude Code v2.1.195 o posterior. En versiones anteriores, un prefijo con guiones simple como `mcp__brave-search` se evalúa como una expresión regular sin anclar y coincide con cada herramienta de ese servidor. La forma `mcp__brave-search__.*` funciona en cada versión.385Los guiones en el conjunto de coincidencia exacta requieren Claude Code v2.1.195 o posterior. En versiones anteriores, un prefijo con guiones desnudo como `mcp__brave-search` se evalúa como una expresión regular sin anclar y coincide con cada herramienta de ese servidor. La forma `mcp__brave-search__.*` funciona en cada versión.
287 386
288Las herramientas de un [servidor MCP incluido en plugin](/docs/es/mcp#plugin-provided-mcp-servers) utilizan un segmento de servidor con alcance que incluye el nombre del plugin: `mcp__plugin_<plugin-name>_<server-name>__<tool>`. Un matcher escrito contra la clave del servidor simple nunca se activa para estas herramientas. Para un plugin llamado `my-plugin` que incluye un servidor bajo la clave `db`, una herramienta `query` aparece como `mcp__plugin_my-plugin_db__query`, por lo que el matcher para cada herramienta de ese servidor es `mcp__plugin_my-plugin_db__.*`. Use el mismo nombre de herramienta con alcance en el campo [`if`](#common-fields) de un controlador. Consulte [Plugin-provided MCP servers](/docs/es/mcp#plugin-provided-mcp-servers) para ver cómo se construye el nombre con alcance.387Las herramientas de un [servidor MCP incluido en plugin](/docs/es/mcp#plugin-provided-mcp-servers) utilizan un segmento de servidor con alcance que incluye el nombre del plugin: `mcp__plugin_<plugin-name>_<server-name>__<tool>`. Un matcher escrito contra la clave del servidor desnuda nunca se activa para estas herramientas. Para un plugin llamado `my-plugin` que incluye un servidor bajo la clave `db`, una herramienta `query` aparece como `mcp__plugin_my-plugin_db__query`, por lo que el matcher para cada herramienta de ese servidor es `mcp__plugin_my-plugin_db__.*`. Utiliza el mismo nombre de herramienta con alcance en el campo [`if`](#common-fields) de un manejador. Consulta [Servidores MCP incluidos en plugin](/docs/es/mcp#plugin-provided-mcp-servers) para saber cómo se construye el nombre con alcance.
289 388
290Este ejemplo registra todas las operaciones del servidor de memoria y valida operaciones de escritura de cualquier servidor MCP:389Este ejemplo registra todas las operaciones del servidor de memoria y valida operaciones de escritura de cualquier servidor MCP:
291 390
317```416```
318 417
319<h3 id="hook-handler-fields">418<h3 id="hook-handler-fields">
320 Campos del controlador de hooks419 Campos de manejador de hook
321</h3>420</h3>
322 421
323Cada objeto en el array `hooks` interno es un controlador de hook: el comando de shell, punto final HTTP, herramienta MCP, prompt de LLM o agente que se ejecuta cuando el matcher coincide. Hay cinco tipos:422Cada objeto en el array `hooks` interno es un manejador de hook: el comando de shell, punto final HTTP, herramienta MCP, prompt LLM o agente que se ejecuta cuando el matcher coincide. Hay cinco tipos:
324 423
325* **[Command hooks](#command-hook-fields)** (`type: "command"`): ejecutan un comando de shell. Su script recibe la [entrada JSON](#hook-input-and-output) del evento en stdin y comunica resultados a través de códigos de salida y stdout.424* **[Hooks de comando](#command-hook-fields)** (`type: "command"`): ejecutan un comando de shell. Tu script recibe la [entrada JSON](#hook-input-and-output) del evento en stdin y comunica resultados de vuelta a través de códigos de salida y stdout.
326* **[HTTP hooks](#http-hook-fields)** (`type: "http"`): envían la entrada JSON del evento como una solicitud HTTP POST a una URL. El punto final comunica resultados a través del cuerpo de la respuesta usando el mismo [formato de salida JSON](#json-output) que los hooks de comando.425* **[Hooks HTTP](#http-hook-fields)** (`type: "http"`): envían la entrada JSON del evento como una solicitud HTTP POST a una URL. El punto final comunica resultados de vuelta a través del cuerpo de respuesta utilizando el mismo [formato de salida JSON](#json-output) que los hooks de comando.
327* **[MCP tool hooks](#mcp-tool-hook-fields)** (`type: "mcp_tool"`): llaman a una herramienta en un servidor [MCP](/docs/es/mcp) ya conectado. La salida de texto de la herramienta se trata como stdout de hook de comando.426* **[Hooks de herramienta MCP](#mcp-tool-hook-fields)** (`type: "mcp_tool"`): llaman a una herramienta en un [servidor MCP](/docs/es/mcp) ya conectado. La salida de texto de la herramienta se trata como stdout de hook de comando.
328* **[Prompt hooks](#prompt-and-agent-hook-fields)** (`type: "prompt"`): envían un prompt a un modelo Claude para evaluación de un solo turno. El modelo devuelve una decisión sí/no como JSON. Consulte [Prompt-based hooks](#prompt-based-hooks).427* **[Hooks de prompt](#prompt-and-agent-hook-fields)** (`type: "prompt"`): envían un prompt a un modelo Claude para evaluación de un solo turno. El modelo devuelve su decisión como JSON. Consulta [Hooks basados en prompt](#prompt-based-hooks).
329* **[Agent hooks](#prompt-and-agent-hook-fields)** (`type: "agent"`): generan un subagente que puede usar herramientas como Read, Grep y Glob para verificar condiciones antes de devolver una decisión. Los hooks de agente son experimentales y pueden cambiar. Consulte [Agent-based hooks](#agent-based-hooks).428* **[Hooks de agente](#prompt-and-agent-hook-fields)** (`type: "agent"`): generan un subagente que puede usar herramientas como Read, Grep y Glob para verificar condiciones antes de devolver una decisión. Los hooks de agente son experimentales y pueden cambiar. Consulta [Hooks basados en agente](#agent-based-hooks).
330 429
331Todos los hooks coincidentes se ejecutan en paralelo, y los controladores idénticos se deduplicarán automáticamente. Los hooks de comando se deduplicarán por cadena de comando y `args`, y los hooks HTTP se deduplicarán por URL.430Todos los hooks coincidentes se ejecutan en paralelo. Si defines el mismo manejador en más de un archivo de configuración, se ejecuta una vez. Una copia del mismo manejador de un plugin o skill se mantiene separada.
332 431
333Los controladores se ejecutan en el directorio actual con el entorno de Claude Code. La variable de entorno `$CLAUDE_CODE_REMOTE` se establece en `"true"` en entornos web remotos y no se establece en la CLI local. A partir de v2.1.199, [`$CLAUDE_CODE_BRIDGE_SESSION_ID`](/docs/es/env-vars) se establece en el ID de sesión de [Remote Control](/docs/es/remote-control) mientras la sesión local tiene una conexión Remote Control activa.432Los manejadores se ejecutan en el directorio actual con el entorno de Claude Code. Si el directorio actual ya no existe, por ejemplo un worktree o directorio temporal que otro shell eliminó a mitad de sesión, Claude Code ejecuta hooks de comando desde el primero de estos que aún existe: el directorio en el que comenzó la sesión, la raíz del proyecto, tu directorio de inicio o el directorio temporal del sistema. Claude Code registra una advertencia nombrando el directorio de respaldo en el [registro de depuración](#debug-hooks).
433
434La variable de entorno `$CLAUDE_CODE_REMOTE` es `"true"` en entornos web remotos y no está establecida en la CLI local. Claude Code v2.1.199 y posterior establece [`$CLAUDE_CODE_BRIDGE_SESSION_ID`](/docs/es/env-vars) en el ID de sesión de [Control Remoto](/docs/es/remote-control) mientras la sesión local tiene una conexión activa de Control Remoto.
334 435
335<h4 id="common-fields">436<h4 id="common-fields">
336 Campos comunes437 Campos comunes
337</h4>438</h4>
338 439
339Estos campos se aplican a todos los tipos de hooks:440Estos campos se aplican a todos los tipos de hook:
340 441
341| Campo | Requerido | Descripción |442| Campo | Requerido | Descripción |
342| :-------------- | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |443| :-------------- | :-------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
343| `type` | sí | `"command"`, `"http"`, `"mcp_tool"`, `"prompt"` o `"agent"` |444| `type` | sí | `"command"`, `"http"`, `"mcp_tool"`, `"prompt"` o `"agent"` |
344| `if` | no | Sintaxis de regla de permiso para filtrar cuándo se ejecuta este hook, como `"Bash(git *)"` o `"Edit(*.ts)"`. El hook solo se genera si la llamada a herramienta coincide con el patrón. Consulte la tabla [Bash matching](#bash-if-matching) a continuación para ver cómo los patrones de Bash se evalúan contra subcomandos, `$()` y backticks. Solo se evalúa en eventos de herramientas: `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest` y `PermissionDenied`. En otros eventos, un hook con `if` establecido nunca se ejecuta. Utiliza la misma sintaxis que [reglas de permiso](/docs/es/permissions) |445| `if` | no | Sintaxis de regla de permisos para filtrar cuándo se ejecuta este hook, como `"Bash(git *)"` o `"Edit(*.ts)"`. El comando de hook solo se ejecuta si la llamada de herramienta coincide con el patrón. Consulta la tabla [Bash matching](#bash-if-matching) a continuación para saber cómo los patrones de Bash se evalúan contra subcomandos, `$()` y backticks. Solo se evalúa en eventos de herramienta: `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest` y `PermissionDenied`. En otros eventos, un hook con `if` establecido nunca se ejecuta. Utiliza la misma sintaxis que [reglas de permisos](/docs/es/permissions) |
345| `timeout` | no | Segundos antes de cancelar. Valores predeterminados: 600 para `command`, `http` y `mcp_tool`; 30 para `prompt`; 60 para `agent`. [`UserPromptSubmit`](#userpromptsubmit) reduce el valor predeterminado de `command`, `http` y `mcp_tool` a 30, y [`MessageDisplay`](#messagedisplay) lo reduce a 10 |446| `timeout` | no | Segundos antes de cancelar. Claude Code no lo aplica en un hook de comando que ejecutas con [`async: true`](#run-hooks-in-the-background). Valores por defecto: 600 para `command`, `http` y `mcp_tool`; 30 para `prompt`; 60 para `agent`. Claude Code reduce el valor por defecto de `command`, `http` y `mcp_tool` a 30 en [`UserPromptSubmit`](#userpromptsubmit), [`PreModelSwitch`](#premodelswitch) y [`PostModelSwitch`](#postmodelswitch), y a 10 en [`MessageDisplay`](#messagedisplay). Los hooks de [`SessionEnd`](#sessionend) comparten un presupuesto de 1.5 segundos; si tu configuración establece un `timeout` por hook más largo, Claude Code aumenta el presupuesto para que coincida, hasta 60 segundos |
346| `statusMessage` | no | Mensaje de spinner personalizado mostrado mientras se ejecuta el hook |447| `statusMessage` | no | Mensaje de spinner personalizado mostrado mientras se ejecuta el hook |
347| `once` | no | Si es `true`, se ejecuta una vez por sesión y luego se elimina. Solo se honra para hooks declarados en [skill frontmatter](#hooks-in-skills-and-agents); se ignora en archivos de configuración y frontmatter de agente |448| `once` | no | Si es `true`, Claude Code elimina el hook después de su primera ejecución exitosa. Una ejecución que falla, bloquea con código de salida 2 o agota el tiempo de espera deja el hook en su lugar, por lo que se ejecuta de nuevo en el siguiente evento coincidente. Solo se respeta para hooks declarados en [frontmatter de skill](#hooks-in-skills-and-agents); se ignora en archivos de configuración y frontmatter de agente |
449
450El campo `if` contiene exactamente una regla de permisos. No hay sintaxis `&&`, `||` o de lista para combinar reglas; para aplicar múltiples condiciones, define un manejador de hook separado para cada una.
348 451
349El campo `if` contiene exactamente una regla de permiso. No hay sintaxis `&&`, `||` o de lista para combinar reglas; para aplicar múltiples condiciones, defina un controlador de hook separado para cada una.452En una condición `if` para una herramienta de archivo, un patrón de directorio de un solo segmento como `"Edit(src/**)"` coincide solo con el directorio `src` en el directorio de trabajo y los archivos bajo él. Para coincidir con un directorio llamado `src` a cualquier profundidad, escribe `"Edit(**/src/**)"`. Antes de v2.1.214, `"Edit(src/**)"` coincidía con un directorio llamado `src` a cualquier profundidad bajo el directorio de trabajo.
350 453
351<span id="bash-if-matching" />Para patrones de Bash, si su comando hook se ejecuta depende de la forma del patrón y del comando Bash que Claude está invocando. Las asignaciones `VAR=value` iniciales se eliminan antes de coincidir.454<span id="bash-if-matching" />Para patrones de Bash, si tu comando de hook se ejecuta depende de la forma del patrón y del comando de Bash que Claude está invocando. Las asignaciones `VAR=value` iniciales se eliminan antes de hacer coincidir.
352 455
353| patrón `if` | Comando Bash | ¿Se ejecuta el hook? | Por qué |456| Patrón `if` | Comando de Bash | ¿Se ejecuta el hook? | Por qué |
354| :----------------- | :--------------------- | :------------------- | :----------------------------------------------------------------------------------------------------------------------- |457| :----------------- | :-------------------------- | :------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------- |
355| `Bash(git *)` | `FOO=bar git push` | sí | las asignaciones iniciales se eliminan; `git push` coincide |458| `Bash(git *)` | `FOO=bar git push` | sí | las asignaciones iniciales se eliminan; `git push` coincide |
356| `Bash(git *)` | `npm test && git push` | sí | cada subcomando se verifica; `git push` coincide |459| `Bash(git *)` | `npm test && git push` | sí | cada subcomando se verifica; `git push` coincide |
357| `Bash(rm *)` | `echo $(rm -rf /)` | sí | los comandos dentro de `$()` y backticks se verifican; `rm -rf /` coincide |460| `Bash(rm *)` | `echo $(rm -rf /)` | sí | los comandos dentro de `$()` y backticks se verifican; `rm -rf /` coincide |
358| `Bash(rm *)` | `echo $(date)` | no | ningún subcomando coincide con `rm *` |461| `Bash(rm *)` | `echo $(date)` | no | ningún subcomando coincide con `rm *` |
462| `Bash(cat *)` | `echo before $(date) after` | no | una sustitución puede estar en cualquier posición de argumento, por lo que se verifican el comando completo y `date`; ninguno coincide con `cat *` |
463| `Bash(git *)` | `$TOOL git push` | sí | Claude Code no puede saber a qué se expande el nombre del comando, por lo que ejecuta el hook |
359| `Bash(git push *)` | `echo $(date)` | sí | los patrones que especifican más que el nombre del comando ejecutan el hook de todas formas en `$()`, backticks o `$VAR` |464| `Bash(git push *)` | `echo $(date)` | sí | los patrones que especifican más que el nombre del comando ejecutan el hook de todas formas en `$()`, backticks o `$VAR` |
360 465
361El filtro también falla abierto, ejecutando su hook independientemente del patrón, cuando el comando Bash no se puede analizar. Debido a que el filtro `if` es de mejor esfuerzo, use el [sistema de permisos](/docs/es/permissions) en lugar de un hook para aplicar un permiso o denegación duro.466Cuando Claude Code no puede determinar qué comandos ejecuta la entrada de Bash, ejecuta tu hook independientemente del patrón. Porque el filtro `if` es de mejor esfuerzo, utiliza el [sistema de permisos](/docs/es/permissions) en lugar de un hook para aplicar una autorización o denegación dura.
362 467
363<h4 id="command-hook-fields">468<h4 id="command-hook-fields">
364 Campos de comando hook469 Campos de hook de comando
365</h4>470</h4>
366 471
367Además de los [campos comunes](#common-fields), los hooks de comando aceptan estos campos:472Además de los [campos comunes](#common-fields), los hooks de comando aceptan estos campos:
368 473
369| Campo | Requerido | Descripción |474| Campo | Requerido | Descripción |
370| :------------ | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |475| :------------ | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
371| `command` | sí | Comando de shell a ejecutar. Con `args`, el ejecutable a generar directamente. Consulte [Exec form and shell form](#exec-form-and-shell-form) |476| `command` | sí | Comando de shell a ejecutar. Con `args`, el ejecutable a generar directamente. Consulta [Forma exec y forma shell](#exec-form-and-shell-form) |
372| `args` | no | Lista de argumentos. Cuando está presente, `command` se resuelve como un ejecutable y se genera directamente con `args` como el vector de argumentos, sin shell involucrado. Consulte [Exec form and shell form](#exec-form-and-shell-form) |477| `args` | no | Lista de argumentos. Cuando está presente, `command` se resuelve como un ejecutable y se genera directamente con `args` como el vector de argumentos, sin shell involucrado. Consulta [Forma exec y forma shell](#exec-form-and-shell-form) |
373| `async` | no | Si es `true`, se ejecuta en segundo plano sin bloquear. Consulte [Run hooks in the background](#run-hooks-in-the-background) |478| `async` | no | Si es `true`, se ejecuta en segundo plano sin bloquear. Consulta [Ejecutar hooks en segundo plano](#run-hooks-in-the-background) |
374| `asyncRewake` | no | Si es `true`, se ejecuta en segundo plano y despierta a Claude en código de salida 2. Implica `async`. El stderr del hook, o stdout si stderr está vacío, se muestra a Claude como un recordatorio del sistema para que pueda reaccionar a un fallo de fondo de larga duración |479| `asyncRewake` | no | Si es `true`, se ejecuta en segundo plano y despierta a Claude en código de salida 2. El stderr del hook, o stdout si stderr está vacío, se muestra a Claude como un recordatorio del sistema para que pueda reaccionar a un fallo de fondo de larga duración |
375| `shell` | no | Shell a usar para este hook. Acepta `"bash"` o `"powershell"`. Por defecto es `"bash"`, o `"powershell"` en Windows cuando Git Bash no está instalado. Establecer `"powershell"` ejecuta el comando a través de PowerShell en Windows. No requiere `CLAUDE_CODE_USE_POWERSHELL_TOOL` ya que los hooks generan PowerShell directamente. Se ignora cuando `args` está establecido |480| `shell` | no | Shell a usar para este hook. Acepta `"bash"` o `"powershell"`. Por defecto es `"bash"`, o `"powershell"` en Windows cuando Git Bash no está instalado. Establecer `"powershell"` ejecuta el comando a través de PowerShell en Windows. No requiere `CLAUDE_CODE_USE_POWERSHELL_TOOL` ya que los hooks generan PowerShell directamente. Se ignora cuando `args` está establecido |
376 481
377<a id="exec-form-and-shell-form" />482<a id="exec-form-and-shell-form" />
378 483
379<h5 id="exec-form-and-shell-form">484<h5 id="exec-form-and-shell-form">
380 Exec form y shell form485 Forma exec y forma shell
381</h5>486</h5>
382 487
383Un hook de comando se ejecuta como exec form cuando `args` está establecido, y shell form cuando `args` se omite. Establezca `args` siempre que el hook haga referencia a un [marcador de posición de ruta](#reference-scripts-by-path), ya que cada elemento se pasa como un argumento sin comillas. Omita `args` cuando necesite características de shell como pipes o `&&`, o cuando ninguna preocupación se aplique.488Un hook de comando se ejecuta como forma exec cuando `args` está establecido, y forma shell cuando `args` se omite. Establece `args` siempre que el hook haga referencia a un [marcador de posición de ruta](#reference-scripts-by-path), ya que cada elemento se pasa como un argumento. Omite `args` cuando necesites características de shell como pipes o `&&`, o cuando ninguna preocupación se aplique.
384 489
385**Exec form** se ejecuta cuando `args` está presente. Claude Code resuelve `command` como un ejecutable en `PATH` y lo genera directamente con `args` como el vector de argumentos. No hay shell, por lo que cada elemento `args` es exactamente un argumento tal como está escrito, y los marcadores de posición de ruta como `${CLAUDE_PLUGIN_ROOT}` se sustituyen en `command` y en cada elemento `args` como cadenas simples. Los caracteres especiales como apóstrofes, `$` y backticks pasan literalmente porque no hay shell para interpretarlos. No ocurre tokenización de shell en ninguna plataforma.490**Forma exec** se ejecuta cuando `args` está presente. Claude Code resuelve `command` como un ejecutable en `PATH` y lo genera directamente con `args` como el vector de argumentos. No hay shell, por lo que cada elemento de `args` es exactamente un argumento tal como está escrito, y los marcadores de posición de ruta como `${CLAUDE_PLUGIN_ROOT}` se sustituyen en `command` y en cada elemento de `args` como cadenas simples. Los caracteres especiales como apóstrofes, `$` y backticks pasan sin cambios porque no hay shell para interpretarlos. No ocurre tokenización de shell en ninguna plataforma.
386 491
387**Shell form** se ejecuta cuando `args` se omite. La cadena `command` se pasa a un shell: `sh -c` en macOS y Linux, Git Bash en Windows, o PowerShell cuando Git Bash no está instalado. Establezca el campo `shell` para elegir explícitamente. El shell tokeniza la cadena, expande variables e interpreta pipes, `&&`, redirecciones y globs.492**Forma shell** se ejecuta cuando `args` se omite. La cadena `command` se pasa a un shell: `sh -c` en macOS y Linux, Git Bash en Windows, o PowerShell cuando Git Bash no está instalado. Establece el campo `shell` para elegir explícitamente. El shell tokeniza la cadena, expande variables e interpreta pipes, `&&`, redirecciones y globs.
388 493
389<Note>494<Note>
390 En Windows, exec form requiere que `command` se resuelva a un ejecutable real como `.exe`. Los shims `.cmd` y `.bat` que npm, npx, eslint y otras herramientas instalan en `node_modules/.bin` no son ejecutables y no pueden generarse sin un shell. Para ejecutarlos en exec form, invoque el script subyacente con `node` directamente, por ejemplo `"command": "node", "args": ["${CLAUDE_PLUGIN_ROOT}/node_modules/eslint/bin/eslint.js"]`. El patrón `node` más ruta de script funciona en cada plataforma porque `node.exe` es un binario real. Para ejecutar un shim `.cmd` o `.bat` por nombre, use shell form.495 En Windows, la forma exec requiere que `command` se resuelva en un ejecutable real como `.exe`. Los shims `.cmd` y `.bat` que npm, npx, eslint y otras herramientas instalan en `node_modules/.bin` no son ejecutables y no se pueden generar sin un shell. Para ejecutarlos en forma exec, invoca el script subyacente con `node` directamente, por ejemplo `"command": "node", "args": ["${CLAUDE_PLUGIN_ROOT}/node_modules/eslint/bin/eslint.js"]`. El patrón `node` más ruta de script funciona en cada plataforma porque `node.exe` es un binario real. Para ejecutar un shim `.cmd` o `.bat` por nombre, usa forma shell.
391</Note>496</Note>
392 497
393Este ejemplo ejecuta un script de Node incluido con un plugin. Exec form pasa la ruta de script resuelta como un argumento sin comillas:498Este ejemplo ejecuta un script de Node incluido con un plugin. La forma exec pasa la ruta de script resuelta como un argumento sin comillas:
394 499
395```json theme={null}500```json theme={null}
396{501{
400}505}
401```506```
402 507
403La forma de shell equivalente necesita comillas para manejar rutas con espacios o caracteres especiales:508La forma shell equivalente necesita comillas para manejar rutas con espacios o caracteres especiales:
404 509
405```json theme={null}510```json theme={null}
406{511{
409}514}
410```515```
411 516
412Ambas formas admiten los mismos [marcadores de posición de ruta](#reference-scripts-by-path), y ambas los exportan como las variables de entorno `CLAUDE_PROJECT_DIR`, `CLAUDE_PLUGIN_ROOT` y `CLAUDE_PLUGIN_DATA` en el proceso generado, por lo que un script puede leer `process.env.CLAUDE_PLUGIN_ROOT` independientemente de cómo se haya lanzado.517Ambas formas soportan los mismos [marcadores de posición de ruta](#reference-scripts-by-path), y ambas los exportan como variables de entorno `CLAUDE_PROJECT_DIR`, `CLAUDE_PLUGIN_ROOT` y `CLAUDE_PLUGIN_DATA` en el proceso generado, por lo que un script puede leer `process.env.CLAUDE_PLUGIN_ROOT` independientemente de cómo se haya lanzado.
413 518
414Los hooks de plugin además sustituyen valores [`${user_config.*}`](/docs/es/plugins-reference#user-configuration), solo en exec form: el valor se sustituye en `command` y en cada elemento `args` como una cadena simple, por lo que ningún shell lo vuelve a analizar.519Los hooks de plugin además sustituyen valores [`${user_config.*}`](/docs/es/plugins-reference#user-configuration), solo en forma exec: el valor se sustituye en `command` y en cada elemento de `args` como una cadena simple, por lo que ningún shell lo re-analiza.
415 520
416Un hook de plugin en shell form cuyo `command` hace referencia a `${user_config.*}` falla con un [error](/docs/es/errors#plugin-command-references-user-config) en lugar de ejecutarse. Para usar un valor de opción de un hook en shell form, lea la variable de entorno `$CLAUDE_PLUGIN_OPTION_<KEY>`, como `$CLAUDE_PLUGIN_OPTION_WEBHOOK_URL` para una opción `webhook_url`, o establezca `args` para cambiar el hook a exec form. Antes de v2.1.207, los comandos de hook de plugin en shell form también sustituían `${user_config.*}`.521Un hook de plugin en forma shell cuyo `command` hace referencia a `${user_config.*}` falla con un [error](/docs/es/errors#plugin-command-references-user-config) en lugar de ejecutarse. Para usar un valor de opción de un hook en forma shell, lee la variable de entorno `$CLAUDE_PLUGIN_OPTION_<KEY>`, como `$CLAUDE_PLUGIN_OPTION_WEBHOOK_URL` para una opción `webhook_url`, o establece `args` para cambiar el hook a forma exec. Antes de v2.1.207, los comandos de hook de plugin en forma shell también sustituían `${user_config.*}`.
417 522
418<Note>523<Note>
419 En exec form, `command` es solo el nombre o ruta del ejecutable. Si `command` es un nombre simple sin separador de ruta y contiene espacios junto con `args`, Claude Code registra una advertencia porque la generación fallará: no hay ejecutable llamado `node script.js`. Mueva los tokens adicionales a `args`. Las rutas absolutas con espacios, como `C:\Program Files\nodejs\node.exe`, son un ejecutable válido único y no desencadenan la advertencia.524 En forma exec, `command` es solo el nombre o ruta del ejecutable. Si `command` es un nombre desnudo sin separador de ruta y contiene espacios junto con `args`, Claude Code registra una advertencia porque la generación fallará: no hay un ejecutable llamado `node script.js`. Mueve los tokens adicionales a `args`. Las rutas absolutas con espacios, como `C:\Program Files\nodejs\node.exe`, son un ejecutable válido único y no activan la advertencia.
420</Note>525</Note>
421 526
422<h4 id="http-hook-fields">527<h4 id="http-hook-fields">
426Además de los [campos comunes](#common-fields), los hooks HTTP aceptan estos campos:531Además de los [campos comunes](#common-fields), los hooks HTTP aceptan estos campos:
427 532
428| Campo | Requerido | Descripción |533| Campo | Requerido | Descripción |
429| :--------------- | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |534| :--------------- | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
430| `url` | sí | URL a la que enviar la solicitud POST |535| `url` | sí | URL a la que enviar la solicitud POST |
431| `headers` | no | Encabezados HTTP adicionales como pares clave-valor. Los valores admiten interpolación de variables de entorno usando la sintaxis `$VAR_NAME` o `${VAR_NAME}`. Solo se resuelven las variables enumeradas en `allowedEnvVars` |536| `headers` | no | Encabezados HTTP adicionales como pares clave-valor. Los valores soportan interpolación de variables de entorno usando sintaxis `$VAR_NAME` o `${VAR_NAME}`. Solo se resuelven las variables listadas en `allowedEnvVars` |
432| `allowedEnvVars` | no | Lista de nombres de variables de entorno que pueden interpolarse en valores de encabezado. Las referencias a variables no enumeradas se reemplazan con cadenas vacías. Requerido para que funcione cualquier interpolación de variable de entorno |537| `allowedEnvVars` | no | Lista de nombres de variables de entorno que pueden interpolarse en valores de encabezado. Las referencias a variables no listadas se reemplazan con cadenas vacías. Requerido para que funcione cualquier interpolación de variable de entorno |
433 538
434Claude Code envía la [entrada JSON](#hook-input-and-output) del hook como el cuerpo de la solicitud POST con `Content-Type: application/json`. El cuerpo de la respuesta usa el mismo [formato de salida JSON](#json-output) que los hooks de comando.539Claude Code envía la [entrada JSON](#hook-input-and-output) del hook como el cuerpo de solicitud POST con `Content-Type: application/json`. El cuerpo de respuesta utiliza el mismo [formato de salida JSON](#json-output) que los hooks de comando.
435 540
436El manejo de errores difiere de los hooks de comando: las respuestas que no son 2xx, los fallos de conexión y los tiempos de espera agotados producen errores sin bloqueo que permiten que la ejecución continúe. Para bloquear una llamada a herramienta o denegar un permiso, devuelva una respuesta 2xx con un cuerpo JSON que contenga `decision: "block"` o un `hookSpecificOutput` con `permissionDecision: "deny"`.541El manejo de errores difiere de los hooks de comando; consulta [Manejo de respuesta HTTP](#http-response-handling).
437 542
438Este ejemplo envía eventos `PreToolUse` a un servicio de validación local, autenticándose con un token de la variable de entorno `MY_TOKEN`:543Este ejemplo envía eventos `PreToolUse` a un servicio de validación local, autenticándose con un token de la variable de entorno `MY_TOKEN`:
439 544
467Además de los [campos comunes](#common-fields), los hooks de herramienta MCP aceptan estos campos:572Además de los [campos comunes](#common-fields), los hooks de herramienta MCP aceptan estos campos:
468 573
469| Campo | Requerido | Descripción |574| Campo | Requerido | Descripción |
470| :------- | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |575| :------- | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
471| `server` | sí | Nombre de un servidor MCP configurado. Para un [servidor incluido en plugin](/docs/es/mcp#plugin-provided-mcp-servers), este es el nombre con alcance `plugin:<plugin-name>:<server-name>`, como `plugin:my-plugin:db`, no la clave del servidor simple. El servidor ya debe estar conectado; el hook nunca desencadena un flujo OAuth o de conexión |576| `server` | sí | Nombre de un servidor MCP configurado. Para un [servidor incluido en plugin](/docs/es/mcp#plugin-provided-mcp-servers), este es el nombre con alcance `plugin:<plugin-name>:<server-name>`, como `plugin:my-plugin:db`, no la clave del servidor desnuda. El servidor debe estar ya conectado; el hook nunca activa un flujo OAuth o de conexión |
472| `tool` | sí | Nombre de la herramienta a llamar en ese servidor |577| `tool` | sí | Nombre de la herramienta a llamar en ese servidor |
473| `input` | no | Argumentos pasados a la herramienta. Los valores de cadena admiten sustitución `${path}` de la [entrada JSON](#hook-input-and-output) del hook, como `"${tool_input.file_path}"` |578| `input` | no | Argumentos pasados a la herramienta. Los valores de cadena soportan sustitución de `${path}` de la [entrada JSON](#hook-input-and-output) del hook, como `"${tool_input.file_path}"` |
474 579
475La salida de texto de la herramienta se trata como stdout de hook de comando: si se analiza como [salida JSON](#json-output) válida, se procesa como una decisión; de lo contrario, se muestra como texto sin formato. Si el servidor nombrado no está conectado, o la herramienta devuelve `isError: true`, el hook produce un error sin bloqueo y la ejecución continúa.580Claude Code lee el contenido de texto de la herramienta de la misma manera que lee stdout de hook de comando, siguiendo la [regla de análisis bajo código de salida 0](#exit-code-0). Si el servidor nombrado no está conectado, o la herramienta devuelve `isError: true`, el hook produce un error sin bloqueo y la ejecución continúa.
476
477Los hooks de herramienta MCP están disponibles en cada evento de hook una vez que Claude Code se ha conectado a sus servidores MCP. `SessionStart` y `Setup` típicamente se activan antes de que los servidores terminen de conectarse, por lo que los hooks en esos eventos deben esperar el error "no conectado" en la primera ejecución.
478 581
479Este ejemplo llama a la herramienta `security_scan` en el servidor MCP `my_server` después de cada `Write` o `Edit`, pasando la ruta del archivo editado:582Este ejemplo llama a la herramienta `security_scan` en el servidor MCP `my_server` después de cada `Write` o `Edit`, pasando la ruta del archivo editado:
480 583
498}601}
499```602```
500 603
604Un hook `mcp_tool` puede ejecutarse solo después de que Claude Code haya puesto los servidores MCP de la sesión disponibles para los hooks. `SessionStart` y `Setup` pueden activarse antes de ese punto:
605
606* **Al lanzar**: `SessionStart` se activa antes de que los servidores estén disponibles, incluso cuando lanzas con `--continue` o `--resume`. Claude Code omite los hooks `mcp_tool` del evento sin llamar a sus herramientas, y el [registro de depuración](#debug-hooks) registra `mcp_tool hooks are not available for the 'SessionStart' hook event (no MCP client context)`.
607* **Más tarde en una sesión en ejecución**: después de `/clear` o una compactación, `SessionStart` se activa de nuevo con los servidores ya disponibles, y sus hooks `mcp_tool` se ejecutan.
608* **En `Setup`**: `Setup` siempre se activa antes de que los servidores estén disponibles, por lo que Claude Code omite sus hooks `mcp_tool` cada vez y registra el mismo mensaje nombrando `Setup`.
609
610Por ejemplo, esta configuración llama a la herramienta `load_context` en el servidor MCP `my_server` desde un hook `SessionStart` sin matcher, por lo que se aplica a cada fuente de `SessionStart`:
611
612```json theme={null}
613{
614 "hooks": {
615 "SessionStart": [
616 {
617 "hooks": [
618 {
619 "type": "mcp_tool",
620 "server": "my_server",
621 "tool": "load_context"
622 }
623 ]
624 }
625 ]
626 }
627}
628```
629
630Cuando ejecutas `claude`, Claude Code omite este hook, nunca llama a `load_context` y escribe el mensaje `no MCP client context` en el registro de depuración. Ejecuta `/clear` en esa misma sesión y el hook se ejecuta y llama a `load_context`. Un hook `type: "command"` en `SessionStart` se ejecuta al lanzar, por lo que usa uno para cualquier cosa que la sesión necesite desde su primer turno.
631
501<h4 id="prompt-and-agent-hook-fields">632<h4 id="prompt-and-agent-hook-fields">
502 Campos de hook de prompt y agente633 Campos de hook de prompt y agente
503</h4>634</h4>
505Además de los [campos comunes](#common-fields), los hooks de prompt y agente aceptan estos campos:636Además de los [campos comunes](#common-fields), los hooks de prompt y agente aceptan estos campos:
506 637
507| Campo | Requerido | Descripción |638| Campo | Requerido | Descripción |
508| :------- | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |639| :------- | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
509| `prompt` | sí | Texto del prompt a enviar al modelo. Use `$ARGUMENTS` como marcador de posición para la entrada JSON del hook. Escape con una barra invertida para incluir texto literal: `\$1.00` se representa como `$1.00` |640| `prompt` | sí | Texto de prompt a enviar al modelo. Usa `$ARGUMENTS` como marcador de posición para la entrada JSON del hook. Escapa con una barra invertida para incluir texto literal: `\$1.00` se renderiza como `$1.00` |
510| `model` | no | Modelo a usar para evaluación. Por defecto es un modelo rápido |641| `model` | no | Modelo a usar para evaluación. Por defecto es un modelo rápido |
511 642
512<h3 id="reference-scripts-by-path">643<h3 id="reference-scripts-by-path">
513 Referenciar scripts por ruta644 Referencia de scripts por ruta
514</h3>645</h3>
515 646
516Use estos marcadores de posición para referenciar scripts de hooks relativos a la raíz del proyecto o plugin, independientemente del directorio de trabajo cuando se ejecuta el hook:647Utiliza estos marcadores de posición para hacer referencia a scripts de hook relativos a la raíz del proyecto o plugin, independientemente del directorio de trabajo cuando se ejecuta el hook:
648
649* `${CLAUDE_PROJECT_DIR}`: la raíz del proyecto donde comenzó la sesión. Claude Code también establece esta variable en el entorno de [servidores MCP stdio](/docs/es/mcp#option-3-add-a-local-stdio-server) y servidores LSP de plugin.
650* `${CLAUDE_PLUGIN_ROOT}`: el directorio de instalación del plugin, para scripts incluidos con un [plugin](/docs/es/plugins). Consulta [variables de entorno de plugin](/docs/es/plugins-reference#environment-variables) para saber cómo se comporta la ruta entre actualizaciones.
651* `${CLAUDE_PLUGIN_DATA}`: el [directorio de datos persistentes](/docs/es/plugins-reference#persistent-data-directory) del plugin, para dependencias y estado que deben sobrevivir a las actualizaciones del plugin.
517 652
518* `${CLAUDE_PROJECT_DIR}`: la raíz del proyecto. Claude Code también establece esta variable en el entorno de [servidores MCP stdio](/docs/es/mcp#option-3-add-a-local-stdio-server) y servidores LSP de plugin.653<Note>
519* `${CLAUDE_PLUGIN_ROOT}`: el directorio de instalación del plugin, para scripts incluidos con un [plugin](/docs/es/plugins). Cambia en cada actualización de plugin.654 **Los worktrees son diferentes.** Si Claude entra en un [worktree](/docs/es/worktrees) durante la sesión, Claude Code mantiene `${CLAUDE_PROJECT_DIR}` donde estaba y pasa la ruta del worktree a tus hooks de una manera diferente:
520* `${CLAUDE_PLUGIN_DATA}`: el [directorio de datos persistentes](/docs/es/plugins-reference#persistent-data-directory) del plugin, para dependencias y estado que deben sobrevivir a las actualizaciones de plugin.
521 655
522Prefiera [exec form](#exec-form-and-shell-form) para cualquier hook que haga referencia a un marcador de posición de ruta. Exec form pasa cada elemento `args` como un argumento sin tokenización de shell, por lo que las rutas con espacios o caracteres especiales no necesitan comillas. En shell form, envuelva cada marcador de posición entre comillas dobles.656 * **`${CLAUDE_PROJECT_DIR}` se queda en su lugar**: aún apunta a la raíz del proyecto donde comenzó la sesión, por lo que un comando como `${CLAUDE_PROJECT_DIR}/.claude/hooks/check-style.sh` aún ejecuta el script en el checkout principal.
657 * **`cwd` sigue a Claude**: el campo `cwd` en la [entrada JSON](#common-input-fields) del hook es la raíz del worktree después de que Claude entra en un worktree, y el nuevo directorio después de que Claude ejecuta `cd`. Léelo cuando un hook necesite saber en qué directorio está trabajando Claude.
658</Note>
659
660Prefiere [forma exec](#exec-form-and-shell-form) para cualquier hook que haga referencia a un marcador de posición de ruta. En forma shell, envuelve cada marcador de posición en comillas dobles.
523 661
524<Tabs>662<Tabs>
525 <Tab title="Scripts de proyecto">663 <Tab title="Project scripts">
526 Este ejemplo usa `${CLAUDE_PROJECT_DIR}` para ejecutar un verificador de estilo desde el directorio `.claude/hooks/` del proyecto después de cualquier llamada a herramienta `Write` o `Edit`:664 Este ejemplo usa `${CLAUDE_PROJECT_DIR}` para ejecutar un verificador de estilo desde el directorio `.claude/hooks/` del proyecto después de cualquier llamada de herramienta `Write` o `Edit`:
527 665
528 ```json theme={null}666 ```json theme={null}
529 {667 {
545 ```683 ```
546 </Tab>684 </Tab>
547 685
548 <Tab title="Scripts de plugin">686 <Tab title="Plugin scripts">
549 Defina hooks de plugin en `hooks/hooks.json` con un campo `description` opcional de nivel superior. Cuando se habilita un plugin, sus hooks se fusionan con sus hooks de usuario y proyecto.687 Define hooks de plugin en `hooks/hooks.json` con un campo `description` opcional de nivel superior. Cuando un plugin está habilitado, sus hooks se fusionan con tus hooks de usuario y proyecto.
550 688
551 Este ejemplo ejecuta un script de formato incluido con el plugin:689 Este ejemplo ejecuta un script de formato incluido con el plugin:
552 690
571 }709 }
572 ```710 ```
573 711
574 Consulte la [referencia de componentes de plugin](/docs/es/plugins-reference#hooks) para obtener detalles sobre cómo crear hooks de plugin.712 Consulta la [referencia de componentes de plugin](/docs/es/plugins-reference#hooks) para obtener detalles sobre cómo crear hooks de plugin.
575 </Tab>713 </Tab>
576</Tabs>714</Tabs>
577 715
579 Hooks en skills y agentes717 Hooks en skills y agentes
580</h3>718</h3>
581 719
582Además de archivos de configuración y plugins, los hooks pueden definirse directamente en [skills](/docs/es/skills) y [subagentes](/docs/es/sub-agents) usando frontmatter. Estos hooks se limitan al ciclo de vida del componente y solo se ejecutan cuando ese componente está activo.720Además de archivos de configuración y plugins, los hooks pueden definirse directamente en [skills](/docs/es/skills) y [subagentes](/docs/es/sub-agents) usando frontmatter, en el mismo formato de configuración que los hooks basados en configuración. Cuánto tiempo Claude Code los mantiene registrados depende del componente:
583
584Se admiten todos los eventos de hook. Para subagentes, los hooks `Stop` se convierten automáticamente a `SubagentStop` ya que ese es el evento que se activa cuando un subagente se completa.
585 721
586Los hooks usan el mismo formato de configuración que los hooks basados en configuración pero se limitan a la vida útil del componente y se limpian cuando finaliza.722* **Hooks de subagente**: Claude Code los ejecuta solo mientras ese subagente se está ejecutando y los elimina cuando termina. Claude Code convierte un hook `Stop` aquí a `SubagentStop`, el evento que se activa cuando un subagente se completa.
723* **Hooks de skill**: Claude Code los registra cuando tú o Claude invocas la skill y los mantiene ejecutándose durante el resto de la sesión, en turnos después del turno propio de la skill también. Para que Claude Code elimine un hook después de su primera ejecución exitosa en su lugar, establece [`once: true`](#common-fields) en él.
587 724
588Esta skill define un hook `PreToolUse` que ejecuta un script de validación de seguridad antes de cada comando `Bash`:725Esta skill define un hook `PreToolUse` que ejecuta un script de validación de seguridad antes de cada comando `Bash`:
589 726
600---737---
601```738```
602 739
603Los agentes usan el mismo formato en su frontmatter YAML.740Los subagentes utilizan el mismo formato en su frontmatter YAML.
741
742Los hooks de frontmatter en una skill de proyecto siguen la misma [regla de confianza de espacio de trabajo que los hooks en archivos de configuración](#workspace-trust). Claude Code los registra cuando tú o Claude invocas la skill, incluso en una ejecución `-p` en una carpeta que no has confiado.
743
744Los hooks de frontmatter en un subagente de proyecto se ejecutan solo después de que aceptes el [diálogo de confianza de espacio de trabajo](/docs/es/permissions#project-allow-rules-and-workspace-trust) para la carpeta de la que proviene el archivo del agente. Una sesión `-p` no cuenta como aceptarlo. [Lo que se ejecuta antes de confiar en una carpeta](/docs/es/permissions#what-runs-before-you-trust-a-folder) compara esto con la regla del archivo de configuración, y la página de subagentes lista [qué alcances están exentos](/docs/es/sub-agents#hooks-in-subagent-frontmatter). Antes de v2.1.218, estos hooks podían ejecutarse desde carpetas que no habías confiado.
604 745
605<h3 id="the-/hooks-menu">746<h3 id="the-/hooks-menu">
606 El menú `/hooks`747 El menú `/hooks`
607</h3>748</h3>
608 749
609Escriba `/hooks` en Claude Code para abrir un navegador de solo lectura para sus hooks configurados. El menú muestra cada evento de hook con un recuento de hooks configurados, le permite profundizar en matchers y muestra los detalles completos de cada controlador de hook. Úselo para verificar la configuración, verificar desde qué archivo de configuración proviene un hook o inspeccionar el comando, prompt o URL de un hook.750Escribe `/hooks` en Claude Code para abrir un navegador de solo lectura para tus hooks configurados. El menú muestra cada evento de hook con un recuento de hooks configurados, te permite profundizar en matchers y muestra los detalles completos de cada manejador de hook. Úsalo para verificar la configuración, comprobar desde qué archivo de configuración proviene un hook o inspeccionar el comando, prompt o URL de un hook.
610 751
611El menú muestra los cinco tipos de hooks: `command`, `prompt`, `agent`, `http` y `mcp_tool`. Cada hook está etiquetado con un prefijo `[type]` y una fuente que indica dónde se definió:752El menú muestra los cinco tipos de hook: `command`, `prompt`, `agent`, `http` y `mcp_tool`. Cada hook está etiquetado con un prefijo `[type]` y una fuente que indica dónde se definió:
612 753
613* `User`: de `~/.claude/settings.json`754* `User Settings`: de `~/.claude/settings.json`
614* `Project`: de `.claude/settings.json`755* `Project Settings`: de `.claude/settings.json`
615* `Local`: de `.claude/settings.local.json`756* `Local Settings`: de `.claude/settings.local.json`
616* `Plugin`: de `hooks/hooks.json` de un plugin757* `Plugin Hooks`: de `hooks/hooks.json` de un plugin
617* `Session`: registrado en memoria para la sesión actual758* `Session Hooks`: registrado en memoria para la sesión actual
618* `Built-in`: registrado internamente por Claude Code
619 759
620Seleccionar un hook abre una vista de detalle que muestra su evento, matcher, tipo, archivo de origen y el comando, prompt o URL completo. El menú es de solo lectura: para agregar, modificar o eliminar hooks, edite el JSON de configuración directamente o pida a Claude que haga el cambio.760Seleccionar un hook abre una vista de detalle mostrando su evento, matcher, tipo, archivo de origen y el comando, prompt o URL completo. El menú es de solo lectura: para añadir, modificar o eliminar hooks, edita el JSON de configuración directamente o pide a Claude que haga el cambio.
621 761
622<h3 id="disable-or-remove-hooks">762<h3 id="disable-or-remove-hooks">
623 Deshabilitar o eliminar hooks763 Deshabilitar o eliminar hooks
624</h3>764</h3>
625 765
626Para eliminar un hook, elimine su entrada del archivo de configuración JSON.766Para eliminar un hook, elimina su entrada del archivo JSON de configuración.
627 767
628Para deshabilitar temporalmente todos los hooks sin eliminarlos, establezca `"disableAllHooks": true` en su archivo de configuración. No hay forma de deshabilitar un hook individual mientras se mantiene en la configuración.768Para deshabilitar temporalmente todos los hooks sin eliminarlos, establece `"disableAllHooks": true` en tu archivo de configuración. Claude Code lee el valor que queda después de que se aplica la [precedencia de configuración](/docs/es/settings#settings-precedence), por lo que un `"disableAllHooks": false` en `.claude/settings.json` de un proyecto anula un `true` en tu configuración de usuario. Para desactivar los hooks para una ejecución sin importar lo que diga la configuración del proyecto, pasa `--settings '{"disableAllHooks": true}'`, que tiene precedencia sobre la configuración de proyecto y local. No hay forma de deshabilitar un hook individual mientras lo mantienes en la configuración.
629 769
630La configuración `disableAllHooks` respeta la jerarquía de configuración administrada. Si un administrador ha configurado hooks a través de configuración de política administrada, `disableAllHooks` establecido en configuración de usuario, proyecto o local no puede deshabilitar esos hooks administrados. Solo `disableAllHooks` establecido en el nivel de configuración administrada puede deshabilitar hooks administrados.770La configuración `disableAllHooks` respeta la jerarquía de configuración administrada. Si un administrador ha configurado hooks a través de la configuración de política administrada, `disableAllHooks` establecido en la configuración de usuario, proyecto o local no puede deshabilitar esos hooks administrados. Solo `disableAllHooks` establecido en el nivel de configuración administrada puede deshabilitar hooks administrados. Para el alcance completo de cada nivel, consulta [`disableAllHooks`](/docs/es/settings-reference#disableallhooks).
631 771
632Las ediciones directas de hooks en archivos de configuración normalmente se capturan automáticamente por el observador de archivos.772Las ediciones directas a hooks en archivos de configuración normalmente se recogen automáticamente por el observador de archivos.
633 773
634<h2 id="hook-input-and-output">774<h2 id="hook-input-and-output">
635 Entrada y salida de hooks775 Entrada y salida de hooks
637 777
638Los hooks de comando reciben datos JSON a través de stdin y comunican resultados a través de códigos de salida, stdout y stderr. Los hooks HTTP reciben el mismo JSON que el cuerpo de la solicitud POST y comunican resultados a través del cuerpo de la respuesta HTTP. Esta sección cubre campos y comportamiento comunes a todos los eventos. Cada sección de evento bajo [Hook events](#hook-events) incluye su esquema de entrada específico y opciones de control de decisión.778Los hooks de comando reciben datos JSON a través de stdin y comunican resultados a través de códigos de salida, stdout y stderr. Los hooks HTTP reciben el mismo JSON que el cuerpo de la solicitud POST y comunican resultados a través del cuerpo de la respuesta HTTP. Esta sección cubre campos y comportamiento comunes a todos los eventos. Cada sección de evento bajo [Hook events](#hook-events) incluye su esquema de entrada específico y opciones de control de decisión.
639 779
640En macOS y Linux, los hooks de comando se ejecutan en su propia sesión sin una terminal de control a partir de v2.1.139. El proceso de hook y cualquier proceso secundario no pueden abrir `/dev/tty` o enviar secuencias de escape directamente a la interfaz de Claude Code. Windows no tiene `/dev/tty`. Para mostrar un mensaje al usuario en cualquier plataforma, devuelva [`systemMessage`](#json-output) en la salida JSON. Para activar una notificación de escritorio, establecer un título de ventana o sonar la campana, devuelva [`terminalSequence`](#emit-terminal-notifications) en su lugar.780En macOS y Linux, los hooks de comando se ejecutan en su propia sesión sin una terminal de control. El proceso de hook y cualquier proceso secundario no pueden abrir `/dev/tty` o enviar secuencias de escape directamente a la interfaz de Claude Code. Windows no tiene `/dev/tty`.
781
782Para mostrar un mensaje al usuario en cualquier plataforma, devuelva [`systemMessage`](#json-output) en la salida JSON. Algunos eventos lo descartan o lo entregan en otro lugar, y cada [sección de evento](#hook-events) lo indica. Para activar una notificación de escritorio, establecer un título de ventana o sonar la campana, devuelva [`terminalSequence`](#emit-terminal-notifications) en su lugar.
641 783
642<h3 id="common-input-fields">784<h3 id="common-input-fields">
643 Campos de entrada comunes785 Campos de entrada comunes
646Los eventos de hook reciben estos campos como JSON, además de campos específicos del evento documentados en cada sección [hook event](#hook-events). Para hooks de comando, este JSON llega a través de stdin. Para hooks HTTP, llega como el cuerpo de la solicitud POST.788Los eventos de hook reciben estos campos como JSON, además de campos específicos del evento documentados en cada sección [hook event](#hook-events). Para hooks de comando, este JSON llega a través de stdin. Para hooks HTTP, llega como el cuerpo de la solicitud POST.
647 789
648| Campo | Descripción |790| Campo | Descripción |
649| :---------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |791| :---------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
650| `session_id` | Identificador de sesión actual |792| `session_id` | Identificador de sesión actual |
651| `prompt_id` | UUID que identifica el prompt del usuario que se está procesando actualmente. Coincide con el [atributo `prompt.id` en eventos de OpenTelemetry](/docs/es/monitoring-usage#event-correlation-attributes), para que pueda correlacionar la salida del hook con la telemetría de un único prompt. Ausente hasta la primera entrada del usuario. Requiere Claude Code v2.1.196 o posterior |793| `prompt_id` | UUID que identifica el prompt del usuario que se está procesando actualmente. Coincide con el [atributo `prompt.id` en eventos de OpenTelemetry](/docs/es/monitoring-usage#event-correlation-attributes), para que pueda correlacionar la salida del hook con la telemetría de un único prompt. Ausente hasta la primera entrada del usuario. Requiere Claude Code v2.1.196 o posterior |
652| `transcript_path` | Ruta al JSON de conversación. El archivo de transcripción se escribe de forma asincrónica y puede rezagarse con respecto a la conversación en memoria, por lo que es posible que aún no incluya los mensajes más recientes del turno actual cuando se activa un hook. Los hooks que necesitan el texto del asistente final del turno actual deben usar `last_assistant_message` en [Stop](#stop) y [SubagentStop](#subagentstop) en lugar de leer la transcripción |794| `transcript_path` | Ruta al JSON de conversación. El archivo de transcripción se escribe de forma asincrónica y puede rezagarse con respecto a la conversación en memoria, por lo que es posible que aún no incluya los mensajes más recientes del turno actual cuando se activa un hook. Los hooks que necesitan el texto del asistente final del turno actual deben usar `last_assistant_message` en [Stop](#stop) y [SubagentStop](#subagentstop) en lugar de leer la transcripción |
653| `cwd` | Directorio de trabajo actual cuando se invoca el hook |795| `cwd` | Directorio de trabajo actual cuando se invoca el hook |
796| `scratchpad_dir` | Ruta al directorio de scratchpad de la sesión, donde Claude mantiene archivos de trabajo temporales. Ausente cuando la sesión no tiene scratchpad o el directorio temporal no está disponible. Requiere Claude Code v2.1.257 o posterior |
654| `permission_mode` | [Modo de permiso](/docs/es/permissions#permission-modes) actual: `"default"`, `"plan"`, `"acceptEdits"`, `"auto"`, `"dontAsk"` o `"bypassPermissions"`. El modo etiquetado como **Manual** llega como `"default"`, nunca como `"manual"`, por lo que los scripts que coinciden con `"default"` siguen funcionando. No todos los eventos reciben este campo. Consulte el ejemplo JSON en cada sección [hook event](#hook-events) |797| `permission_mode` | [Modo de permiso](/docs/es/permissions#permission-modes) actual: `"default"`, `"plan"`, `"acceptEdits"`, `"auto"`, `"dontAsk"` o `"bypassPermissions"`. El modo etiquetado como **Manual** llega como `"default"`, nunca como `"manual"`, por lo que los scripts que coinciden con `"default"` siguen funcionando. No todos los eventos reciben este campo. Consulte el ejemplo JSON en cada sección [hook event](#hook-events) |
655| `effort` | Objeto con un campo `level` que contiene el [nivel de esfuerzo](/docs/es/model-config#adjust-effort-level) activo para el turno: `"low"`, `"medium"`, `"high"`, `"xhigh"` o `"max"`. Si el esfuerzo solicitado del modelo excede lo que el modelo actual admite, este es el nivel degradado que el modelo realmente utilizó. Ultracode no es un nivel distinto y se reporta como `"xhigh"`. El objeto coincide con el campo `effort` de la [línea de estado](/docs/es/statusline#available-data). Presente para eventos que se activan dentro de un contexto de uso de herramienta, como `PreToolUse`, `PostToolUse`, `Stop` y `SubagentStop`, cuando el modelo actual admite el parámetro de esfuerzo. El nivel también está disponible para comandos de hook y la herramienta Bash como la variable de entorno `$CLAUDE_EFFORT`. |798| `effort` | Objeto con un campo `level` que contiene el [nivel de esfuerzo](/docs/es/model-config#adjust-effort-level) en vigor cuando se ejecuta el hook: `"low"`, `"medium"`, `"high"`, `"xhigh"` o `"max"`. Si establece un nivel que el modelo activo no admite, `level` reporta el nivel que Claude Code ejecutó en su lugar; [Adjust effort level](/docs/es/model-config#adjust-effort-level) dice cómo lo elige. Ultracode no es un nivel distinto y se reporta como `"xhigh"`. El objeto coincide con el campo `effort` de la [línea de estado](/docs/es/statusline#available-data). Presente para eventos que se activan dentro de un contexto de uso de herramienta, como `PreToolUse`, `PostToolUse`, `Stop` y `SubagentStop`, cuando el modelo actual admite el parámetro de esfuerzo. El nivel también está disponible para comandos de hook y la herramienta Bash como la variable de entorno `$CLAUDE_EFFORT`. |
656| `hook_event_name` | Nombre del evento que se activó |799| `hook_event_name` | Nombre del evento que se activó |
657 800
658Cuando se ejecuta con `--agent` o dentro de un subagente, se incluyen dos campos adicionales:801Cuando se ejecuta con `--agent` o dentro de un subagente, se incluyen dos campos adicionales:
659 802
660| Campo | Descripción |803| Campo | Descripción |
661| :----------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |804| :----------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
662| `agent_id` | Identificador único para el subagente. Presente solo cuando el hook se activa dentro de una llamada de subagente. Use esto para distinguir llamadas de hook de subagente de llamadas de hilo principal. |805| `agent_id` | Identificador único para el subagente. Presente solo cuando el hook se activa dentro de una llamada de subagente. Use esto para distinguir llamadas de hook de subagente de llamadas de hilo principal. |
663| `agent_type` | Nombre del agente (por ejemplo, `"Explore"` o `"security-reviewer"`). Presente cuando la sesión usa `--agent` o el hook se activa dentro de un subagente. Para subagentes, el tipo del subagente tiene precedencia sobre el valor `--agent` de la sesión. Para [subagentes personalizados](/docs/es/sub-agents), este es el campo `name` del frontmatter del agente, no el nombre del archivo. Para subagentes enviados por un [plugin](/docs/es/plugins), este es el identificador con alcance de plugin como `my-plugin:reviewer`, no el nombre de frontmatter desnudo. Consulte [SubagentStart](#subagentstart) para saber cómo escribir un matcher contra un nombre con alcance de plugin. |806| `agent_type` | Nombre del agente (por ejemplo, `"Explore"` o `"security-reviewer"`). Presente cuando la sesión usa `--agent` o el hook se activa dentro de un subagente. Para subagentes, el tipo del subagente tiene precedencia sobre el valor `--agent` de la sesión. Consulte [SubagentStart](#subagentstart) para los valores que los subagentes personalizados y de plugin reportan y cómo escribir un matcher contra un nombre con alcance de plugin. |
807
808Solo los hooks [`SessionStart`](#sessionstart) pueden recibir un campo `model`, y Claude Code no siempre lo incluye. Los hooks [`PreModelSwitch`](#premodelswitch) y [`PostModelSwitch`](#postmodelswitch) reciben `from_model` y `to_model` en su lugar, así que use un hook PostModelSwitch para seguir el modelo mientras cambia durante una sesión.
809
810No hay variable de entorno `$CLAUDE_MODEL`. El hook puede leer `$ANTHROPIC_MODEL` si lo establece en su shell, pero ese valor no cambia cuando cambia de modelos con `/model` durante una sesión.
664 811
665Solo los hooks [`SessionStart`](#sessionstart) pueden recibir un campo `model`, y no se garantiza que esté presente. No hay variable de entorno `$CLAUDE_MODEL`. Un proceso de hook hereda el entorno principal, por lo que puede leer `$ANTHROPIC_MODEL` si lo establece en su shell, pero ese valor no cambia cuando cambia de modelos con `/model` durante una sesión. Un conjunto de variables no se hereda: Claude Code [elimina variables exportadoras `OTEL_*` de cada subproceso que genera](/docs/es/monitoring-usage#administrator-configuration), incluyendo hooks.812Un proceso de hook hereda el entorno principal, aparte de las variables exportadoras `OTEL_*` que Claude Code [elimina de cada subproceso que genera](/docs/es/monitoring-usage#administrator-configuration) y, cuando [`CLAUDE_CODE_SUBPROCESS_ENV_SCRUB`](/docs/es/env-vars#variables) se establece en `1`, las variables que elimina.
666 813
667Por ejemplo, un hook `PreToolUse` para un comando Bash recibe esto en stdin:814Por ejemplo, un hook `PreToolUse` para un comando Bash recibe esto en stdin:
668 815
672 "prompt_id": "550e8400-e29b-41d4-a716-446655440000",819 "prompt_id": "550e8400-e29b-41d4-a716-446655440000",
673 "transcript_path": "/home/user/.claude/projects/.../transcript.jsonl",820 "transcript_path": "/home/user/.claude/projects/.../transcript.jsonl",
674 "cwd": "/home/user/my-project",821 "cwd": "/home/user/my-project",
822 "scratchpad_dir": "/tmp/claude-1000/-home-user-my-project/abc123/scratchpad",
675 "permission_mode": "default",823 "permission_mode": "default",
676 "hook_event_name": "PreToolUse",824 "hook_event_name": "PreToolUse",
677 "tool_name": "Bash",825 "tool_name": "Bash",
678 "tool_input": {826 "tool_input": {
679 "command": "npm test"827 "command": "npm test",
680 }828 "description": "Run test suite",
829 "timeout": 120000,
830 "run_in_background": false
831 },
832 "tool_use_id": "toolu_01ABC123..."
681}833}
682```834```
683 835
684Los campos `tool_name` y `tool_input` son específicos del evento. Cada sección [hook event](#hook-events) documenta los campos adicionales para ese evento.836Los campos `tool_name`, `tool_input` y `tool_use_id` son específicos del evento. Cada sección [hook event](#hook-events) documenta los campos adicionales para ese evento.
685 837
686<h3 id="exit-code-output">838<h3 id="exit-code-output">
687 Salida de código de salida839 Salida de código de salida
688</h3>840</h3>
689 841
690El código de salida de su comando de hook le dice a Claude Code si la acción debe proceder, ser bloqueada o ser ignorada.842El código de salida de su comando de hook le dice a Claude Code si la acción debe proceder, ser bloqueada o ser ignorada. El código de salida no actúa solo. Claude Code lee campos [JSON output](#json-output) desde stdout en cada código de salida, no solo en 0, y para eventos que usan el modelo de decisión estándar, un objeto analizado que pasa la validación del esquema tiene efecto junto con el código. El bloqueo de Exit 2 es el único resultado que JSON no puede anular.
691 843
692**Exit 0** significa éxito. Claude Code analiza stdout para [campos de salida JSON](#json-output). La salida JSON solo se procesa en exit 0. Para la mayoría de eventos, stdout se escribe en el registro de depuración pero no se muestra en la transcripción. Las excepciones son `UserPromptSubmit`, `UserPromptExpansion` y `SessionStart`, donde stdout se agrega como contexto que Claude puede ver y actuar.844Dos tablas poseen las excepciones por evento: [Exit code 2 behavior per event](#exit-code-2-behavior-per-event) dice qué hacen los códigos de salida para cada evento, y [Decision control](#decision-control) dice qué campos de decisión honra cada evento. Los campos universales como `systemMessage` funcionan en la mayoría de eventos y se enumeran en la tabla [JSON output](#json-output).
693 845
694**Exit 2** significa un error de bloqueo. Claude Code ignora stdout y cualquier JSON en él. En su lugar, el texto de stderr se devuelve a Claude como un mensaje de error. El efecto depende del evento: `PreToolUse` bloquea la llamada a herramienta, `UserPromptSubmit` rechaza el prompt, y así sucesivamente. Consulte [exit code 2 behavior](#exit-code-2-behavior-per-event) para la lista completa.846<h4 id="exit-code-0">
847 Exit code 0
848</h4>
849
850Exit 0 significa éxito, y es el código de salida previsto cuando imprime JSON para control estructurado.
851
852Para la mayoría de eventos, Claude Code escribe stdout en el registro de depuración y no lo muestra en la transcripción. Las excepciones son `UserPromptSubmit`, `UserPromptExpansion`, `SessionStart` y `PostModelSwitch`, donde Claude Code agrega stdout de texto plano como contexto que Claude puede ver y actuar.
853
854Si Claude Code lee su stdout como [JSON output](#json-output) o como texto plano depende de cómo comienza y termina, ignorando espacios en blanco circundantes:
695 855
696**Cualquier otro código de salida** es un error sin bloqueo para la mayoría de eventos de hook. La transcripción muestra un aviso `<hook name> hook error` seguido de la primera línea de stderr, para que pueda identificar la causa sin `--debug`. La ejecución continúa y el stderr completo se escribe en el registro de depuración.856* **Comienza con `{` y termina con `}`**: Claude Code lo analiza como JSON. Cuando la salida son dos o más líneas que cada una se analiza como JSON por su cuenta, y ninguna línea es un objeto [JSON output](#json-output) que establece un campo, Claude Code trata toda la salida como texto plano. Cuando una de esas líneas sí establece un campo, toda la salida es un fallo de análisis, descrito a continuación.
857* **Comienza con `{` pero no termina con `}`**: Claude Code lo trata como texto plano.
858* **Comienza con cualquier otra cosa**: Claude Code lo trata como texto plano, una matriz JSON o una cadena JSON entrecomillada incluida.
697 859
698Por ejemplo, un script de comando de hook que bloquea comandos Bash peligrosos:860Para eventos que usan el modelo de decisión estándar, exit 0 con un objeto analizado que falla la validación del esquema es un error sin bloqueo: la acción procede, y la transcripción muestra un aviso `<hook name> hook error` con el mensaje de validación. Lo mismo sucede en cualquier código de salida que no sea 2, mientras que [exit 2 aún bloquea](#exit-code-2).
861
862Para eventos que usan el modelo de decisión estándar, cuando Claude Code intenta analizar su stdout como JSON y no puede, reporta un error sin bloqueo en cada código de salida que no sea 2. La transcripción muestra un aviso `<hook name> hook error` con el mensaje de análisis. En los eventos que agregan stdout de texto plano como contexto, Claude Code no agrega el texto. Antes de v2.1.248, Claude Code trataba ese stdout como texto plano.
863
864Stderr de un hook que sale 0 va solo al registro de depuración, nunca a la transcripción, y Claude nunca lo ve. Para leerlo usted mismo, habilite [debug logging](#debug-hooks). Para mostrar una advertencia a Claude desde un hook `PostToolUse` o `PostToolUseFailure`, salga 2 en su lugar para que [Claude vea stderr](#exit-code-2-behavior-per-event) aunque la herramienta ya se haya ejecutado.
865
866<h4 id="exit-code-2">
867 Exit code 2
868</h4>
869
870Exit 2 significa un error de bloqueo. En [eventos que pueden bloquear](#exit-code-2-behavior-per-event), exit 2 bloquea independientemente de si imprime JSON: incluso un `permissionDecision` JSON de `"allow"` no puede anularlo. Claude Code aún lee cualquier [JSON output](#json-output) válido en stdout. En `Elicitation` y `ElicitationResult`, el `hookSpecificOutput` de un hook exit-2 se ignora.
871
872El mensaje de bloqueo es la razón de la decisión de bloqueo de su JSON cuando hace una, y su texto stderr en caso contrario. Lo que el bloqueo hace varía según el evento: `PreToolUse` bloquea la llamada a herramienta, `UserPromptSubmit` rechaza el prompt, y así sucesivamente. [Exit code 2 behavior per event](#exit-code-2-behavior-per-event) enumera el efecto para cada evento, y cada sección de evento dice dónde va el mensaje.
873
874Un hook que sale 2 mientras imprime JSON que falla la validación del esquema [JSON output](#json-output) aún bloquea: Claude Code usa stderr como la razón de bloqueo y registra el fallo de validación en el registro de depuración. Antes de v2.1.214, Claude Code trataba esa combinación como un error sin bloqueo y la acción procedía.
875
876Este script bloquea comandos `rm` saliendo 2 y deja cada otro comando al flujo de permiso normal:
699 877
700```bash theme={null}878```bash theme={null}
701#!/bin/bash879#!/bin/bash
702# Lee entrada JSON desde stdin, verifica el comando880# Lee entrada JSON desde stdin, verifica el comando
703command=$(jq -r '.tool_input.command' < /dev/stdin)881input=$(cat)
882command=$(jq -r '.tool_input.command' <<<"$input")
704 883
705if [[ "$command" == rm* ]]; then884if [[ "$command" == rm* ]]; then
706 echo "Blocked: rm commands are not allowed" >&2885 echo "Blocked: rm commands are not allowed" >&2
710exit 0 # No decision: the normal permission flow applies889exit 0 # No decision: the normal permission flow applies
711```890```
712 891
892<h4 id="other-exit-codes">
893 Otros códigos de salida
894</h4>
895
896Cualquier otro código de salida no bloquea por su cuenta para la mayoría de eventos de hook. Lo que sucede depende de su stdout:
897
898* Con un objeto analizado que pasa la validación del esquema, para eventos que usan el modelo de decisión estándar, Claude Code ignora el código de salida y solo el JSON decide el resultado:
899 * Cada campo que el evento admite se honra, incluyendo `permissionDecision`, `additionalContext`, `updatedInput` y `systemMessage`, y el hook no se reporta como un error.
900 * [Decision control](#decision-control) enumera los campos de decisión por evento; campos universales como `systemMessage` siguen la tabla [JSON output](#json-output).
901* Con un objeto analizado que falla la validación del esquema, para eventos que usan el modelo de decisión estándar, es el mismo error sin bloqueo que [en exit 0](#exit-code-0): la acción procede, y el aviso `<hook name> hook error` lleva el mensaje de validación.
902* Con stdout que Claude Code [intenta analizar como JSON](#exit-code-0) y no puede, Claude Code reporta el mismo error sin bloqueo que en exit 0 para eventos que usan el modelo de decisión estándar. La acción procede, y el aviso lleva el mensaje de análisis.
903* Con stdout que Claude Code [trata como texto plano](#exit-code-0), o con stdout vacío, es un error sin bloqueo para la mayoría de eventos de hook: la acción procede, y la transcripción muestra un aviso `<hook name> hook error` seguido de la primera línea de stderr, prefijado con `Failed with non-blocking status code:`. Para capturar el stderr completo, habilite [debug logging](#debug-hooks).
904
905Los eventos fuera del modelo de decisión estándar mantienen sus propias filas en la [tabla por evento](#exit-code-2-behavior-per-event): `WorktreeCreate` falla la creación en cualquier salida distinta de cero sin importar lo que diga su JSON, y eventos que descartan la salida del hook completamente, como `StopFailure`, ignoran su JSON en cada código de salida, aparte de campos de efecto secundario como `terminalSequence`, que aún se activan.
906
907Un hook que no puede iniciarse cae en el mismo cubo sin bloqueo. Cuando la ruta del script no existe o no es ejecutable, el shell sale con un código como 127 y ve el mismo aviso con el mensaje del intérprete, por ejemplo `Failed with non-blocking status code: /bin/sh: /path/to/hook.sh: No such file or directory`. Para la mayoría de eventos de hook, la acción procede. Cuando configura un hook de política, observe este aviso en su primera ejecución: una ruta mal escrita en `settings.json` deja la puerta silenciosamente deshabilitada.
908
713<Warning>909<Warning>
714 Para la mayoría de eventos de hook, solo el código de salida 2 bloquea la acción. Claude Code trata el código de salida 1 como un error sin bloqueo y procede con la acción, aunque 1 es el código de fallo convencional de Unix. Si su hook está destinado a aplicar una política, use `exit 2`. La excepción es `WorktreeCreate`, donde cualquier código de salida distinto de cero aborta la creación de worktree.910 Para la mayoría de eventos de hook, el código de salida 2 es el único código de salida que bloquea solo a través del código. Sin JSON válido en stdout, Claude Code trata el código de salida 1 como un error sin bloqueo y procede con la acción, aunque 1 es el código de fallo convencional de Unix. Si su hook está destinado a aplicar una política, use `exit 2`. Los eventos de worktree difieren: cualquier código de salida distinto de cero de `WorktreeCreate` aborta la creación de worktree, y cualquier código de salida distinto de cero de `WorktreeRemove` hace que la eliminación de worktree falle si el directorio aún existe después.
715</Warning>911</Warning>
716 912
913<h4 id="timeouts">
914 Tiempos de espera
915</h4>
916
917Aparte de un hook de comando que ejecuta con [`async: true`](#run-hooks-in-the-background), Claude Code cancela un hook `command`, `http` o `mcp_tool` que alcanza su [`timeout`](#common-fields), descartando la salida del hook, por lo que en la mayoría de eventos un hook agotado no renderiza decisión.
918
919En [`PreModelSwitch`](#premodelswitch), un hook cancelado en su timeout bloquea el cambio de modelo. En `PreToolUse`, las dos familias de hooks difieren:
920
921* Un hook `command`, `http` o `mcp_tool` agotado no bloquea la llamada a herramienta. La llamada continúa a través del [flujo de permiso](/docs/es/permissions) normal, así que no cuente con un hook estancado para actuar como puerta.
922* Un hook de callback [Agent SDK](/docs/es/agent-sdk/hooks) que excede su timeout [bloquea la llamada a herramienta](#pretooluse).
923
717<h4 id="exit-code-2-behavior-per-event">924<h4 id="exit-code-2-behavior-per-event">
718 Comportamiento del código de salida 2 por evento925 Comportamiento del código de salida 2 por evento
719</h4>926</h4>
720 927
721El código de salida 2 es la forma en que un hook señala "detente, no hagas esto". El efecto depende del evento, porque algunos eventos representan acciones que pueden bloquearse (como una llamada a herramienta que aún no ha sucedido) y otros representan cosas que ya sucedieron o no pueden prevenirse.928Exit code 2 es la forma en que un hook señala "detente, no hagas esto". El efecto depende del evento, porque algunos eventos representan acciones que pueden bloquearse (como una llamada a herramienta que aún no ha sucedido) y otros representan cosas que ya sucedieron o no pueden prevenirse.
722 929
723| Evento de hook | ¿Puede bloquear? | Qué sucede en exit 2 |930| Evento de hook | ¿Puede bloquear? | Qué sucede en exit 2 |
724| :-------------------- | :--------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------- |931| :-------------------- | :--------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
725| `PreToolUse` | Sí | Bloquea la llamada a herramienta |932| `PreToolUse` | Sí | Bloquea la llamada a herramienta |
726| `PermissionRequest` | Sí | Deniega el permiso |933| `PermissionRequest` | No | El código de salida 2 no se honra para este evento y el flujo de permiso procede sin cambios. Deniegue a través del objeto [`decision`](#permissionrequest-decision-control) en su lugar |
727| `UserPromptSubmit` | Sí | Bloquea el procesamiento del prompt y borra el prompt |934| `UserPromptSubmit` | Sí | Bloquea el procesamiento del prompt y borra el prompt |
728| `UserPromptExpansion` | Sí | Bloquea la expansión |935| `UserPromptExpansion` | Sí | Bloquea la expansión |
729| `Stop` | Sí | Evita que Claude se detenga, continúa la conversación |936| `Stop` | Sí | Evita que Claude se detenga, continúa la conversación |
732| `TaskCreated` | Sí | Revierte la creación de la tarea |939| `TaskCreated` | Sí | Revierte la creación de la tarea |
733| `TaskCompleted` | Sí | Evita que la tarea se marque como completada |940| `TaskCompleted` | Sí | Evita que la tarea se marque como completada |
734| `ConfigChange` | Sí | Bloquea que el cambio de configuración tenga efecto (excepto `policy_settings`) |941| `ConfigChange` | Sí | Bloquea que el cambio de configuración tenga efecto (excepto `policy_settings`) |
735| `StopFailure` | No | La salida y el código de salida se ignoran |942| `StopFailure` | No | La salida y el código de salida se ignoran, excepto `terminalSequence` |
736| `PostToolUse` | No | Muestra stderr a Claude; la herramienta ya se ejecutó |943| `PostToolUse` | No | Muestra stderr a Claude; la herramienta ya se ejecutó |
737| `PostToolUseFailure` | No | Muestra stderr a Claude; la herramienta ya falló |944| `PostToolUseFailure` | No | Muestra stderr a Claude; la herramienta ya falló |
738| `PostToolBatch` | Sí | Detiene el bucle agentico antes de la siguiente llamada al modelo |945| `PostToolBatch` | Sí | Detiene el bucle agentico antes de la siguiente llamada al modelo |
739| `PermissionDenied` | No | El código de salida y stderr se ignoran porque la denegación ya ocurrió. Use JSON `hookSpecificOutput.retry: true` para decirle al modelo que puede reintentar |946| `PermissionDenied` | No | El código de salida y stderr se ignoran porque la denegación ya ocurrió. Use JSON `hookSpecificOutput.retry: true` para decirle al modelo que puede reintentar; Claude Code ignora `retry: true` para [denegaciones sin veredicto](#permissiondenied-decision-control) |
740| `Notification` | No | Muestra stderr solo al usuario |947| `Notification` | No | El código de salida y stderr se ignoran |
741| `SubagentStart` | No | Muestra stderr solo al usuario |948| `SubagentStart` | No | Muestra stderr solo al usuario |
742| `SessionStart` | No | Muestra stderr solo al usuario |949| `SessionStart` | No | Muestra stderr solo al usuario |
743| `Setup` | No | Muestra stderr solo al usuario |950| `Setup` | No | El código de salida y stderr se ignoran |
744| `SessionEnd` | No | Muestra stderr solo al usuario |951| `SessionEnd` | No | Muestra stderr solo al usuario |
745| `CwdChanged` | No | Muestra stderr solo al usuario |952| `CwdChanged` | No | Muestra stderr solo al usuario |
953| `DirectoryAdded` | No | Stderr va al registro de depuración; el directorio ya está agregado |
746| `FileChanged` | No | Muestra stderr solo al usuario |954| `FileChanged` | No | Muestra stderr solo al usuario |
747| `PreCompact` | Sí | Bloquea la compactación |955| `PreCompact` | Sí | Bloquea la compactación |
748| `PostCompact` | No | Muestra stderr solo al usuario |956| `PostCompact` | No | Muestra stderr solo al usuario |
957| `PreModelSwitch` | Sí | Bloquea el cambio de modelo y muestra stderr al usuario |
958| `PostModelSwitch` | No | Muestra stderr solo al usuario; el modelo ya cambió |
749| `Elicitation` | Sí | Deniega la elicitación |959| `Elicitation` | Sí | Deniega la elicitación |
750| `ElicitationResult` | Sí | Bloquea la respuesta (la acción se convierte en decline) |960| `ElicitationResult` | Sí | Bloquea la respuesta (la acción se convierte en decline) |
751| `WorktreeCreate` | Sí | Cualquier código de salida distinto de cero causa que la creación de worktree falle |961| `WorktreeCreate` | Sí | Cualquier código de salida distinto de cero causa que la creación de worktree falle |
752| `WorktreeRemove` | No | Los fallos se registran solo en modo de depuración |962| `WorktreeRemove` | Sí | Cualquier código de salida distinto de cero causa que la eliminación de worktree falle si el directorio aún existe después. Consulte [WorktreeRemove](#worktreeremove) para saber qué sucede con el directorio |
753| `InstructionsLoaded` | No | El código de salida se ignora |963| `InstructionsLoaded` | No | El código de salida se ignora |
754| `MessageDisplay` | No | Se muestra el texto original |964| `MessageDisplay` | No | Se muestra el texto original |
755 965
756Para `SessionStart`, `Setup` y `SubagentStart`, el stderr del código de salida 2 se renderiza en la transcripción como un aviso `<hook name> hook error`, de la misma manera que un [error sin bloqueo](#exit-code-output). Claude no lo ve, y la sesión o subagente procede. Para `SubagentStart`, el aviso aparece en la propia transcripción del subagente, no en la conversación principal.966Para `SessionStart`, `SubagentStart` y `PostModelSwitch`, Claude Code renderiza el stderr del código de salida 2 en la transcripción como un aviso `<hook name> hook error`, de la misma manera que renderiza un [error sin bloqueo](#exit-code-output). Claude no lo ve, y la sesión o subagente procede. Para `SubagentStart`, el aviso aparece en la propia transcripción del subagente, no en la conversación principal.
757
758A partir de Claude Code v2.1.199, `SessionStart`, `Setup` y `SubagentStart` muestran stderr del código de salida 2 en la transcripción. Las versiones anteriores lo escribían solo en el registro de depuración.
759 967
760<h3 id="http-response-handling">968<h3 id="http-response-handling">
761 Manejo de respuesta HTTP969 Manejo de respuesta HTTP
762</h3>970</h3>
763 971
764Los hooks HTTP usan códigos de estado HTTP y cuerpos de respuesta en lugar de códigos de salida y stdout:972Los hooks HTTP usan códigos de estado HTTP y cuerpos de respuesta en lugar de códigos de salida y stdout. Los resultados a continuación se aplican a la mayoría de eventos; un evento con su propio contrato de fallo en la [tabla por evento](#exit-code-2-behavior-per-event), como `WorktreeCreate`, aplica ese contrato a un hook HTTP fallido también:
765 973
766* **2xx con un cuerpo vacío**: éxito, equivalente a código de salida 0 sin salida974* **2xx con un cuerpo vacío**: éxito, equivalente a código de salida 0 sin salida
767* **2xx con un cuerpo de texto plano**: éxito, el texto se agrega como contexto975* **2xx con un cuerpo de objeto JSON**: analizado usando el mismo esquema [JSON output](#json-output) que los hooks de comando. Un cuerpo que falla la validación del esquema es un error sin bloqueo
768* **2xx con un cuerpo JSON**: éxito, analizado usando el mismo esquema [JSON output](#json-output) que los hooks de comando976* **2xx con cualquier otro cuerpo, como texto plano**: error sin bloqueo, manejado igual que un estado que no es 2xx. Claude Code no agrega el texto al contexto de Claude
769* **Estado que no es 2xx**: error sin bloqueo, la ejecución continúa977* **Estado que no es 2xx**: error sin bloqueo, la ejecución continúa
770* **Fallo de conexión o tiempo de espera agotado**: error sin bloqueo, la ejecución continúa978* **Fallo de conexión**: error sin bloqueo, la ejecución continúa
979* **Tiempo de espera**: el hook se cancela, como se describe bajo [Timeouts](#timeouts)
771 980
772A diferencia de los hooks de comando, los hooks HTTP no pueden señalar un error de bloqueo solo a través de códigos de estado. Para bloquear una llamada a herramienta o denegar un permiso, devuelva una respuesta 2xx con un cuerpo JSON que contenga los campos de decisión apropiados.981A diferencia de los hooks de comando, los hooks HTTP no pueden señalar un error de bloqueo solo a través de códigos de estado. Para bloquear una llamada a herramienta o denegar un permiso, devuelva una respuesta 2xx con un cuerpo JSON que contenga los campos de decisión apropiados.
773 982
775 Salida JSON984 Salida JSON
776</h3>985</h3>
777 986
778Los códigos de salida le permiten bloquear o permanecer en silencio, pero la salida JSON le da un control más granular. En lugar de salir con código 2 para bloquear, salga 0 e imprima un objeto JSON en stdout. Claude Code lee campos específicos de ese JSON para controlar el comportamiento, incluyendo [decision control](#decision-control) para bloquear, permitir o escalar al usuario.987Los códigos de salida solo le permiten bloquear o permanecer en silencio, pero la salida JSON le da un control más granular. En lugar de salir con código 2 para bloquear, salga 0 e imprima un objeto JSON en stdout. Claude Code lee campos específicos de ese JSON para controlar el comportamiento, incluyendo [decision control](#decision-control) para bloquear, permitir o escalar al usuario.
779 988
780<Note>989<Note>
781 Debe elegir un enfoque por hook, no ambos: use códigos de salida solos para señalizar, o salga 0 e imprima JSON para control estructurado. Claude Code solo procesa JSON en exit 0. Si sale 2, cualquier JSON se ignora.990 Elija un enfoque por hook: use códigos de salida solos para señalizar, o salga 0 e imprima JSON para control estructurado. Si los mezcla, exit 2 mantiene su [efecto de bloqueo](#exit-code-2-behavior-per-event), y Claude Code aún lee los campos JSON, con la excepción de elicitación única anotada bajo [Exit code 2](#exit-code-2).
782</Note>991</Note>
783 992
784El stdout de su hook debe contener solo el objeto JSON. Si su perfil de shell imprime texto al inicio, puede interferir con el análisis JSON. Consulte [JSON validation failed](/docs/es/hooks-guide#json-validation-failed) en la guía de solución de problemas.993El stdout de su hook debe contener solo el objeto JSON. Si su perfil de shell imprime texto al inicio, puede interferir con el análisis JSON. Consulte [Hook JSON has no effect](/docs/es/hooks-guide#hook-json-has-no-effect) en la guía de solución de problemas.
785 994
786Las cadenas de salida de hook, incluyendo `additionalContext`, `systemMessage` y stdout plano, están limitadas a 10.000 caracteres. La salida que excede este límite se guarda en un archivo y se reemplaza con una vista previa y ruta de archivo, de la misma manera que se manejan los resultados de herramientas grandes.995Las cadenas de salida de hook, incluyendo `additionalContext`, `systemMessage` e `initialUserMessage`, y su stdout plano, están limitadas a 10.000 caracteres:
996
997* **Alcance**: Claude Code mide cada cadena por su cuenta, incluso cuando varios hooks se ejecutan para el mismo evento. Para salida JSON, cada campo se mide por separado; stdout plano se mide en su totalidad.
998* **Sobre el límite**: Claude Code guarda la salida en un archivo en el directorio de sesión y la reemplaza con la ruta del archivo y una vista previa de hasta los primeros 2.000 caracteres. Un resultado de Bash válido grande se maneja de la misma manera, descrito bajo [Output limits](/docs/es/tools-reference#output-limits). A diferencia de ese techo de Bash, este límite no tiene configuración o variable de entorno para aumentarlo.
999* **Lectura del archivo**: Claude Code no le pide a Claude que lea el archivo, así que mantenga cualquier cosa que Claude siempre deba ver dentro del límite.
787 1000
788El objeto JSON admite tres tipos de campos:1001El objeto JSON admite tres tipos de campos:
789 1002
790* **Campos universales** como `continue` funcionan en todos los eventos. Estos se enumeran en la tabla a continuación.1003* **Campos universales** como `continue` se enumeran en la tabla a continuación. Cada evento los acepta, pero algunos eventos los descartan o entregan `systemMessage` en otro lugar que no sea la transcripción. Cada sección de evento lo indica. `terminalSequence` funciona en esos eventos también, con las excepciones enumeradas bajo [Emit terminal notifications](#emit-terminal-notifications).
791* **`decision` y `reason` de nivel superior** son utilizados por algunos eventos para bloquear o proporcionar retroalimentación.1004* **`decision` y `reason` de nivel superior** son utilizados por algunos eventos para bloquear o proporcionar retroalimentación.
792* **`hookSpecificOutput`** es un objeto anidado para eventos que necesitan control más rico. Requiere un campo `hookEventName` establecido en el nombre del evento.1005* **`hookSpecificOutput`** es un objeto anidado para eventos que necesitan control más rico. Requiere un campo `hookEventName` establecido en el nombre del evento.
793 1006
794| Campo | Predeterminado | Descripción |1007| Campo | Predeterminado | Descripción |
795| :----------------- | :------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |1008| :----------------- | :------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
796| `continue` | `true` | Si es `false`, Claude detiene el procesamiento completamente después de que se ejecuta el hook. Tiene precedencia sobre cualquier campo de decisión específico del evento |1009| `continue` | `true` | Si es `false`, Claude detiene el procesamiento completamente después de que se ejecuta el hook. Tiene precedencia sobre cualquier campo de decisión específico del evento |
797| `stopReason` | ninguno | Mensaje mostrado al usuario cuando `continue` es `false`. No se muestra a Claude |1010| `stopReason` | ninguno | Mensaje mostrado al usuario cuando `continue` es `false`. Se queda en la conversación, por lo que Claude lo ve si la conversación continúa |
798| `suppressOutput` | `false` | Si es `true`, oculta stdout del hook de la transcripción. Stdout aún aparece en el registro de depuración |1011| `suppressOutput` | `false` | No tiene efecto: Claude Code acepta el campo pero no actúa sobre él. El stdout de un hook exitoso nunca se muestra en la transcripción y se registra en el registro de depuración |
799| `systemMessage` | ninguno | Mensaje de advertencia mostrado al usuario |1012| `systemMessage` | ninguno | Mensaje de advertencia mostrado al usuario. En [Agent SDK](/docs/es/agent-sdk/overview) y salida [`--output-format stream-json`](/docs/es/headless), puede llegar como un [`SDKInformationalMessage`](/docs/es/agent-sdk/typescript#sdkinformationalmessage) |
800| `terminalSequence` | ninguno | Una secuencia de escape de terminal para que Claude Code emita en su nombre, como una notificación de escritorio, título de ventana o campana. Restringido a OSC `0`/`1`/`2`/`9`/`99`/`777` y BEL. Si el valor contiene algo fuera de la lista de permitidos, el campo se ignora. Use esto en lugar de escribir en `/dev/tty`, que no está disponible para hooks |1013| `terminalSequence` | ninguno | Una secuencia de escape de terminal para que Claude Code emita en su nombre, como una notificación de escritorio, título de ventana o campana. Restringido a OSC `0`/`1`/`2`/`9`/`99`/`777` y BEL. Si el valor contiene algo fuera de la lista de permitidos, el campo se ignora. Use esto en lugar de escribir en `/dev/tty`, que no está disponible para hooks |
801 1014
802Para detener Claude completamente independientemente del tipo de evento:1015Para detener Claude completamente:
803 1016
804```json theme={null}1017```json theme={null}
805{ "continue": false, "stopReason": "Build failed, fix errors before continuing" }1018{ "continue": false, "stopReason": "Build failed, fix errors before continuing" }
806```1019```
807 1020
1021Para hooks `PreToolUse` y `PostToolUse`, la parada se aplica incluso cuando la llamada a herramienta falla o se completa mientras Claude aún está transmitiendo una respuesta.
1022
808<h4 id="emit-terminal-notifications">1023<h4 id="emit-terminal-notifications">
809 Emitir notificaciones de terminal1024 Emitir notificaciones de terminal
810</h4>1025</h4>
811 1026
812El campo `terminalSequence` requiere Claude Code v2.1.141 o posterior.
813
814Los hooks se ejecutan sin una terminal de control, por lo que escribir secuencias de escape directamente en `/dev/tty` falla. En su lugar, devuelva la secuencia de escape en el campo `terminalSequence` y Claude Code la emite por usted a través de su propia ruta de escritura de terminal. Esto es libre de carreras, funciona dentro de tmux y GNU screen, y funciona en Windows donde no hay `/dev/tty`.1027Los hooks se ejecutan sin una terminal de control, por lo que escribir secuencias de escape directamente en `/dev/tty` falla. En su lugar, devuelva la secuencia de escape en el campo `terminalSequence` y Claude Code la emite por usted a través de su propia ruta de escritura de terminal. Esto es libre de carreras, funciona dentro de tmux y GNU screen, y funciona en Windows donde no hay `/dev/tty`.
815 1028
816El campo acepta una cadena de una o más secuencias de escape permitidas:1029El campo acepta una cadena de una o más secuencias de escape permitidas:
823 1036
824Las secuencias pueden terminarse con BEL o con ST. Cualquier cosa fuera de la lista de permitidos, incluyendo secuencias de cursor y color CSI, secuencias de paleta OSC, hipervínculos OSC 8, escrituras de portapapeles OSC 52 y OSC 1337, se rechaza y el campo se ignora.1037Las secuencias pueden terminarse con BEL o con ST. Cualquier cosa fuera de la lista de permitidos, incluyendo secuencias de cursor y color CSI, secuencias de paleta OSC, hipervínculos OSC 8, escrituras de portapapeles OSC 52 y OSC 1337, se rechaza y el campo se ignora.
825 1038
1039Claude Code escribe la secuencia en sí cuando procesa la salida de su hook, por lo que el campo funciona en eventos que descartan `systemMessage` y `continue`, como `Notification` y `StopFailure`. Tiene dos límites:
1040
1041* Claude Code escribe la secuencia solo en una sesión interactiva, y solo mientras su interfaz está en pantalla. En modo no interactivo con la bandera `-p` y en Agent SDK, ignora el campo.
1042* Un hook de comando `WorktreeCreate` no puede devolver JSON, porque Claude Code lee su stdout como la ruta de worktree. Un hook HTTP `WorktreeCreate` devuelve JSON y puede incluir el campo.
1043
826El ejemplo a continuación dispara una notificación de escritorio desde un hook `Notification`. La secuencia de escape se construye con escapes octales `printf` para que los bytes de control nunca aparezcan en la línea de comandos del shell, y `jq -n --arg` construye la salida JSON para que las comillas, barras invertidas y saltos de línea en el mensaje de notificación se escapen correctamente:1044El ejemplo a continuación dispara una notificación de escritorio desde un hook `Notification`. La secuencia de escape se construye con escapes octales `printf` para que los bytes de control nunca aparezcan en la línea de comandos del shell, y `jq -n --arg` construye la salida JSON para que las comillas, barras invertidas y saltos de línea en el mensaje de notificación se escapen correctamente:
827 1045
828```bash theme={null}1046```bash theme={null}
829#!/bin/bash1047#!/bin/bash
830# Hook de notificación: ping al escritorio cuando Claude Code necesita atención.1048# Hook de notificación: ping al escritorio cuando Claude Code necesita atención.
831input=$(cat)1049input=$(cat)
832title="Claude Code'1050title="Claude Code"
833body=$(jq -r '.message // 'Needs your attention"' <<<"$input")1051body=$(jq -r '.message // "Needs your attention"' <<<"$input")
834seq=$(printf '\033]777;notify;%s;%s\007' "$title" "$body")1052seq=$(printf '\033]777;notify;%s;%s\007' "$title" "$body")
835jq -nc --arg seq "$seq" '{terminalSequence: $seq}'1053jq -nc --arg seq "$seq" '{terminalSequence: $seq}'
836```1054```
837 1055
838La forma `{ "terminalSequence": "..." }` es la misma desde cualquier shell o lenguaje. En Windows, construya la cadena de escape en PowerShell o un script y emita el mismo objeto JSON.1056La forma `{ "terminalSequence": "..." }` es la misma desde cualquier shell o lenguaje.
839
840<Note>
841 `terminalSequence` es el reemplazo compatible para hooks que anteriormente escribían secuencias de escape directamente en `/dev/tty`. La lista de permitidos está restringida a secuencias que no pueden mover el cursor o alterar colores, por lo que un hook nunca puede corromper un prompt en pantalla.
842</Note>
843 1057
844<h4 id="add-context-for-claude">1058<h4 id="add-context-for-claude">
845 Agregar contexto para Claude1059 Agregar contexto para Claude
860 1074
861Dónde aparece el recordatorio depende del evento:1075Dónde aparece el recordatorio depende del evento:
862 1076
863* [SessionStart](#sessionstart), [Setup](#setup) y [SubagentStart](#subagentstart): al inicio de la conversación, antes del primer prompt1077* [SessionStart](#sessionstart) y [SubagentStart](#subagentstart): al inicio de la conversación, antes del primer prompt
864* [UserPromptSubmit](#userpromptsubmit) y [UserPromptExpansion](#userpromptexpansion): junto al prompt enviado1078* [UserPromptSubmit](#userpromptsubmit) y [UserPromptExpansion](#userpromptexpansion): junto al prompt enviado
865* [PreToolUse](#pretooluse), [PostToolUse](#posttooluse), [PostToolUseFailure](#posttoolusefailure) y [PostToolBatch](#posttoolbatch): junto al resultado de la herramienta1079* [PreToolUse](#pretooluse), [PostToolUse](#posttooluse), [PostToolUseFailure](#posttoolusefailure) y [PostToolBatch](#posttoolbatch): junto al resultado de la herramienta
866* [Stop](#stop) y [SubagentStop](#subagentstop): al final del turno. La conversación continúa para que Claude pueda actuar sobre la retroalimentación. Consulte [Stop decision control](#stop-decision-control)1080* [Stop](#stop) y [SubagentStop](#subagentstop): al final del turno. La conversación continúa para que Claude pueda actuar sobre la retroalimentación. Consulte [Stop decision control](#stop-decision-control)
1081* [PostModelSwitch](#postmodelswitch): con la siguiente solicitud después del cambio. Consulte [PostModelSwitch decision control](#postmodelswitch-decision-control) para el tiempo
1082
1083Cuando varios hooks devuelven `additionalContext` para el mismo evento, Claude recibe todos los valores.
867 1084
868Cuando varios hooks devuelven `additionalContext` para el mismo evento, Claude recibe todos los valores. Si un valor excede 10.000 caracteres, Claude Code escribe el texto completo en un archivo en el directorio de sesión y pasa a Claude la ruta del archivo con una vista previa corta en su lugar.1085Si un valor excede 10.000 caracteres, Claude Code escribe el texto en un archivo en el directorio de sesión y pasa a Claude la ruta del archivo con una vista previa de hasta los primeros 2.000 caracteres en su lugar. Claude puede leer el archivo, pero Claude Code no se lo pide.
869 1086
870Use `additionalContext` para información que Claude debe conocer sobre el estado actual de su entorno o la operación que acaba de ejecutarse:1087Use `additionalContext` para información que Claude debe conocer sobre el estado actual de su entorno o la operación que acaba de ejecutarse:
871 1088
877 1094
878Escriba el texto como declaraciones factuales en lugar de instrucciones de sistema imperativas. Frases como "El destino de implementación es producción" o "Este repositorio usa `bun test`" se leen como información del proyecto. El texto enmarcado como comandos de sistema fuera de banda puede activar las defensas de inyección de prompts de Claude, lo que hace que Claude le muestre el texto en lugar de tratarlo como contexto.1095Escriba el texto como declaraciones factuales en lugar de instrucciones de sistema imperativas. Frases como "El destino de implementación es producción" o "Este repositorio usa `bun test`" se leen como información del proyecto. El texto enmarcado como comandos de sistema fuera de banda puede activar las defensas de inyección de prompts de Claude, lo que hace que Claude le muestre el texto en lugar de tratarlo como contexto.
879 1096
880Una vez inyectado, el texto se guarda en la transcripción de sesión. Para eventos a mitad de sesión como `PostToolUse` o `UserPromptSubmit`, reanudar con `--continue` o `--resume` reproduce el texto guardado en lugar de volver a ejecutar el hook para turnos anteriores, por lo que valores como marcas de tiempo o SHAs de commit se vuelven obsoletos al reanudar. Los hooks `SessionStart` se ejecutan nuevamente al reanudar con `source` establecido en `"resume"`, por lo que pueden actualizar su contexto.1097Claude Code guarda el texto inyectado en la transcripción de sesión. Para eventos a mitad de sesión como `PostToolUse` o `UserPromptSubmit`, cuando reanuda con `--continue` o `--resume`, Claude Code reproduce el texto guardado en lugar de volver a ejecutar el hook para turnos anteriores, por lo que valores como marcas de tiempo o SHAs de commit se vuelven obsoletos. Los hooks `SessionStart` se ejecutan nuevamente al reanudar con `source` establecido en `"resume"`, o `"fork"` si agregó `--fork-session`, por lo que pueden actualizar su contexto.
881 1098
882<h4 id="decision-control">1099<h4 id="decision-control">
883 Control de decisión1100 Control de decisión
886No todos los eventos admiten bloqueo o control de comportamiento a través de JSON. Los eventos que lo hacen cada uno usan un conjunto diferente de campos para expresar esa decisión. Use esta tabla como referencia rápida antes de escribir un hook:1103No todos los eventos admiten bloqueo o control de comportamiento a través de JSON. Los eventos que lo hacen cada uno usan un conjunto diferente de campos para expresar esa decisión. Use esta tabla como referencia rápida antes de escribir un hook:
887 1104
888| Eventos | Patrón de decisión | Campos clave |1105| Eventos | Patrón de decisión | Campos clave |
889| :---------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |1106| :---------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
890| UserPromptSubmit, UserPromptExpansion, PostToolUse, PostToolUseFailure, PostToolBatch, Stop, SubagentStop, ConfigChange, PreCompact | `decision` de nivel superior | `decision: "block"`, `reason`. Stop y SubagentStop también aceptan `hookSpecificOutput.additionalContext` para [retroalimentación sin error que continúa la conversación](#stop-decision-control) |1107| UserPromptSubmit, UserPromptExpansion, PostToolUse, PostToolUseFailure, PostToolBatch, Stop, SubagentStop, ConfigChange, PreCompact | `decision` de nivel superior | `decision: "block"`, `reason`. Stop y SubagentStop también aceptan `hookSpecificOutput.additionalContext` para [retroalimentación sin error que continúa la conversación](#stop-decision-control) |
891| TeammateIdle, TaskCreated, TaskCompleted | Código de salida o `continue: false` | El código de salida 2 bloquea la acción con retroalimentación de stderr. JSON `{"continue": false, "stopReason": "..."}` también detiene al compañero completamente, coincidiendo con el comportamiento del hook `Stop` |1108| TeammateIdle, TaskCompleted | Código de salida o `continue: false` | El código de salida 2 bloquea la acción con retroalimentación de stderr. JSON `{"continue": false, "stopReason": "..."}` también detiene al compañero completamente, coincidiendo con el comportamiento del hook `Stop`; [TaskCompleted lo ignora cuando la herramienta `TaskUpdate` activó el evento](#taskcompleted-decision-control) |
1109| TaskCreated | Código de salida o `decision` de nivel superior | El código de salida 2 o `decision: "block"` [cancela la tarea](#taskcreated-decision-control) y devuelve el mensaje a Claude. `continue: false` se ignora |
892| PreToolUse | `hookSpecificOutput` | `permissionDecision` (allow/deny/ask/defer), `permissionDecisionReason` |1110| PreToolUse | `hookSpecificOutput` | `permissionDecision` (allow/deny/ask/defer), `permissionDecisionReason` |
1111| PreModelSwitch | `hookSpecificOutput` o `decision` de nivel superior | `permissionDecision` (allow/deny/ask), `permissionDecisionReason`. `decision: "block"` también [cancela el cambio](#premodelswitch-decision-control) |
893| PermissionRequest | `hookSpecificOutput` | `decision.behavior` (allow/deny) |1112| PermissionRequest | `hookSpecificOutput` | `decision.behavior` (allow/deny) |
894| PermissionDenied | `hookSpecificOutput` | `retry: true` le dice al modelo que puede reintentar la llamada a herramienta denegada |1113| PermissionDenied | `hookSpecificOutput` | `retry: true` le dice al modelo que puede reintentar la llamada a herramienta denegada; Claude Code ignora `retry: true` para [denegaciones sin veredicto](#permissiondenied-decision-control) |
895| WorktreeCreate | ruta return | El hook de comando imprime la ruta en stdout; el hook HTTP devuelve `hookSpecificOutput.worktreePath`. El fallo del hook o la ruta faltante falla la creación |1114| WorktreeCreate | ruta return | El hook de comando imprime la ruta en stdout; el hook HTTP devuelve `hookSpecificOutput.worktreePath`. El fallo del hook o la ruta faltante falla la creación |
1115| WorktreeRemove | Código de salida | Cualquier código de salida distinto de cero hace que la eliminación falle si el directorio aún existe después. La salida JSON se descarta |
896| Elicitation | `hookSpecificOutput` | `action` (accept/decline/cancel), `content` (valores de campo de formulario para accept) |1116| Elicitation | `hookSpecificOutput` | `action` (accept/decline/cancel), `content` (valores de campo de formulario para accept) |
897| ElicitationResult | `hookSpecificOutput` | `action` (accept/decline/cancel), `content` (valores de campo de formulario override) |1117| ElicitationResult | `hookSpecificOutput` | `action` (accept/decline/cancel), `content` (valores de campo de formulario override) |
898| MessageDisplay | `hookSpecificOutput` | `displayContent` reemplaza el texto mostrado en pantalla. Solo visualización: la transcripción y lo que Claude ve mantienen el original |1118| MessageDisplay | `hookSpecificOutput` | `displayContent` reemplaza el texto mostrado en pantalla. Solo visualización: la transcripción y lo que Claude ve mantienen el original |
899| SessionStart, Setup, SubagentStart | Solo contexto | `hookSpecificOutput.additionalContext` agrega contexto para Claude. SessionStart también acepta [`initialUserMessage`, `watchPaths`, `sessionTitle` y `reloadSkills`](#sessionstart-decision-control). Sin bloqueo o control de decisión |1119| SessionStart, SubagentStart, PostModelSwitch | Solo contexto | `hookSpecificOutput.additionalContext` agrega contexto para Claude. SessionStart también acepta [`initialUserMessage`, `watchPaths`, `sessionTitle` y `reloadSkills`](#sessionstart-decision-control). Sin bloqueo o control de decisión |
900| WorktreeRemove, Notification, SessionEnd, PostCompact, InstructionsLoaded, StopFailure, CwdChanged, FileChanged | Ninguno | Sin control de decisión. Se usa para efectos secundarios como registro o limpieza |1120| Setup, Notification, SessionEnd, PostCompact, InstructionsLoaded, StopFailure, CwdChanged, DirectoryAdded, FileChanged | Ninguno | Sin control de decisión. Se usa para efectos secundarios como registro o limpieza |
901 1121
902Algunos eventos también pueden reescribir contenido en lugar de solo permitir o bloquearlo:1122Algunos eventos también pueden reescribir contenido en lugar de solo permitir o bloquearlo:
903 1123
912 1132
913<Tabs>1133<Tabs>
914 <Tab title="Decisión de nivel superior">1134 <Tab title="Decisión de nivel superior">
915 Utilizado por `UserPromptSubmit`, `UserPromptExpansion`, `PostToolUse`, `PostToolUseFailure`, `PostToolBatch`, `Stop`, `SubagentStop`, `ConfigChange` y `PreCompact`. El único valor es `"block"`. Para permitir que la acción continúe, omita `decision` de su JSON, o salga 0 sin ningún JSON en absoluto:1135 El único valor para `decision` es `"block"`. Para permitir que la acción continúe, omita `decision` de su JSON, o salga 0 sin ningún JSON en absoluto:
916 1136
917 ```json theme={null}1137 ```json theme={null}
918 {1138 {
958Para ejemplos extendidos incluyendo validación de comandos Bash, filtrado de prompts y scripts de aprobación automática, consulte [What you can automate](/docs/es/hooks-guide#what-you-can-automate) en la guía y la [implementación de referencia del validador de comandos Bash](https://github.com/anthropics/claude-code/blob/main/examples/hooks/bash_command_validator_example.py).1178Para ejemplos extendidos incluyendo validación de comandos Bash, filtrado de prompts y scripts de aprobación automática, consulte [What you can automate](/docs/es/hooks-guide#what-you-can-automate) en la guía y la [implementación de referencia del validador de comandos Bash](https://github.com/anthropics/claude-code/blob/main/examples/hooks/bash_command_validator_example.py).
959 1179
960<h2 id="hook-events">1180<h2 id="hook-events">
961 Eventos de hook1181 Eventos de hooks
962</h2>1182</h2>
963 1183
964Cada evento corresponde a un punto en el ciclo de vida de Claude Code donde los hooks pueden ejecutarse. Las secciones a continuación se ordenan para coincidir con el ciclo de vida: desde la configuración de sesión a través del bucle agentico hasta el final de la sesión. Cada sección describe cuándo se activa el evento, qué matchers admite, la entrada JSON que recibe y cómo controlar el comportamiento a través de la salida.1184Cada evento corresponde a un punto en el ciclo de vida de Claude Code donde los hooks pueden ejecutarse. Las secciones siguientes están ordenadas para coincidir con el ciclo de vida: desde la configuración de la sesión a través del bucle agéntico hasta el final de la sesión. Cada sección describe cuándo se dispara el evento, qué matchers admite, la entrada JSON que recibe y cómo controlar el comportamiento a través de la salida.
965 1185
966<h3 id="sessionstart">1186<h3 id="sessionstart">
967 SessionStart1187 SessionStart
969 1189
970Se ejecuta cuando Claude Code inicia una nueva sesión o reanuda una sesión existente. Útil para cargar contexto de desarrollo como problemas existentes o cambios recientes en su base de código, o configurar variables de entorno. Para contexto estático que no requiere un script, use [CLAUDE.md](/docs/es/memory) en su lugar.1190Se ejecuta cuando Claude Code inicia una nueva sesión o reanuda una sesión existente. Útil para cargar contexto de desarrollo como problemas existentes o cambios recientes en su base de código, o configurar variables de entorno. Para contexto estático que no requiere un script, use [CLAUDE.md](/docs/es/memory) en su lugar.
971 1191
972SessionStart se ejecuta en cada sesión, así que mantenga estos hooks rápidos. Solo se admiten hooks `type: "command"` y `type: "mcp_tool"`.1192SessionStart se ejecuta en cada sesión, así que mantenga estos hooks rápidos. Solo se admiten hooks `type: "command"` y `type: "mcp_tool"`. Consulte [Campos de hook de herramienta MCP](#mcp-tool-hook-fields) para saber cuándo se ejecutan los hooks `mcp_tool`.
973 1193
974El valor del matcher corresponde a cómo se inició la sesión:1194El valor del matcher corresponde a cómo se inició la sesión:
975 1195
976| Matcher | Cuándo se activa |1196| Matcher | Cuándo se dispara |
977| :-------- | :----------------------------------- |1197| :-------- | :------------------------------------------------------------------------------------------------------------------------------------- |
978| `startup` | Nueva sesión |1198| `startup` | Nueva sesión |
979| `resume` | `--resume`, `--continue` o `/resume` |1199| `resume` | `--resume`, `--continue`, o `/resume` |
980| `clear` | `/clear` |1200| `clear` | `/clear` |
981| `compact` | Compactación automática o manual |1201| `compact` | Compactación automática o manual |
1202| `fork` | Una nueva sesión bifurcada desde una existente: `--fork-session` con `--resume` o `--continue`, la copia de fondo `/fork`, o `/branch` |
1203
1204Antes de v2.1.214, las sesiones bifurcadas reportaban la fuente `"resume"`.
1205
1206Cuando inicia una sesión interactiva, reanuda una conversación al iniciar con `--continue` o `--resume`, o ejecuta `/clear`, los hooks SessionStart se ejecutan en segundo plano. Puede escribir de inmediato, y una conversación que reanudó aparece sin esperar a que se completen los hooks. La primera respuesta de Claude aún espera a que se completen los hooks, por lo que su contexto llega a Claude.
1207
1208Cuando cambia de conversación con `/resume` dentro de una sesión, el cambio espera a que se completen los hooks. Si ejecuta `/clear` o cambia a otra conversación mientras los hooks de fondo aún se están ejecutando, nada de lo que devuelven se aplica a la sesión.
1209
1210La misma espera se aplica al iniciar, incluida una sesión reanudada: un prompt que envía mientras los hooks SessionStart aún se están ejecutando no llega a Claude hasta que se completen.
1211
1212Durante cualquiera de estas esperas, presione `Esc` para recuperar el prompt en la entrada sin enviarlo. Los hooks continúan ejecutándose.
982 1213
983<h4 id="sessionstart-input">1214<h4 id="sessionstart-input">
984 Entrada de SessionStart1215 Entrada de SessionStart
985</h4>1216</h4>
986 1217
987Además de los [campos de entrada comunes](#common-input-fields), los hooks SessionStart reciben `source` y opcionalmente `model`, `agent_type` y `session_title`:1218Además de los [campos de entrada comunes](#common-input-fields), los hooks SessionStart reciben `source` y opcionalmente `model`, `agent_type`, y `session_title`:
988 1219
989| Campo | Descripción |1220| Campo | Descripción |
990| :-------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |1221| :-------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
991| `source` | Cómo comenzó la sesión: `"startup"` para nuevas sesiones, `"resume"` para sesiones reanudadas, `"clear"` después de `/clear` o `"compact"` después de compactación |1222| `source` | Cómo se inició la sesión: `"startup"` para nuevas sesiones, `"resume"` para sesiones reanudadas, `"clear"` después de `/clear`, `"compact"` después de compactación, o `"fork"` para una nueva sesión bifurcada desde una existente |
992| `model` | El identificador del modelo activo. Puede omitirse, por ejemplo después de `/clear` o cuando se restaura una sesión a través de recuperación de conversación, así que verifique el campo antes de leerlo |1223| `model` | El identificador del modelo activo. Puede omitirse, por ejemplo después de `/clear` o cuando se restaura una sesión a través de recuperación de conversación, así que verifique el campo antes de leerlo |
993| `agent_type` | El nombre del agente, presente cuando inicia Claude Code con `claude --agent <name>` |1224| `agent_type` | El nombre del agente, presente cuando inicia Claude Code con `claude --agent <name>` |
994| `session_title` | El título de sesión actual si ya está establecido, por ejemplo a través de `--name` o `/rename`. Un hook que emite `sessionTitle` puede verificar `session_title` primero para evitar sobrescribir un título que el usuario estableció explícitamente |1225| `session_title` | El título de sesión actual si ya está establecido, por ejemplo a través de `--name` o `/rename`. Un hook que emite `sessionTitle` puede verificar `session_title` primero para evitar sobrescribir un título que el usuario estableció explícitamente |
995 1226
1227Cuando `source` es `"resume"` o `"fork"` y la transcripción contiene al menos una respuesta de Claude, los hooks SessionStart también reciben los cuatro campos siguientes. Su hook puede usarlos para reportar qué cuesta reanudar una conversación obsoleta antes de la primera solicitud, por ejemplo en un [`systemMessage`](#json-output). Estos campos requieren Claude Code v2.1.251 o posterior.
1228
1229| Campo | Descripción |
1230| :---------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1231| `seconds_since_last_response` | Segundos de reloj de pared desde la última respuesta en la transcripción reanudada |
1232| `context_tokens` | Tokens que la primera solicitud de la sesión reanudada reenvía como su prompt |
1233| `prompt_cache_likely_expired` | `true` cuando la última respuesta es más antigua que la [duración de vida del caché de prompt](/docs/es/prompt-caching#cache-lifetime) de la sesión o una compactación posterior reemplazó la conversación en caché |
1234| `estimated_cache_write_usd` | Costo estimado en dólares estadounidenses de escribir `context_tokens` en el caché de prompt en el modelo de la sesión, excluyendo la respuesta |
1235
1236Este ejemplo muestra la entrada para una sesión reanudada 90 minutos después de su última respuesta:
1237
996```json theme={null}1238```json theme={null}
997{1239{
998 "session_id": "abc123",1240 "session_id": "abc123",
999 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",1241 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
1000 "cwd": "/Users/...",1242 "cwd": "/Users/...",
1001 "hook_event_name": "SessionStart",1243 "hook_event_name": "SessionStart",
1002 "source": "startup",1244 "source": "resume",
1003 "model": "claude-sonnet-5"1245 "model": "claude-opus-5",
1246 "seconds_since_last_response": 5400,
1247 "context_tokens": 182340,
1248 "prompt_cache_likely_expired": true,
1249 "estimated_cache_write_usd": 1.1396
1004}1250}
1005```1251```
1006 1252
1008 Control de decisión de SessionStart1254 Control de decisión de SessionStart
1009</h4>1255</h4>
1010 1256
1011Cualquier texto que su script de hook imprima en stdout se agrega como contexto para Claude. Además de los [campos de salida JSON](#json-output) disponibles para todos los hooks, puede devolver estos campos específicos del evento:1257Claude Code agrega stdout que [trata como texto plano](#exit-code-0) al contexto de Claude. Además de los [campos de salida JSON](#json-output) disponibles para todos los hooks, puede devolver estos campos específicos del evento:
1012 1258
1013| Campo | Descripción |1259| Campo | Descripción |
1014| :------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |1260| :------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1015| `additionalContext` | Cadena agregada al contexto de Claude al inicio de la conversación, antes del primer prompt. Consulte [Agregar contexto para Claude](#add-context-for-claude) para saber cómo se entrega el texto y qué poner en él |1261| `additionalContext` | Cadena agregada al contexto de Claude al inicio de la conversación, antes del primer prompt. Consulte [Agregar contexto para Claude](#add-context-for-claude) para saber cómo se entrega el texto y qué poner en él |
1016| `initialUserMessage` | Cadena utilizada como el primer mensaje de usuario de la sesión. Se aplica en [modo no interactivo](/docs/es/headless) con la bandera `-p`, donde se convierte en el primer turno incluso si no se proporciona ningún prompt. Si se proporciona un prompt, sigue como el siguiente turno. A diferencia de `additionalContext`, que se adjunta a un turno existente, esto crea el turno |1262| `initialUserMessage` | Cadena utilizada como el primer mensaje del usuario de la sesión. Se aplica en [modo no interactivo](/docs/es/headless) con la bandera `-p`, donde se convierte en el primer turno incluso si no se proporciona ningún prompt. Si se proporciona un prompt, sigue como el siguiente turno. A diferencia de `additionalContext`, que se adjunta a un turno existente, esto crea el turno |
1017| `sessionTitle` | Establece el título de la sesión, con el mismo efecto que `/rename`. Use para nombrar sesiones automáticamente desde la carpeta de lanzamiento, rama de git o nombre de worktree. Se aplica solo cuando `source` es `"startup"` o `"resume"`; se ignora en `"clear"` y `"compact"` |1263| `sessionTitle` | Establece el título de la sesión, con el mismo efecto que `/rename`. Úselo para nombrar sesiones automáticamente desde la carpeta de inicio, rama de git o nombre de worktree. Se aplica cuando `source` es `"startup"`, `"resume"`, o `"fork"`; se ignora en `"clear"` y `"compact"` |
1018| `watchPaths` | Array de rutas absolutas para monitorear eventos [FileChanged](#filechanged) durante esta sesión |1264| `watchPaths` | Matriz de rutas absolutas para observar eventos [FileChanged](#filechanged) durante esta sesión |
1019| `reloadSkills` | Booleano. Cuando es `true`, Claude Code vuelve a escanear los directorios [skill](/docs/es/skills) y de comandos después de que se completen los hooks SessionStart, por lo que las skills que instaló el hook están disponibles en la misma sesión, comenzando con el primer prompt |1265| `reloadSkills` | Booleano. Cuando es `true`, Claude Code vuelve a escanear los directorios de [skill](/docs/es/skills) y comando después de que se completen los hooks SessionStart, por lo que las skills que instaló el hook están disponibles en la misma sesión, comenzando con el primer prompt |
1020 1266
1021```json theme={null}1267```json theme={null}
1022{1268{
1028}1274}
1029```1275```
1030 1276
1031Dado que el stdout plano ya llega a Claude para este evento, un hook que solo carga contexto puede imprimir en stdout directamente sin construir JSON. Use el formulario JSON cuando necesite combinar contexto con otros campos como `suppressOutput` o `sessionTitle`.1277Dado que stdout plano ya llega a Claude para este evento, un hook que solo carga contexto puede imprimir a stdout directamente sin construir JSON. Use la forma JSON cuando necesite combinar contexto con otros campos como `sessionTitle`.
1032 1278
1033Use `reloadSkills` cuando un hook SessionStart instala o actualiza skills. El descubrimiento de skills normalmente se ejecuta antes de que se completen los hooks SessionStart, por lo que los archivos que el hook escribe en `~/.claude/skills/` o `.claude/skills/` de otro modo solo aparecerían en la siguiente sesión. Este ejemplo sincroniza un repositorio de skills compartido y solicita el re-escaneo:1279Use `reloadSkills` cuando un hook SessionStart instala o actualiza skills. El descubrimiento de skills normalmente se ejecuta antes de que se completen los hooks SessionStart, por lo que los archivos que el hook escribe en `~/.claude/skills/` o `.claude/skills/` de otro modo solo aparecerían en la siguiente sesión. Este ejemplo sincroniza un repositorio de skills compartido y solicita el re-escaneo:
1034 1280
1041echo '{"hookSpecificOutput": {"hookEventName": "SessionStart", "reloadSkills": true}}'1287echo '{"hookSpecificOutput": {"hookEventName": "SessionStart", "reloadSkills": true}}'
1042```1288```
1043 1289
1290La URL del repositorio es un marcador de posición; reemplácela con su propio repositorio de skills. Con el marcador de posición, el clon falla e imprime un mensaje `fatal:` a stderr. Stderr de un hook SessionStart que sale con 0 es solo informativo, por lo que la solicitud `reloadSkills` aún se aplica.
1291
1044<h4 id="persist-environment-variables">1292<h4 id="persist-environment-variables">
1045 Persistir variables de entorno1293 Persistir variables de entorno
1046</h4>1294</h4>
1068 1316
1069ENV_BEFORE=$(export -p | sort)1317ENV_BEFORE=$(export -p | sort)
1070 1318
1071# Ejecute sus comandos de configuración que modifican el entorno1319# Run your setup commands that modify the environment
1072source ~/.nvm/nvm.sh1320source ~/.nvm/nvm.sh
1073nvm use 201321nvm use 20
1074 1322
1080exit 01328exit 0
1081```1329```
1082 1330
1083Cualquier variable escrita en este archivo estará disponible en todos los comandos Bash posteriores que Claude Code ejecute durante la sesión.
1084
1085<Note>1331<Note>
1086 `CLAUDE_ENV_FILE` está disponible para hooks SessionStart, [Setup](#setup), [CwdChanged](#cwdchanged) y [FileChanged](#filechanged). Otros tipos de hooks no tienen acceso a esta variable.1332 `CLAUDE_ENV_FILE` está disponible para hooks SessionStart, [Setup](#setup), [CwdChanged](#cwdchanged), y [FileChanged](#filechanged). Otros tipos de hooks no tienen acceso a esta variable.
1087</Note>1333</Note>
1088 1334
1089<h3 id="setup">1335<h3 id="setup">
1090 Setup1336 Setup
1091</h3>1337</h3>
1092 1338
1093Se activa solo cuando inicia Claude Code con `--init-only`, o con `--init` o `--maintenance` en [modo no interactivo](/docs/es/headless) con la bandera `-p`. No se activa en el inicio normal. Úselo para instalación de dependencias única o limpieza programada que desencadena explícitamente desde CI o scripts, separado del inicio de sesión normal. Para inicialización por sesión, use [SessionStart](#sessionstart) en su lugar.1339Se dispara solo cuando inicia Claude Code con `--init-only`, o con `--init` o `--maintenance` en [modo no interactivo](/docs/es/headless) con la bandera `-p`. No se dispara al iniciar normalmente. Úselo para instalación de dependencias única o limpieza programada que dispara explícitamente desde CI o scripts, separado del inicio de sesión normal. Para inicialización por sesión, use [SessionStart](#sessionstart) en su lugar.
1094 1340
1095El valor del matcher corresponde a la bandera CLI que desencadenó el hook:1341El valor del matcher corresponde a la bandera CLI que disparó el hook:
1096 1342
1097| Matcher | Cuándo se activa |1343| Matcher | Cuándo se dispara |
1098| :------------ | :---------------------------------------- |1344| :------------ | :---------------------------------------- |
1099| `init` | `claude --init-only` o `claude -p --init` |1345| `init` | `claude --init-only` o `claude -p --init` |
1100| `maintenance` | `claude -p --maintenance` |1346| `maintenance` | `claude -p --maintenance` |
1101 1347
1102`--init-only` ejecuta hooks Setup y hooks SessionStart con el matcher `startup`, luego sale sin iniciar una conversación. `--init` y `--maintenance` activan hooks Setup solo cuando se combinan con `-p`; en una sesión interactiva esas dos banderas actualmente no activan hooks Setup.1348Cuando ejecuta `claude --init-only`, Claude Code ejecuta hooks Setup y hooks `SessionStart` con el matcher `startup`, luego sale sin iniciar una conversación.
1103 1349
1104Debido a que Setup no se activa en cada lanzamiento, un plugin que necesita una dependencia instalada no puede confiar solo en Setup. El patrón práctico es verificar la dependencia en el primer uso e instalar si falta, por ejemplo un hook o skill que pruebe `${CLAUDE_PLUGIN_DATA}/node_modules` y ejecute `npm install` si está ausente. Consulte el [directorio de datos persistentes](/docs/es/plugins-reference#persistent-data-directory) para saber dónde almacenar dependencias instaladas.1350Cuando inicia o continúa una conversación con `-p`, también necesita proporcionar un prompt, como argumento o canalizando en stdin. Puede omitir el prompt cuando un hook `SessionStart` proporciona [`initialUserMessage`](#sessionstart-decision-control) o cuando reanuda una sesión con una [llamada de herramienta diferida](#defer-a-tool-call-for-later).
1351
1352En caso de éxito, `--init-only` no imprime nada en la terminal. Para confirmar que los hooks se ejecutaron, comience con `claude --debug-file <path> --init-only`, reemplazando `<path>` con una ubicación de archivo de registro, y verifique el registro para las entradas de hook Setup y SessionStart.
1353
1354Debido a que Setup no se dispara en cada inicio, un plugin que necesita una dependencia instalada no puede confiar solo en Setup. El patrón práctico es verificar la dependencia en el primer uso e instalar si falta, por ejemplo un hook o skill que prueba `${CLAUDE_PLUGIN_DATA}/node_modules` y ejecuta `npm install` si está ausente. Consulte el [directorio de datos persistentes](/docs/es/plugins-reference#persistent-data-directory) para saber dónde almacenar las dependencias instaladas. Si distribuye su plugin a través de un marketplace, es posible que no necesite este patrón: Claude Code [instala automáticamente las dependencias del paquete Node.js elegibles](/docs/es/plugins-reference#node-js-package-dependencies) cuando almacena en caché el plugin.
1105 1355
1106<h4 id="setup-input">1356<h4 id="setup-input">
1107 Entrada de Setup1357 Entrada de Setup
1123 Control de decisión de Setup1373 Control de decisión de Setup
1124</h4>1374</h4>
1125 1375
1126Los hooks Setup no pueden bloquear. Cualquier código de salida distinto de cero, incluyendo 2, muestra stderr al usuario como un aviso de `<hook name> hook error`, y la ejecución continúa. En [modo no interactivo](/docs/es/headless), la salida del hook aparece solo cuando inicia con `--verbose`.1376Los hooks Setup no pueden bloquear; la ejecución continúa en cualquier código de salida. En cada código de salida, Claude Code descarta los [campos de salida JSON](#json-output) de un hook Setup, como `systemMessage`, `continue`, y `hookSpecificOutput.additionalContext`. Con `-p`, la salida stdout, stderr y código de salida de un hook Setup aparecen en la salida de la ejecución solo como [eventos `hook_response`](/docs/es/headless#read-session-metadata) cuando inicia con `--output-format stream-json --verbose`.
1127
1128Para pasar información al contexto de Claude, devuelva `additionalContext` en salida JSON; el stdout plano se escribe solo en el registro de depuración. Además de los [campos de salida JSON](#json-output) disponibles para todos los hooks, puede devolver estos campos específicos del evento:
1129
1130| Campo | Descripción |
1131| :------------------ | :---------------------------------------------------------------------------------- |
1132| `additionalContext` | Cadena agregada al contexto de Claude. Los valores de múltiples hooks se concatenan |
1133
1134```json theme={null}
1135{
1136 "hookSpecificOutput": {
1137 "hookEventName": "Setup",
1138 "additionalContext": "Dependencies installed: node_modules, .venv"
1139 }
1140}
1141```
1142 1377
1143Los hooks Setup tienen acceso a `CLAUDE_ENV_FILE`. Las variables escritas en ese archivo persisten en comandos Bash posteriores para la sesión, al igual que en los [hooks SessionStart](#persist-environment-variables). Solo se admiten hooks `type: "command"` y `type: "mcp_tool"`.1378Los hooks Setup tienen acceso a `CLAUDE_ENV_FILE`. Las variables escritas en ese archivo persisten en comandos Bash posteriores para la sesión, al igual que en [hooks SessionStart](#persist-environment-variables). Solo se ejecutan hooks `type: "command"` en `Setup`. Un hook `type: "mcp_tool"` en `Setup` siempre se omite, como se describe en [Campos de hook de herramienta MCP](#mcp-tool-hook-fields).
1144 1379
1145<h3 id="instructionsloaded">1380<h3 id="instructionsloaded">
1146 InstructionsLoaded1381 InstructionsLoaded
1147</h3>1382</h3>
1148 1383
1149Se activa cuando se carga un archivo `CLAUDE.md` o `.claude/rules/*.md` en contexto. Este evento se activa al inicio de la sesión para archivos cargados con entusiasmo y nuevamente más tarde cuando se cargan archivos de forma perezosa, por ejemplo cuando Claude accede a un subdirectorio que contiene un `CLAUDE.md` anidado o cuando reglas condicionales con frontmatter `paths:` coinciden. El hook no admite bloqueo o control de decisión. Se ejecuta de forma asincrónica con fines de observabilidad.1384Se dispara cuando se carga un archivo `CLAUDE.md` o `.claude/rules/*.md` en el contexto. Este evento se dispara al inicio de la sesión para archivos cargados con entusiasmo y nuevamente más tarde cuando se cargan archivos de forma perezosa, por ejemplo cuando Claude accede a un subdirectorio que contiene un `CLAUDE.md` anidado o cuando las reglas condicionales con frontmatter `paths:` coinciden. El hook no admite bloqueo o control de decisión. Se ejecuta de forma asincrónica con fines de observabilidad.
1385
1386Este evento no se dispara cuando Claude [lee `AGENTS.md` directamente](/docs/es/memory#agents-md) a través de la configuración **Project instructions**. Se dispara cuando un `CLAUDE.md` importa su `AGENTS.md`, con `load_reason` establecido en `include` como para cualquier otro archivo importado, y cuando `CLAUDE.md` es un symlink a él, como una carga normal de `CLAUDE.md`.
1150 1387
1151El matcher se ejecuta contra `load_reason`. Por ejemplo, use `"matcher": "session_start"` para activarse solo para archivos cargados al inicio de la sesión, o `"matcher": "path_glob_match|nested_traversal"` para activarse solo para cargas perezosas.1388El matcher se ejecuta contra `load_reason`. Por ejemplo, use `"matcher": "session_start"` para dispararse solo para archivos cargados al inicio de la sesión, o `"matcher": "path_glob_match|nested_traversal"` para dispararse solo para cargas perezosas.
1152 1389
1153<h4 id="instructionsloaded-input">1390<h4 id="instructionsloaded-input">
1154 Entrada de InstructionsLoaded1391 Entrada de InstructionsLoaded
1157Además de los [campos de entrada comunes](#common-input-fields), los hooks InstructionsLoaded reciben estos campos:1394Además de los [campos de entrada comunes](#common-input-fields), los hooks InstructionsLoaded reciben estos campos:
1158 1395
1159| Campo | Descripción |1396| Campo | Descripción |
1160| :------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |1397| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1161| `file_path` | Ruta absoluta al archivo de instrucciones que se cargó |1398| `file_path` | Ruta absoluta al archivo de instrucciones que se cargó |
1162| `memory_type` | Alcance del archivo: `"User"`, `"Project"`, `"Local"` o `"Managed"` |1399| `memory_type` | Alcance del archivo: `"User"`, `"Project"`, `"Local"`, o `"Managed"` |
1163| `load_reason` | Por qué se cargó el archivo: `"session_start"`, `"nested_traversal"`, `"path_glob_match"`, `"include"` o `"compact"`. El valor `"compact"` se activa cuando los archivos de instrucciones se recargan después de un evento de compactación |1400| `load_reason` | Por qué se cargó el archivo: `"session_start"`, `"nested_traversal"`, `"path_glob_match"`, `"include"`, o `"compact"`. El valor `"compact"` se dispara cuando los archivos de instrucciones se recargan después de un evento de compactación |
1164| `globs` | Patrones de glob de ruta del frontmatter `paths:` del archivo, si los hay. Presente solo para cargas `path_glob_match` |1401| `globs` | Patrones de glob de ruta del frontmatter `paths:` del archivo, si los hay. Presente solo para cargas `path_glob_match` |
1165| `trigger_file_path` | Ruta al archivo cuyo acceso desencadenó esta carga, para cargas perezosas |1402| `trigger_file_path` | Ruta al archivo cuyo acceso disparó esta carga, para cargas perezosas |
1166| `parent_file_path` | Ruta al archivo de instrucciones padre que incluyó este, para cargas `include` |1403| `parent_file_path` | Ruta al archivo de instrucciones padre que incluyó este, para cargas `include` |
1167 1404
1168```json theme={null}1405```json theme={null}
1181 Control de decisión de InstructionsLoaded1418 Control de decisión de InstructionsLoaded
1182</h4>1419</h4>
1183 1420
1184Los hooks InstructionsLoaded no tienen control de decisión. No pueden bloquear o modificar la carga de instrucciones. Use este evento para registro de auditoría, seguimiento de cumplimiento u observabilidad.1421Los hooks InstructionsLoaded no tienen control de decisión. No pueden bloquear o modificar la carga de instrucciones. Claude Code descarta sus [campos de salida JSON](#json-output), como `systemMessage` y `continue`. Use este evento para auditoría de registros, seguimiento de cumplimiento u observabilidad.
1185 1422
1186<h3 id="userpromptsubmit">1423<h3 id="userpromptsubmit">
1187 UserPromptSubmit1424 UserPromptSubmit
1189 1426
1190Se ejecuta cuando el usuario envía un prompt, antes de que Claude lo procese. Esto le permite agregar contexto adicional basado en el prompt/conversación, validar prompts o bloquear ciertos tipos de prompts.1427Se ejecuta cuando el usuario envía un prompt, antes de que Claude lo procese. Esto le permite agregar contexto adicional basado en el prompt/conversación, validar prompts o bloquear ciertos tipos de prompts.
1191 1428
1192Los hooks `UserPromptSubmit` tienen un tiempo de espera predeterminado de 30 segundos para tipos `command`, `http` y `mcp_tool`, más corto que el predeterminado de 600 segundos para esos tipos en otros eventos. Debido a que este hook se ejecuta antes de cada prompt y bloquea el procesamiento del modelo hasta que se completa, un hook atascado detiene la sesión. Si su hook necesita más tiempo, establezca el campo `timeout` en la entrada del hook.1429Los hooks `UserPromptSubmit` tienen un tiempo de espera predeterminado de 30 segundos para tipos `command`, `http` y `mcp_tool`, más corto que el predeterminado de 600 segundos para esos tipos en la mayoría de otros eventos. Debido a que este hook se ejecuta antes de cada prompt y bloquea el procesamiento del modelo hasta que se completa, un hook atascado detiene la sesión. Si su hook necesita más tiempo, establezca el campo `timeout` en la entrada del hook.
1193 1430
1194Un hook `UserPromptSubmit` de tipo `command`, `http` o `mcp_tool` que alcanza su tiempo de espera se cancela y su salida, incluyendo cualquier `additionalContext`, se descarta. El prompt aún llega a Claude sin ese contexto. A partir de v2.1.196, la transcripción muestra un aviso que nombra el hook, el tiempo de espera que se activó y que la salida fue descartada. Las versiones anteriores cancelan el hook sin aviso.1431Aparte de un hook de comando que ejecuta con [`async: true`](#run-hooks-in-the-background), un hook de comando, HTTP o herramienta MCP `UserPromptSubmit` que alcanza su tiempo de espera se cancela y su salida, incluido cualquier `additionalContext`, se descarta. El prompt aún llega a Claude sin ese contexto. La transcripción muestra un aviso que nombra el hook, el tiempo de espera que se disparó y que la salida se descartó.
1195 1432
1196Un hook de callback [Agent SDK](/docs/es/agent-sdk/hooks) en `UserPromptSubmit` que alcanza su tiempo de espera bloquea el prompt con un mensaje que nombra el hook y el tiempo de espera, porque un callback allí puede estar actuando como una puerta de política que no debe fallar abierta. La sesión continúa. Antes de v2.1.208, un tiempo de espera de callback en ese evento terminaba el turno con un error de ejecución.1433Un hook de devolución de llamada [Agent SDK](/docs/es/agent-sdk/hooks) en `UserPromptSubmit` que alcanza su tiempo de espera bloquea el prompt con un mensaje que nombra el hook y el tiempo de espera, porque una devolución de llamada allí puede actuar como una puerta de política que no debe fallar abierta. La sesión continúa. Antes de v2.1.208, un tiempo de espera de devolución de llamada en ese evento terminaba el turno con un error de ejecución.
1197 1434
1198<h4 id="userpromptsubmit-input">1435<h4 id="userpromptsubmit-input">
1199 Entrada de UserPromptSubmit1436 Entrada de UserPromptSubmit
1220 1457
1221Hay dos formas de agregar contexto a la conversación en código de salida 0:1458Hay dos formas de agregar contexto a la conversación en código de salida 0:
1222 1459
1223* **Stdout de texto plano**: cualquier texto que no sea JSON escrito en stdout se agrega como contexto1460* **Stdout de texto plano**: Claude Code agrega stdout que [trata como texto plano](#exit-code-0) al contexto de Claude
1224* **JSON con `additionalContext`**: use el formato JSON a continuación para más control. El campo `additionalContext` se agrega como contexto1461* **JSON con `additionalContext`**: use el formato JSON a continuación para más control. El campo `additionalContext` se agrega como contexto
1225 1462
1226El stdout plano se muestra como salida de hook en la transcripción. El valor de `additionalContext` se inyecta como un recordatorio del sistema que Claude lee sin una entrada de transcripción visible.1463Ningún canal produce una entrada de transcripción visible. El stdout plano y el valor `additionalContext` se inyectan cada uno como un recordatorio del sistema que comienza con el nombre del hook; Claude lee ambos. Para confirmar la entrega, verifique el [registro de depuración](#debug-hooks).
1227 1464
1228Para bloquear un prompt, devuelva un objeto JSON con `decision` establecido en `"block"`:1465Para bloquear un prompt, devuelva un objeto JSON con `decision` establecido en `"block"`:
1229 1466
1230| Campo | Descripción |1467| Campo | Descripción |
1231| :----------------------- | :---------------------------------------------------------------------------------------------------------------------------------- |1468| :----------------------- | :---------------------------------------------------------------------------------------------------------------------------------- |
1232| `decision` | `"block"` evita que el prompt se procese y lo borra del contexto. Omita para permitir que el prompt continúe |1469| `decision` | `"block"` evita que se procese el prompt y lo borra del contexto. Omita para permitir que el prompt continúe |
1233| `reason` | Se muestra al usuario cuando `decision` es `"block"`. No se agrega al contexto |1470| `reason` | Se muestra al usuario cuando `decision` es `"block"`. No se agrega al contexto |
1234| `additionalContext` | Cadena agregada al contexto de Claude junto con el prompt enviado. Consulte [Agregar contexto para Claude](#add-context-for-claude) |1471| `additionalContext` | Cadena agregada al contexto de Claude junto con el prompt enviado. Consulte [Agregar contexto para Claude](#add-context-for-claude) |
1235| `sessionTitle` | Establece el título de la sesión. Use para nombrar sesiones automáticamente basándose en el contenido del prompt |1472| `sessionTitle` | Establece el título de la sesión. Úselo para nombrar sesiones automáticamente basándose en el contenido del prompt |
1236| `suppressOriginalPrompt` | Si es `true` cuando `decision` es `"block"`, omite el texto del prompt original del mensaje de bloqueo mostrado al usuario |1473| `suppressOriginalPrompt` | Si es `true` cuando `decision` es `"block"`, omite el texto del prompt original del mensaje de bloqueo mostrado al usuario |
1237 1474
1475Un hook que bloquea saliendo con 2 se enruta de la misma manera que `reason`: el mensaje de bloqueo muestra el texto stderr al usuario y no se agrega al contexto.
1476
1238```json theme={null}1477```json theme={null}
1239{1478{
1240 "decision": "block",1479 "decision": "block",
1251 UserPromptExpansion1490 UserPromptExpansion
1252</h3>1491</h3>
1253 1492
1254Se ejecuta cuando un comando de barra diagonal escrito por el usuario se expande en un prompt antes de llegar a Claude. Use esto para bloquear comandos específicos de invocación directa, inyectar contexto para una skill particular o registrar qué comandos invocan los usuarios. Por ejemplo, un hook que coincida con `deploy` puede bloquear `/deploy` a menos que esté presente un archivo de aprobación, o un hook que coincida con una skill de revisión puede agregar la lista de verificación de revisión del equipo como `additionalContext`.1493Se ejecuta cuando un comando escrito por el usuario se expande en un prompt antes de llegar a Claude. Úselo para bloquear comandos específicos de invocación directa, inyectar contexto para una skill particular o registrar qué comandos invocan los usuarios. Por ejemplo, un hook que coincide con `deploy` puede bloquear `/deploy` a menos que esté presente un archivo de aprobación, o un hook que coincide con una skill de revisión puede agregar la lista de verificación de revisión del equipo como `additionalContext`.
1255 1494
1256Este evento cubre la ruta que `PreToolUse` no cubre: un hook `PreToolUse` que coincida con la herramienta `Skill` se activa solo cuando Claude llama a la herramienta, pero escribir `/skillname` directamente omite `PreToolUse`. `UserPromptExpansion` se activa en esa ruta directa.1495Este evento cubre la ruta que `PreToolUse` no cubre: un hook `PreToolUse` que coincide con la herramienta `Skill` se dispara solo cuando Claude llama a la herramienta, pero escribir `/skillname` directamente omite `PreToolUse`. `UserPromptExpansion` se dispara en esa ruta directa.
1257 1496
1258Coincide en `command_name`. Deje el matcher vacío para activarse en cada comando de barra diagonal de tipo prompt.1497Coincide en `command_name`. Deje el matcher vacío para dispararse en cada comando de tipo prompt.
1259 1498
1260<h4 id="userpromptexpansion-input">1499<h4 id="userpromptexpansion-input">
1261 Entrada de UserPromptExpansion1500 Entrada de UserPromptExpansion
1262</h4>1501</h4>
1263 1502
1264Además de los [campos de entrada comunes](#common-input-fields), los hooks UserPromptExpansion reciben `expansion_type`, `command_name`, `command_args`, `command_source` y la cadena `prompt` original. El campo `expansion_type` es `slash_command` para skills y comandos personalizados, o `mcp_prompt` para prompts de servidor MCP.1503Además de los [campos de entrada comunes](#common-input-fields), los hooks UserPromptExpansion reciben `expansion_type`, `command_name`, `command_args`, `command_source` y la cadena `prompt` original. El campo `expansion_type` es `slash_command` para skills y comandos personalizados, o `mcp_prompt` para prompts del servidor MCP.
1265 1504
1266```json theme={null}1505```json theme={null}
1267{1506{
1286 1525
1287| Campo | Descripción |1526| Campo | Descripción |
1288| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------ |1527| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------ |
1289| `decision` | `"block"` evita que el comando de barra diagonal se expanda. Omita para permitir que continúe |1528| `decision` | `"block"` evita que el comando se expanda. Omita para permitir que continúe |
1290| `reason` | Se muestra al usuario cuando `decision` es `"block"` |1529| `reason` | Se muestra al usuario cuando `decision` es `"block"` |
1291| `additionalContext` | Cadena agregada al contexto de Claude junto con el prompt expandido. Consulte [Agregar contexto para Claude](#add-context-for-claude) |1530| `additionalContext` | Cadena agregada al contexto de Claude junto con el prompt expandido. Consulte [Agregar contexto para Claude](#add-context-for-claude) |
1292 1531
1532Un hook que bloquea saliendo con 2 se enruta de la misma manera que `reason`: el mensaje de bloqueo muestra el texto stderr al usuario.
1533
1293```json theme={null}1534```json theme={null}
1294{1535{
1295 "decision": "block",1536 "decision": "block",
1310Use MessageDisplay para:1551Use MessageDisplay para:
1311 1552
1312* eliminar markdown para una visualización mínima1553* eliminar markdown para una visualización mínima
1313* transformar el texto que una aplicación del Agent SDK muestra a sus usuarios1554* transformar el texto que una aplicación Agent SDK muestra a sus usuarios
1314* redactar claves API o nombres de host internos de las respuestas de Claude1555* redactar claves API o nombres de host internos de las respuestas de Claude
1315 1556
1316Claude Code retiene cada lote hasta que su hook regresa, así que mantenga el hook rápido. Si el hook falla o agota el tiempo de espera, Claude Code muestra el texto original. El tiempo de espera predeterminado para este evento es 10 segundos; si su hook necesita más tiempo, establezca el campo `timeout` en la entrada del hook.1557Claude Code retiene cada lote hasta que su hook devuelve, así que mantenga el hook rápido. Si el hook falla o agota el tiempo de espera, Claude Code muestra el texto original. El tiempo de espera predeterminado para este evento es 10 segundos; si su hook necesita más tiempo, establezca el campo `timeout` en la entrada del hook.
1317 1558
1318MessageDisplay es solo para visualización: el texto de reemplazo cambia solo lo que se renderiza en pantalla. La transcripción y lo que Claude ve mantienen el texto original, por lo que Claude nunca ve el reemplazo, y el modo detallado muestra el original. El hook recibe solo texto de mensaje del asistente, por lo que los resultados de herramientas y el texto que escribe se renderizarán sin cambios.1559MessageDisplay es solo para visualización: el texto de reemplazo cambia solo lo que se renderiza en pantalla. La transcripción y lo que Claude ve mantienen el texto original, por lo que Claude nunca ve el reemplazo, y el modo detallado muestra el original. El hook recibe solo texto de mensaje del asistente, por lo que los resultados de herramientas y el texto que escribe se renderiza sin cambios.
1319 1560
1320MessageDisplay no admite matchers y se activa para cada mensaje del asistente que transmite texto; los mensajes sin texto, como respuestas de solo llamada de herramienta, no lo activan.1561MessageDisplay no admite matchers y se dispara para cada mensaje del asistente que transmite texto; los mensajes sin texto, como respuestas de solo llamada de herramienta, no lo disparan.
1321 1562
1322En ejecuciones no interactivas, incluidas consultas del Agent SDK y `claude -p`, MessageDisplay se ejecuta una vez por mensaje del asistente en lugar de una vez por lote de líneas. La llamada única llega después de que se completa el mensaje y lleva el texto del mensaje completo: `index` es `0`, `final` es `true` y `delta` contiene el mensaje completo. Un hook que recopila el texto `delta` para cada mensaje recibe el mismo texto total en ambos modos.1563En ejecuciones no interactivas, incluidas consultas de Agent SDK y `claude -p`, MessageDisplay se ejecuta una vez por mensaje del asistente en lugar de una vez por lote de líneas. La llamada única llega después de que se completa el mensaje y lleva el texto del mensaje completo: `index` es `0`, `final` es `true`, y `delta` contiene el mensaje completo. Un hook que recopila el texto `delta` para cada mensaje recibe el mismo texto total en ambos modos.
1323 1564
1324<h4 id="messagedisplay-input">1565<h4 id="messagedisplay-input">
1325 Entrada de MessageDisplay1566 Entrada de MessageDisplay
1326</h4>1567</h4>
1327 1568
1328Además de los [campos de entrada comunes](#common-input-fields), los hooks MessageDisplay reciben identificadores para el turno y el mensaje, la posición de esta llamada dentro del mensaje y el nuevo texto en `delta`. Los límites de lote dependen de cómo se transmite el texto, así que use `index` y `final` para rastrear el progreso a través de un mensaje en lugar de esperar que las líneas se agrupen de una manera particular.1569Además de los [campos de entrada comunes](#common-input-fields), los hooks MessageDisplay reciben identificadores para el turno y el mensaje, la posición de esta llamada dentro del mensaje y el nuevo texto en `delta`. Los límites de lotes dependen de cómo se transmite el texto, así que use `index` y `final` para rastrear el progreso a través de un mensaje en lugar de esperar que las líneas se agrupen de una manera particular.
1329 1570
1330| Campo | Descripción |1571| Campo | Descripción |
1331| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |1572| :----------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1332| `turn_id` | UUID del turno actual |1573| `turn_id` | UUID del turno actual |
1333| `message_id` | UUID del mensaje del asistente que se está mostrando. Estable en cada lote del mismo mensaje. Este no es el `msg_…` id de API, por lo que no se puede correlacionar con ids de mensaje de transcripción |1574| `message_id` | UUID del mensaje del asistente que se muestra. Estable en cada lote del mismo mensaje. Este no es el ID de API `msg_…`, por lo que no se puede correlacionar con IDs de mensaje de transcripción |
1334| `index` | Índice basado en cero de este lote dentro del mensaje |1575| `index` | Índice basado en cero de este lote dentro del mensaje |
1335| `final` | `true` en el último lote del mensaje. Cada mensaje tiene exactamente un lote final |1576| `final` | `true` en el último lote del mensaje. Cada mensaje tiene exactamente un lote final |
1336| `delta` | Las líneas recién completadas desde el lote anterior, incluyendo saltos de línea finales. Siempre líneas completas, excepto el lote final que puede terminar a mitad de línea. En ejecuciones interactivas, el delta del lote final está vacío cuando el mensaje termina en un salto de línea, así que trate `final`, no un delta no vacío, como la señal de fin de mensaje. En ejecuciones del Agent SDK y `claude -p`, la llamada única lleva el mensaje completo |1577| `delta` | Las líneas recién completadas desde el lote anterior, incluidas las saltos de línea finales. Siempre líneas completas, excepto el lote final que puede terminar a mitad de línea. En ejecuciones interactivas, el delta del lote final está vacío cuando el mensaje termina en un salto de línea, así que trate `final`, no un delta no vacío, como la señal de fin de mensaje. En ejecuciones de Agent SDK y `claude -p`, la llamada única lleva el mensaje completo |
1337 1578
1338```json theme={null}1579```json theme={null}
1339{1580{
1359| :--------------- | :------------------------------------------------------------------ |1600| :--------------- | :------------------------------------------------------------------ |
1360| `displayContent` | Texto mostrado en lugar del delta. Omítalo para mostrar el original |1601| `displayContent` | Texto mostrado en lugar del delta. Omítalo para mostrar el original |
1361 1602
1362Los hooks MessageDisplay no tienen control de decisión. No pueden bloquear el mensaje o cambiar lo que se almacena en la transcripción o se envía a Claude.1603Los hooks MessageDisplay no tienen control de decisión. No pueden bloquear el mensaje o cambiar lo que se almacena en la transcripción o se envía a Claude. Claude Code actúa sobre `displayContent` de su salida JSON y descarta `systemMessage` y `continue`.
1363 1604
1364Este ejemplo elimina el formato markdown de las respuestas de Claude para una visualización de texto plano. El script lee cada lote desde stdin, elimina marcadores de negrita y backticks de código en línea de `delta` y devuelve el resultado como `displayContent`.1605Este ejemplo elimina el formato markdown de las respuestas de Claude para una visualización de texto plano. El script lee cada lote de stdin, elimina marcadores en negrita y comillas invertidas de código en línea de `delta`, y devuelve el resultado como `displayContent`.
1365 1606
1366<Tabs>1607<Tabs>
1367 <Tab title="macOS/Linux">1608 <Tab title="macOS/Linux">
1391 #!/bin/bash1632 #!/bin/bash
1392 jq '{hookSpecificOutput: {hookEventName: "MessageDisplay", displayContent: (.delta | gsub("\\*\\*"; "") | gsub("`"; ""))}}'1633 jq '{hookSpecificOutput: {hookEventName: "MessageDisplay", displayContent: (.delta | gsub("\\*\\*"; "") | gsub("`"; ""))}}'
1393 ```1634 ```
1394
1395 El script necesita `jq` en su `PATH`.
1396 </Tab>1635 </Tab>
1397 1636
1398 <Tab title="Windows (PowerShell)">1637 <Tab title="Windows (PowerShell)">
1439 </Tab>1678 </Tab>
1440</Tabs>1679</Tabs>
1441 1680
1442Los lotes sin markdown pasan sin cambios. Si el script falla, por ejemplo porque `jq` falta, Claude Code muestra el texto original y nota el fallo solo en [salida de depuración](#debug-hooks), no en la sesión.1681Los lotes sin markdown pasan sin cambios. Si el script falla, por ejemplo porque falta `jq`, Claude Code muestra el texto original y solo nota el fallo en [salida de depuración](#debug-hooks), no en la sesión.
1443 1682
1444<h3 id="pretooluse">1683<h3 id="pretooluse">
1445 PreToolUse1684 PreToolUse
1446</h3>1685</h3>
1447 1686
1448Se ejecuta después de que Claude crea parámetros de herramienta y antes de procesar la llamada a herramienta. Coincide en el nombre de la herramienta: `Bash`, `Edit`, `Write`, `Read`, `Glob`, `Grep`, `Agent`, `WebFetch`, `WebSearch`, `AskUserQuestion`, `ExitPlanMode` y cualquier [nombre de herramienta MCP](#match-mcp-tools).1687Se ejecuta después de que Claude crea parámetros de herramienta y antes de procesar la llamada de herramienta. Coincide con cualquier nombre de herramienta excepto `EndConversation`: herramientas integradas como `Bash`, `PowerShell`, `Edit`, `Write`, `Read`, `Glob`, `Grep`, `Agent`, `Workflow`, `WebFetch`, `WebSearch`, `AskUserQuestion`, y `ExitPlanMode`, y cualquier [nombre de herramienta MCP](#match-mcp-tools).
1688
1689Para ejecutar un hook cuando un archivo específico cambia en el disco, sin importar qué lo escribió, use [FileChanged](#filechanged) en lugar de hacer coincidir herramientas de edición de archivos por nombre. A diferencia de PreToolUse, Claude Code ejecuta hooks FileChanged después del cambio y no tienen control de decisión, por lo que no pueden bloquear la escritura.
1449 1690
1450<Warning>1691<Warning>
1451 PreToolUse se ejecuta solo cuando Claude llama a una herramienta. Los archivos que [referencia con `@` en su prompt](/docs/es/common-workflows#reference-files-and-directories) se agregan sin ninguna llamada a herramienta: Claude Code inserta sus contenidos mientras construye el prompt, por lo que no se activa ningún hook PreToolUse para ellos, incluyendo hooks que coincidan con `Read`. Para bloquear rutas específicas de referencias `@`, use una [regla de denegación `Read`](/docs/es/permissions#read-and-edit) en su lugar.1692 PreToolUse se ejecuta solo cuando Claude llama a una herramienta. Los archivos que [referencia con `@` en su prompt](/docs/es/common-workflows#reference-files-and-directories) se agregan sin ninguna llamada de herramienta: Claude Code inserta su contenido mientras construye el prompt, por lo que ningún hook PreToolUse se dispara para ellos, incluidos los hooks que coinciden con `Read`. Para bloquear rutas específicas de referencias `@`, use una [regla de denegación `Read`](/docs/es/permissions#read-and-edit) en su lugar.
1693
1694 PreToolUse tampoco se dispara para [`EndConversation`](/docs/es/tools-reference#endconversation-tool-behavior).
1452</Warning>1695</Warning>
1453 1696
1454Use [PreToolUse decision control](#pretooluse-decision-control) para permitir, denegar, preguntar o diferir la llamada a herramienta.1697Use [control de decisión PreToolUse](#pretooluse-decision-control) para permitir, denegar, preguntar o diferir la llamada de herramienta.
1698
1699Un hook de devolución de llamada [Agent SDK](/docs/es/agent-sdk/hooks) en `PreToolUse` que excede su tiempo de espera bloquea la llamada de herramienta, y Claude recibe un resultado de error que nombra el tiempo de espera. Una denegación explícita devuelta por otro hook aún tiene prioridad.
1455 1700
1456<h4 id="pretooluse-input">1701<h4 id="pretooluse-input">
1457 Entrada de PreToolUse1702 Entrada de PreToolUse
1458</h4>1703</h4>
1459 1704
1460Además de los [campos de entrada comunes](#common-input-fields), los hooks PreToolUse reciben `tool_name`, `tool_input` y `tool_use_id`. Los campos `tool_input` dependen de la herramienta:1705Además de los [campos de entrada comunes](#common-input-fields), los hooks PreToolUse reciben `tool_name`, `tool_input`, y `tool_use_id`.
1706
1707Para una [herramienta MCP](#match-mcp-tools), la entrada también lleva `mcp_server`, un objeto con el `name` del servidor y un `source` que dice de dónde vino la definición del servidor. Los valores `source` incluyen `plugin`, `sdk`, y alcances de configuración como `user` y `project`. [`McpServerProvenance`](/docs/es/agent-sdk/typescript#mcpserverprovenance) en la referencia de Agent SDK los enumera todos y dice cómo tratar uno que no reconozca. Base las decisiones de confianza en `source` en lugar de en `name` o el prefijo de nombre de herramienta `mcp__<server>__`. El campo `mcp_server` requiere Claude Code v2.1.274 o posterior.
1708
1709Para las herramientas de archivo `Write`, `Edit`, y `Read`, `tool_input.file_path` siempre es absoluto:
1710
1711* Claude Code expande `~` y rutas relativas antes de que se ejecuten los hooks, por lo que un hook que coincide con rutas no puede ser eludido a través de `~` o un deletreo relativo de la misma ruta
1712* En Windows, la ruta llega con separadores de barra invertida, incluso cuando su hook se ejecuta bajo Git Bash donde `$PWD` se ve como `/c/project`
1713* Una comparación escrita con barras diagonales, como una verificación `/src/`, nunca coincide con una ruta de barra invertida, y la llamada de herramienta continúa como si el hook no tuviera nada que bloquear
1714* Normalice separadores antes de comparar: `FILE_PATH="${FILE_PATH//\\//}"` en Bash, o `file_path.replace("\\", "/")` en Python, luego coincida con un segmento de ruta como `/src/` en lugar de anclar con `^`, ya que la ruta es absoluta
1715
1716Una llamada `Write` en Windows entrega:
1717
1718```json theme={null}
1719{
1720 "hook_event_name": "PreToolUse",
1721 "tool_name": "Write",
1722 "tool_input": {
1723 "file_path": "C:\\project\\src\\index.ts",
1724 "content": "..."
1725 },
1726 ...
1727}
1728```
1729
1730Los campos `tool_input` dependen de la herramienta:
1731
1732<a id="bash" />
1461 1733
1462<h5 id="bash">1734<h5 id="bash">
1463 Bash1735 Bash
1470| `command` | string | `"npm test"` | El comando de shell a ejecutar |1742| `command` | string | `"npm test"` | El comando de shell a ejecutar |
1471| `description` | string | `"Run test suite"` | Descripción opcional de lo que hace el comando |1743| `description` | string | `"Run test suite"` | Descripción opcional de lo que hace el comando |
1472| `timeout` | number | `120000` | Tiempo de espera opcional en milisegundos. Los valores por encima del [máximo](/docs/es/tools-reference#bash-tool-behavior) se reducen al máximo en lugar de ser rechazados |1744| `timeout` | number | `120000` | Tiempo de espera opcional en milisegundos. Los valores por encima del [máximo](/docs/es/tools-reference#bash-tool-behavior) se reducen al máximo en lugar de ser rechazados |
1473| `run_in_background` | boolean | `false` | Si se ejecuta el comando en segundo plano |1745| `run_in_background` | boolean | `false` | Si ejecutar el comando en segundo plano |
1746
1747Cuando un comando Bash cambia archivos en un repositorio Git, Claude Code puede registrar qué cambió. Registra los cambios en cada modo de permiso cuando la configuración [`bashEditDiffEnabled`](/docs/es/settings-reference#basheditdiffenabled) activa el registro; la entrada de esa configuración dice qué archivos pueden establecerla. De lo contrario, solo los registra en modo automático y modo `bypassPermissions`, y solo cuando Claude Code dirige a Claude a editar archivos a través de Bash. Establezca `bashEditDiffEnabled` en `false` para desactivar el registro. Los comandos de fondo y los comandos de solo lectura no llevan diff.
1748
1749Su hook [PostToolUse](#posttooluse) luego recibe los archivos cambiados en `tool_response.bashEditDiff`. La lista cubre qué cambió bajo el repositorio mientras se ejecutaba el comando. Los archivos que Git ignora y los archivos en submódulos no se enumeran. Requiere Claude Code v2.1.269 o posterior.
1750
1751<Note>
1752 La lista es mejor esfuerzo y en beta pública. Claude Code puede perder un cambio, incluir un archivo que otro proceso cambió al mismo tiempo, o detenerse en sus límites de tamaño. La forma del campo puede cambiar. Use la lista para encontrar qué revisar, no para hacer cumplir una política.
1753</Note>
1754
1755`changedFiles` y `files` enumeran qué cambió el comando; los campos restantes dicen qué tan completa y confiable es esa lista.
1756
1757| Campo | Tipo | Ejemplo | Descripción |
1758| :------------- | :------ | :------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1759| `changedFiles` | array | `["/path/to/src/app.ts"]` | Rutas absolutas de los archivos que el comando cambió, como máximo 200. Presente siempre que `files` contenga un diff o `moreFiles` esté por encima de cero |
1760| `files` | array | `[{"filePath": "/path/to/src/app.ts", "hunks": [...]}]` | Diffs de hasta 5 archivos cambiados, para visualización. `created` o `deleted` es `true` para un archivo que el comando agregó o eliminó |
1761| `moreFiles` | number | `2` | Recuento de archivos cambiados sin diff en `files` |
1762| `unavailable` | boolean | `true` | Se establece cuando el diff está incompleto o no se pudo tomar |
1763| `skipped` | boolean | `true` | Se establece para un comando Git que mueve el árbol de trabajo, como `git checkout` o `git stash`, por lo que Claude Code no toma diff |
1764| `shared` | boolean | `true` | Se establece cuando otra llamada de herramienta Bash, como la de un subagente, se ejecutó en el mismo repositorio al mismo tiempo, por lo que algunos cambios enumerados pueden ser de ese comando |
1765
1766<a id="powershell" />
1767
1768<h5 id="powershell">
1769 PowerShell
1770</h5>
1771
1772Ejecuta comandos de PowerShell. Consulte la [herramienta PowerShell](/docs/es/tools-reference#powershell-tool) para disponibilidad por plataforma.
1773
1774Los campos coinciden con la herramienta Bash, con la cadena de comando en `command`:
1775
1776| Campo | Tipo | Ejemplo | Descripción |
1777| :------------------ | :------ | :------------------------- | :--------------------------------------------- |
1778| `command` | string | `"Get-ChildItem -Recurse"` | El comando de PowerShell a ejecutar |
1779| `description` | string | `"List files recursively"` | Descripción opcional de lo que hace el comando |
1780| `timeout` | number | `120000` | Tiempo de espera opcional en milisegundos |
1781| `run_in_background` | boolean | `false` | Si ejecutar el comando en segundo plano |
1782
1783Coincida con `Bash|PowerShell` en hooks que inspeccionen comandos de shell, para que cubran ambas herramientas:
1784
1785* En Windows, dondequiera que la herramienta PowerShell esté habilitada, Claude trata PowerShell como el shell principal y enruta comandos de shell a través de él.
1786* En Windows sin Git Bash, la herramienta se habilita automáticamente y Claude Code no registra la herramienta Bash en absoluto.
1787* Un hook que coincide solo con `Bash` nunca se dispara allí.
1474 1788
1475<h5 id="write">1789<h5 id="write">
1476 Write1790 Write
1490Reemplaza una cadena en un archivo existente.1804Reemplaza una cadena en un archivo existente.
1491 1805
1492| Campo | Tipo | Ejemplo | Descripción |1806| Campo | Tipo | Ejemplo | Descripción |
1493| :------------ | :------ | :-------------------- | :------------------------------------- |1807| :------------ | :------ | :-------------------- | :---------------------------------- |
1494| `file_path` | string | `"/path/to/file.txt"` | Ruta absoluta al archivo a editar |1808| `file_path` | string | `"/path/to/file.txt"` | Ruta absoluta al archivo a editar |
1495| `old_string` | string | `"original text"` | Texto a encontrar y reemplazar |1809| `old_string` | string | `"original text"` | Texto a encontrar y reemplazar |
1496| `new_string` | string | `"replacement text"` | Texto de reemplazo |1810| `new_string` | string | `"replacement text"` | Texto de reemplazo |
1497| `replace_all` | boolean | `false` | Si se reemplazan todas las ocurrencias |1811| `replace_all` | boolean | `false` | Si reemplazar todas las ocurrencias |
1498 1812
1499<h5 id="read">1813<h5 id="read">
1500 Read1814 Read
1515Encuentra archivos que coincidan con un patrón glob.1829Encuentra archivos que coincidan con un patrón glob.
1516 1830
1517| Campo | Tipo | Ejemplo | Descripción |1831| Campo | Tipo | Ejemplo | Descripción |
1518| :-------- | :----- | :--------------- | :------------------------------------------------------------------------------ |1832| :-------- | :----- | :--------------- | :--------------------------------------------------------------------------------- |
1519| `pattern` | string | `"**/*.ts"` | Patrón glob para coincidir archivos contra |1833| `pattern` | string | `"**/*.ts"` | Patrón glob para hacer coincidir archivos contra |
1520| `path` | string | `"/path/to/dir"` | Directorio opcional para buscar. Por defecto es el directorio de trabajo actual |1834| `path` | string | `"/path/to/dir"` | Directorio opcional para buscar en. Por defecto es el directorio de trabajo actual |
1521 1835
1522<h5 id="grep">1836<h5 id="grep">
1523 Grep1837 Grep
1526Busca contenidos de archivo con expresiones regulares.1840Busca contenidos de archivo con expresiones regulares.
1527 1841
1528| Campo | Tipo | Ejemplo | Descripción |1842| Campo | Tipo | Ejemplo | Descripción |
1529| :------------ | :------ | :--------------- | :------------------------------------------------------------------------------------- |1843| :------------ | :------ | :--------------- | :-------------------------------------------------------------------------------------- |
1530| `pattern` | string | `"TODO.*fix"` | Patrón de expresión regular a buscar |1844| `pattern` | string | `"TODO.*fix"` | Patrón de expresión regular a buscar |
1531| `path` | string | `"/path/to/dir"` | Archivo o directorio opcional para buscar |1845| `path` | string | `"/path/to/dir"` | Archivo o directorio opcional para buscar en |
1532| `glob` | string | `"*.ts"` | Patrón glob opcional para filtrar archivos |1846| `glob` | string | `"*.ts"` | Patrón glob opcional para filtrar archivos |
1533| `output_mode` | string | `"content"` | `"content"`, `"files_with_matches"` o `"count"`. Por defecto es `"files_with_matches"` |1847| `output_mode` | string | `"content"` | `"content"`, `"files_with_matches"`, o `"count"`. Por defecto es `"files_with_matches"` |
1534| `-i` | boolean | `true` | Búsqueda insensible a mayúsculas y minúsculas |1848| `-i` | boolean | `true` | Búsqueda insensible a mayúsculas y minúsculas |
1535| `multiline` | boolean | `false` | Habilitar coincidencia multilínea |1849| `multiline` | boolean | `false` | Habilitar coincidencia multilínea |
1536 1850
1570| `subagent_type` | string | `"Explore"` | Tipo de agente especializado a usar |1884| `subagent_type` | string | `"Explore"` | Tipo de agente especializado a usar |
1571| `model` | string | `"sonnet"` | Alias de modelo opcional para anular el predeterminado |1885| `model` | string | `"sonnet"` | Alias de modelo opcional para anular el predeterminado |
1572 1886
1573En `PostToolUse`, `tool_response` para una llamada Agent completada lleva el texto final del subagente junto con telemetría de uso. Lea estos campos para registrar el costo por subagente desde un hook:1887Cuando una llamada de Agent en primer plano se completa, su hook [PostToolUse](#posttooluse) recibe el resultado del subagente y telemetría de ejecución en `tool_response`. Lea estos campos para inspeccionar la ejecución; para resúmenes de tokens y costos en subagentes, use los [contadores de tokens y costos](/docs/es/monitoring-usage#token-counter) filtrados a `query_source` `"subagent"`, ya que `totalTokens` y `usage` cubren solo la solicitud final:
1574 1888
1575| Campo | Tipo | Ejemplo | Descripción |1889| Campo | Tipo | Ejemplo | Descripción |
1576| :------------------ | :----- | :---------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |1890| :------------------ | :----- | :---------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1577| `status` | string | `"completed"` | `"completed"` para subagentes en primer plano, `"async_launched"` para subagentes en segundo plano. A partir de v2.1.198, los subagentes se ejecutan en segundo plano por defecto, por lo que un `run_in_background` omitido también produce `"async_launched"` |1891| `status` | string | `"completed"` | `"completed"` para subagentes en primer plano, `"async_launched"` para subagentes en segundo plano. A partir de v2.1.198, los subagentes se ejecutan en segundo plano de forma predeterminada, por lo que un `run_in_background` omitido también produce `"async_launched"` |
1578| `agentId` | string | `"a4d2c8f1e0b3a297"` | Identificador para la ejecución del subagente |1892| `agentId` | string | `"a4d2c8f1e0b3a297"` | Identificador para la ejecución del subagente |
1579| `content` | array | `[{"type": "text", "text": "Found 12 endpoints..."}]` | Los bloques de texto finales del subagente |1893| `content` | array | `[{"type": "text", "text": "Found 12 endpoints..."}]` | Los bloques de texto finales del subagente, o, para un subagente cuyo informe pasa a través de `SubagentHandback`, una nota breve sobre esa entrega en su lugar |
1580| `resolvedModel` | string | `"claude-sonnet-4-5"` | Modelo en el que se ejecutó el subagente, que puede diferir del modelo solicitado. Requiere Claude Code v2.1.174 o posterior |1894| `resolvedModel` | string | `"claude-sonnet-4-5"` | Modelo en el que comenzó el subagente, que puede diferir del modelo solicitado |
1581| `totalTokens` | number | `12450` | Tokens totales facturados en los turnos del subagente |1895| `modelsUsed` | array | `["claude-sonnet-4-5", "claude-haiku-4-5"]` | Modelos utilizados en orden, con repeticiones consecutivas colapsadas; se establece solo cuando el modelo fue intercambiado a mitad de ejecución. Requiere Claude Code v2.1.212 o posterior |
1896| `totalTokens` | number | `12450` | Recuento de tokens de la solicitud final de API del subagente: tokens de entrada, salida y caché combinados. Este no es un total en toda la ejecución |
1582| `totalDurationMs` | number | `48211` | Duración de reloj de pared de la ejecución del subagente |1897| `totalDurationMs` | number | `48211` | Duración de reloj de pared de la ejecución del subagente |
1583| `totalToolUseCount` | number | `7` | Recuento de llamadas a herramientas que hizo el subagente |1898| `totalToolUseCount` | number | `7` | Recuento de llamadas de herramienta que realizó el subagente |
1584| `usage` | object | `{"input_tokens": 8320, ...}` | Desglose de tokens por tipo: `input_tokens`, `output_tokens`, `cache_creation_input_tokens`, `cache_read_input_tokens` |1899| `usage` | object | `{"input_tokens": 8320, ...}` | Desglose de tokens por tipo de la solicitud final de API: `input_tokens`, `output_tokens`, `cache_creation_input_tokens`, `cache_read_input_tokens` |
1585 1900
1586Para subagentes en segundo plano, la herramienta regresa inmediatamente después de lanzar, por lo que `tool_response` no lleva campos de uso. Tiene `status: "async_launched"`, `agentId`, `description`, `prompt`, `outputFile` y `resolvedModel`.1901En Claude Code v2.1.271 o posterior, un subagente que se ejecuta con la herramienta [`SubagentHandback`](/docs/es/tools-reference) que Claude Code proporciona en [modo automático](/docs/es/permission-modes#eliminate-prompts-with-auto-mode), entrega su informe a través de esa herramienta en lugar de devolverlo como texto. El campo `content` de su resultado `completed` luego lleva una nota breve sobre esa entrega en lugar del informe en sí. Para leer el informe, coincida un hook `PreToolUse` o `PostToolUse` en `SubagentHandback` y lea `tool_input.message`.
1587 1902
1588El campo `resolvedModel` nombra el modelo en el que se ejecuta realmente el subagente, que puede diferir del valor `model` en `tool_input`, como cuando `availableModels` u otra anulación se aplica. Requiere Claude Code v2.1.174 o posterior.1903Para subagentes en segundo plano, la herramienta devuelve cuando la tarea se mueve al segundo plano, por lo que `tool_response` no lleva campos de uso: un lanzamiento en segundo plano devuelve inmediatamente, y una tarea en primer plano que Claude Code pone en segundo plano a mitad de ejecución devuelve en esa transición. Tiene `status: "async_launched"`, `agentId`, `description`, `prompt`, `outputFile`, y `resolvedModel`.
1904
1905En una respuesta `completed`, `resolvedModel` nombra el modelo en el que comenzó el subagente, que puede diferir del valor `model` en `tool_input`, como cuando `availableModels` u otra anulación se aplica. En una respuesta `async_launched`, `resolvedModel` nombra el modelo en uso cuando el agente se movió al segundo plano, por lo que un intercambio que ocurrió antes de pasar al segundo plano se refleja allí. El comportamiento de `modelsUsed` y `resolvedModel` en tiempo de segundo plano requieren Claude Code v2.1.212 o posterior.
1589 1906
1590<a id="askuserquestion" />1907<a id="askuserquestion" />
1591 1908
1597 1914
1598| Campo | Tipo | Ejemplo | Descripción |1915| Campo | Tipo | Ejemplo | Descripción |
1599| :---------- | :----- | :----------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |1916| :---------- | :----- | :----------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
1600| `questions` | array | `[{"question": "Which framework?", "header": "Framework", "options": [{"label": "React"}], "multiSelect": false}]` | Preguntas a presentar, cada una con una cadena `question`, `header` corto, array `options` y bandera `multiSelect` opcional |1917| `questions` | array | `[{"question": "Which framework?", "header": "Framework", "options": [{"label": "React"}], "multiSelect": false}]` | Preguntas a presentar, cada una con una cadena `question`, `header` corto, matriz `options`, y bandera `multiSelect` opcional |
1601| `answers` | object | `{"Which framework?": "React"}` | Opcional. Asigna texto de pregunta a la etiqueta de opción seleccionada. Las respuestas de selección múltiple unen etiquetas con comas. Claude no establece este campo; suministrarlo a través de `updatedInput` para responder programáticamente |1918| `answers` | object | `{"Which framework?": "React"}` | Opcional. Asigna texto de pregunta a la etiqueta de opción seleccionada. Las respuestas de selección múltiple unen etiquetas con comas. Claude no establece este campo; suministrarlo a través de `updatedInput` para responder programáticamente |
1602 1919
1603<h5 id="exitplanmode">1920<h5 id="exitplanmode">
1604 ExitPlanMode1921 ExitPlanMode
1605</h5>1922</h5>
1606 1923
1607Presenta un plan y pide al usuario que lo apruebe antes de que Claude salga del [modo plan](/docs/es/permission-modes#analyze-before-you-edit-with-plan-mode). Claude escribe el plan en un archivo en el disco antes de llamar a la herramienta, por lo que el `tool_input` literal del modelo es típicamente vacío. Claude Code inyecta el contenido del plan y la ruta del archivo antes de pasar la entrada a los hooks.1924Presenta un plan y pide al usuario que lo apruebe antes de que Claude salga del [modo de plan](/docs/es/permission-modes#analyze-before-you-edit-with-plan-mode). Claude escribe el plan en un archivo en el disco antes de llamar a la herramienta, por lo que la `tool_input` literal del modelo es típicamente vacía. Claude Code inyecta el contenido del plan y la ruta del archivo antes de pasar la entrada a los hooks.
1608 1925
1609| Campo | Tipo | Ejemplo | Descripción |1926| Campo | Tipo | Ejemplo | Descripción |
1610| :--------------- | :----- | :------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- |1927| :--------------- | :----- | :------------------------------------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------- |
1611| `plan` | string | `"## Refactor auth\n1. Extract..."` | Contenido del plan en Markdown. Inyectado desde el archivo del plan en el disco |1928| `plan` | string | `"## Refactor auth\n1. Extract..."` | Contenido del plan en Markdown. Inyectado desde el archivo del plan en el disco |
1612| `planFilePath` | string | `"/Users/.../plans/refactor-auth.md"` | Ruta al archivo del plan. Inyectado |1929| `planFilePath` | string | `"/Users/.../plans/refactor-auth.md"` | Ruta al archivo del plan. Inyectado |
1613| `allowedPrompts` | array | `[{"tool": "Bash", "prompt": "run tests"}]` | Deprecado. Claude Code acepta el campo pero lo ignora. Antes de v2.1.205, llevaba permisos basados en prompts que Claude estaba solicitando para implementar el plan |1930| `allowedPrompts` | array | `[{"tool": "Bash", "prompt": "run tests"}]` | Deprecado. Claude Code acepta el campo pero lo ignora. Antes de v2.1.205, llevaba permisos basados en prompts que Claude solicitó para implementar el plan |
1614 1931
1615En `PostToolUse`, `tool_response` es un objeto con campos `plan` y `filePath` que contienen el plan aprobado, más banderas de estado internas. Lea `tool_response.plan` para el contenido del plan en lugar de releer el archivo desde el disco.1932En `PostToolUse`, `tool_response` es un objeto con campos `plan` y `filePath` que contienen el plan aprobado, más banderas de estado internas. Lea `tool_response.plan` para el contenido del plan en lugar de releer el archivo del disco.
1616 1933
1617<h4 id="pretooluse-decision-control">1934<h4 id="pretooluse-decision-control">
1618 Control de decisión de PreToolUse1935 Control de decisión de PreToolUse
1619</h4>1936</h4>
1620 1937
1621Los hooks `PreToolUse` pueden controlar si procede una llamada a herramienta. A diferencia de otros hooks que usan un campo `decision` de nivel superior, PreToolUse devuelve su decisión dentro de un objeto `hookSpecificOutput`. Esto le da control más rico: cuatro resultados (permitir, denegar, preguntar o diferir) más la capacidad de modificar la entrada de la herramienta antes de la ejecución.1938Los hooks `PreToolUse` pueden controlar si procede una llamada de herramienta. A diferencia de otros hooks que usan un campo `decision` de nivel superior, PreToolUse devuelve su decisión dentro de un objeto `hookSpecificOutput`. Esto le da un control más rico: cuatro resultados (permitir, denegar, preguntar o diferir) más la capacidad de modificar la entrada de herramienta antes de la ejecución.
1622 1939
1623| Campo | Descripción |1940| Campo | Descripción |
1624| :------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |1941| :------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1625| `permissionDecision` | `"allow"` omite el sistema de permisos, excepto para [herramientas que requieren interacción del usuario](#pretooluse-decision-control) y herramientas de conector [que su organización estableció en `ask`](/docs/es/mcp#organization-controls-on-connector-tools). `"deny"` evita la llamada a herramienta. `"ask"` solicita al usuario que confirme. `"defer"` sale correctamente para que la herramienta pueda reanudarse más tarde. Las reglas [Deny and ask](/docs/es/permissions#manage-permissions) aún se evalúan independientemente de lo que devuelva el hook |1942| `permissionDecision` | `"allow"` omite el aviso de permiso, excepto para las [acciones que ningún modo aprueba automáticamente](/docs/es/permission-modes#actions-no-mode-auto-approves) y para `AskUserQuestion` y `ExitPlanMode`, que necesitan [`updatedInput` emparejado con él](#allow-with-updatedinput). `"deny"` evita la llamada de herramienta. `"ask"` solicita al usuario que confirme. `"defer"` sale correctamente para que la herramienta pueda reanudarse más tarde. Las [reglas de denegación y pregunta](/docs/es/permissions#manage-permissions) aún se evalúan independientemente de lo que devuelva el hook |
1626| `permissionDecisionReason` | Para `"allow"` y `"ask"`, se muestra al usuario pero no a Claude. Para `"deny"`, se muestra a Claude. Para `"defer"`, se ignora |1943| `permissionDecisionReason` | Para `"allow"` y `"ask"`, se muestra al usuario pero no a Claude. Para `"deny"`, se muestra a Claude. Para `"defer"`, se ignora |
1627| `updatedInput` | Modifica los parámetros de entrada de la herramienta antes de la ejecución. Reemplaza el objeto de entrada completo, así que incluya campos sin cambios junto con los modificados. Combinar con `"allow"` para aprobación automática, o `"ask"` para mostrar la entrada modificada al usuario. Para `"defer"`, se ignora |1944| `updatedInput` | Modifica los parámetros de entrada de la herramienta antes de la ejecución. Reemplaza el objeto de entrada completo, así que incluya campos sin cambios junto con los modificados. Claude Code evalúa reglas de permiso y la elegibilidad de [segundo plano automático](/docs/es/tools-reference#background-commands) de un comando Bash contra la entrada que devuelve su hook, no la entrada que envió Claude. Combine con `"allow"` para aprobar automáticamente, o `"ask"` para mostrar la entrada modificada al usuario. Para `"defer"`, se ignora |
1628| `additionalContext` | Cadena agregada al contexto de Claude junto con el resultado de la herramienta. Ignorado cuando `permissionDecision` es `"defer"`. Consulte [Agregar contexto para Claude](#add-context-for-claude) |1945| `additionalContext` | Cadena agregada al contexto de Claude junto con el resultado de la herramienta. Se ignora cuando `permissionDecision` es `"defer"`. Consulte [Agregar contexto para Claude](#add-context-for-claude) |
1946
1947Cuando múltiples hooks PreToolUse devuelven decisiones diferentes, la precedencia es `deny` > `defer` > `ask` > `allow`.
1629 1948
1630Cuando múltiples hooks PreToolUse devuelven diferentes decisiones, la precedencia es `deny` > `defer` > `ask` > `allow`.1949Un hook que bloquea saliendo con 2 se enruta de la misma manera que `"deny"`: Claude ve el mensaje stderr como la razón de la denegación.
1631 1950
1632Cuando un hook devuelve `"ask"`, el diálogo de permiso mostrado al usuario incluye una etiqueta que identifica de dónde proviene el hook: por ejemplo, `[User]`, `[Project]`, `[Plugin]` o `[Local]`. Esto ayuda a los usuarios a entender qué fuente de configuración está solicitando confirmación.1951Cuando un hook devuelve `"ask"`, el aviso de permiso mostrado al usuario incluye una etiqueta que identifica de dónde vino el hook: `[settings]` para un hook de cualquier archivo de configuración o del frontmatter del agente, `[plugin:<name>]` para el hook de un plugin, o `[skill]` para un hook del frontmatter de skill. Esto ayuda a los usuarios a entender qué fuente de configuración solicita confirmación.
1952
1953Un `"ask"` de un hook también fuerza un aviso de permiso en [modo automático](/docs/es/permission-modes#eliminate-prompts-with-auto-mode): el clasificador aún puede denegar la llamada de herramienta, pero no puede aprobar la llamada silenciosamente. Antes de v2.1.211, el clasificador podría aprobar un comando Bash ejecutándose fuera del [sandbox](/docs/es/sandboxing) sin mostrar el aviso que solicitó el hook; el clasificador aún aplicaba sus propias reglas de seguridad a ese comando, y una denegación de hook `"deny"` siempre se honraba.
1633 1954
1634```json theme={null}1955```json theme={null}
1635{1956{
1645}1966}
1646```1967```
1647 1968
1648`AskUserQuestion` y `ExitPlanMode` requieren interacción del usuario y normalmente se bloquean en [modo no interactivo](/docs/es/headless) con la bandera `-p`. Devolver `permissionDecision: "allow"` junto con `updatedInput` satisface ese requisito: el hook lee la entrada de la herramienta desde stdin, recopila la respuesta a través de su propia interfaz de usuario y la devuelve en `updatedInput` para que la herramienta se ejecute sin solicitar. Devolver `"allow"` solo no es suficiente para estas herramientas. Para `AskUserQuestion`, repita el array `questions` original y agregue un objeto [`answers`](#askuserquestion) que asigne el texto de cada pregunta a la respuesta elegida.1969<span id="allow-with-updatedinput" />
1649 1970
1650Herramientas de conector [que su organización estableció en `ask`](/docs/es/mcp#organization-controls-on-connector-tools) solicitan incluso cuando un hook devuelve `"allow"`.1971En [modo no interactivo](/docs/es/headless) con la bandera `-p`, Claude Code ofrece `AskUserQuestion` y `ExitPlanMode` solo cuando la ejecución tiene un [anfitrión de permiso](/docs/es/headless#turn-off-permission-prompts-in-unattended-runs) para recibir el aviso, como una devolución de llamada `canUseTool` de Agent SDK. Estas herramientas requieren interacción del usuario. Devolver `permissionDecision: "allow"` junto con `updatedInput` satisface ese requisito: el hook lee la entrada de la herramienta de stdin, recopila la respuesta a través de su propia interfaz de usuario, y la devuelve en `updatedInput` para que la herramienta se ejecute sin solicitar. Devolver `"allow"` solo no es suficiente para estas herramientas. Para `AskUserQuestion`, devuelva la matriz `questions` original y agregue un objeto [`answers`](#askuserquestion) que asigne el texto de cada pregunta a la respuesta elegida.
1651 1972
1652A partir de v2.1.199, una herramienta MCP cuyo servidor la marca con [`_meta["anthropic/requiresUserInteraction"]`](/docs/es/mcp#require-approval-for-a-specific-tool) es más estricta: un hook no puede omitir su solicitud de aprobación con `"allow"`, con o sin `updatedInput`, porque Claude Code no puede confirmar que el hook recopiló la interacción que la herramienta necesita.1973A partir de v2.1.199, una herramienta MCP cuyo servidor la marca con [`_meta["anthropic/requiresUserInteraction"]`](/docs/es/mcp#require-approval-for-a-specific-tool) es más estricta: un hook no puede omitir su aviso de aprobación con `"allow"`, con o sin `updatedInput`, porque Claude Code no puede confirmar que el hook recopiló la interacción que la herramienta necesita.
1653 1974
1654<Note>1975<Note>
1655 PreToolUse anteriormente usaba campos `decision` y `reason` de nivel superior, pero estos están deprecados para este evento. Use `hookSpecificOutput.permissionDecision` y `hookSpecificOutput.permissionDecisionReason` en su lugar. Los valores deprecados `"approve"` y `"block"` se asignan a `"allow"` y `"deny"` respectivamente. Otros eventos como PostToolUse y Stop continúan usando `decision` y `reason` de nivel superior como su formato actual.1976 PreToolUse previamente usaba campos `decision` y `reason` de nivel superior, pero estos están deprecados para este evento. Use `hookSpecificOutput.permissionDecision` y `hookSpecificOutput.permissionDecisionReason` en su lugar. Los valores deprecados `"approve"` y `"block"` se asignan a `"allow"` y `"deny"` respectivamente. Otros eventos como PostToolUse y Stop continúan usando `decision` y `reason` de nivel superior como su formato actual.
1656</Note>1977</Note>
1657 1978
1658<h4 id="defer-a-tool-call-for-later">1979<h4 id="defer-a-tool-call-for-later">
1659 Diferir una llamada a herramienta para más tarde1980 Diferir una llamada de herramienta para más tarde
1660</h4>1981</h4>
1661 1982
1662`"defer"` es para integraciones que ejecutan `claude -p` como un subproceso y leen su salida JSON, como una aplicación del Agent SDK o una interfaz de usuario personalizada construida sobre Claude Code. Permite que ese proceso de llamada pause Claude en una llamada a herramienta, recopile entrada a través de su propia interfaz y reanude donde se quedó. Claude Code honra este valor solo en [modo no interactivo](/docs/es/headless) con la bandera `-p`. En sesiones interactivas registra una advertencia e ignora el resultado del hook.1983`"defer"` es para integraciones que ejecutan `claude -p` como un subproceso y leen su salida JSON, como una aplicación Agent SDK o una interfaz de usuario personalizada construida sobre Claude Code. Permite que ese proceso de llamada pause Claude en una llamada de herramienta, recopile entrada a través de su propia interfaz, y reanude donde se quedó. Claude Code honra este valor solo en [modo no interactivo](/docs/es/headless) con la bandera `-p`. En sesiones interactivas registra una advertencia e ignora el resultado del hook.
1663 1984
1664La herramienta `AskUserQuestion` es el caso típico: Claude quiere hacer algo al usuario, pero no hay terminal para responder. El viaje de ida y vuelta funciona así:1985La herramienta `AskUserQuestion` es el caso típico: Claude quiere hacer una pregunta al usuario, pero no hay terminal para responder. Una ejecución `-p` ofrece `AskUserQuestion` solo cuando tiene un [anfitrión de permiso](/docs/es/headless#turn-off-permission-prompts-in-unattended-runs), como una herramienta MCP que pasa con `--permission-prompt-tool`, así que comience la ejecución con una. El viaje de ida y vuelta funciona así:
1665 1986
16661. Claude llama a `AskUserQuestion`. Se activa el hook `PreToolUse`.19871. Claude llama a `AskUserQuestion`. Se dispara el hook `PreToolUse`.
16672. El hook devuelve `permissionDecision: "defer"`. La herramienta no se ejecuta. El proceso sale con `stop_reason: "tool_deferred"` y la llamada a herramienta pendiente preservada en la transcripción.19882. El hook devuelve `permissionDecision: "defer"`. La herramienta no se ejecuta. El proceso sale con `stop_reason: "tool_deferred"` y la llamada de herramienta pendiente preservada en la transcripción.
16683. El proceso de llamada lee `deferred_tool_use` del resultado del SDK, muestra la pregunta en su propia interfaz de usuario y espera una respuesta.19893. El proceso de llamada lee `deferred_tool_use` del resultado de SDK, muestra la pregunta en su propia interfaz de usuario, y espera una respuesta.
16694. El proceso de llamada ejecuta `claude -p --resume <session-id>`. La misma llamada a herramienta activa `PreToolUse` nuevamente.19904. El proceso de llamada ejecuta `claude -p --resume <session-id>` con el mismo anfitrión de permiso. Se dispara la misma llamada de herramienta `PreToolUse` nuevamente.
16705. El hook devuelve `permissionDecision: "allow"` con la respuesta en `updatedInput`. La herramienta se ejecuta y Claude continúa.19915. El hook devuelve `permissionDecision: "allow"` con la respuesta en `updatedInput`. La herramienta se ejecuta y Claude continúa.
1671 1992
1672El campo `deferred_tool_use` lleva el `id`, `name` e `input` de la herramienta. El `input` son los parámetros que Claude generó para la llamada a herramienta, capturados antes de la ejecución:1993El campo `deferred_tool_use` lleva el `id`, `name`, e `input` de la herramienta. El `input` son los parámetros que Claude generó para la llamada de herramienta, capturados antes de la ejecución:
1673 1994
1674```json theme={null}1995```json theme={null}
1675{1996{
1685}2006}
1686```2007```
1687 2008
1688No hay límite de tiempo de espera o reintento. La sesión permanece en el disco hasta que la reanude, sujeta al barrido de retención [`cleanupPeriodDays`](/docs/es/settings#available-settings) que elimina archivos de sesión después de 30 días por defecto. Si la respuesta no está lista cuando reanuda, el hook puede devolver `"defer"` nuevamente y el proceso sale de la misma manera. El proceso de llamada controla cuándo romper el bucle devolviendo finalmente `"allow"` o `"deny"` del hook.2009No hay límite de tiempo de espera o reintento. La sesión permanece en el disco hasta que la reanude, sujeta al barrido de retención [`cleanupPeriodDays`](/docs/es/settings-reference#cleanupperioddays), que elimina archivos de sesión después de 30 días de forma predeterminada, siguiendo las [reglas de barrido de retención](/docs/es/claude-directory#cleaned-up-automatically). Si la respuesta no está lista cuando reanuda, el hook puede devolver `"defer"` nuevamente y el proceso sale de la misma manera. El proceso de llamada controla cuándo romper el bucle devolviendo finalmente `"allow"` o `"deny"` del hook.
1689 2010
1690`"defer"` solo funciona cuando Claude hace una única llamada a herramienta en el turno. Si Claude hace varias llamadas a herramientas a la vez, `"defer"` se ignora con una advertencia y la herramienta procede a través del flujo de permiso normal. La restricción existe porque reanudar solo puede re-ejecutar una herramienta: no hay forma de diferir una llamada de un lote sin dejar las otras sin resolver.2011`"defer"` solo funciona cuando Claude realiza una única llamada de herramienta en el turno. Si Claude realiza varias llamadas de herramienta a la vez, `"defer"` se ignora con una advertencia y la herramienta procede a través del flujo de permiso normal. La restricción existe porque reanudar solo puede re-ejecutar una herramienta: no hay forma de diferir una llamada de un lote sin dejar las otras sin resolver.
1691 2012
1692Si la herramienta diferida ya no está disponible cuando reanuda, el proceso sale con `stop_reason: "tool_deferred_unavailable"` e `is_error: true` antes de que se active el hook. Esto sucede cuando un servidor MCP que proporcionó la herramienta no está conectado para la sesión reanudada. El payload `deferred_tool_use` aún se incluye para que pueda identificar qué herramienta desapareció.2013Si la herramienta diferida ya no está disponible cuando reanuda, el proceso sale con `stop_reason: "tool_deferred_unavailable"` e `is_error: true` antes de que se dispare el hook. Esto sucede cuando un servidor MCP que proporcionó la herramienta no está conectado para la sesión reanudada. La carga `deferred_tool_use` aún se incluye para que pueda identificar qué herramienta desapareció.
1693 2014
1694<Note>2015<Note>
1695 `--resume` restaura el modo de permiso que estaba activo cuando se diferió la herramienta, por lo que no necesita pasar `--permission-mode` nuevamente. Las excepciones son `plan` y `bypassPermissions`, que nunca se llevan. Pasar `--permission-mode` explícitamente en reanudar anula el valor restaurado.2016 Para reanudar una sesión diferida en modo de plan, pase [`--permission-prompt-tool`](/docs/es/cli-reference#cli-flags) junto con `--resume` para que Claude Code pueda presentar el plan para aprobación. Sin él, Claude Code no restaura el modo de plan. Requiere Claude Code v2.1.246 o posterior.
2017
2018 Cuando reanuda con `-p`, Claude Code no restaura ningún otro modo de permiso almacenado. Comienza la ejecución en el modo de permiso que comenzaría una nueva ejecución `claude -p`, así que pase `--permission-mode` o `--dangerously-skip-permissions` nuevamente si la sesión diferida usó uno. Cuando reanuda con `claude --resume <session-id>` sin `-p`, Claude Code restaura el modo de permiso almacenado, con las excepciones enumeradas en [modo de permiso al reanudar](/docs/es/sessions#permission-mode-on-resume).
1696</Note>2019</Note>
1697 2020
1698<h3 id="permissionrequest">2021<h3 id="permissionrequest">
1699 PermissionRequest2022 PermissionRequest
1700</h3>2023</h3>
1701 2024
1702Se ejecuta cuando se muestra un diálogo de permiso al usuario.2025Se ejecuta cuando Claude Code está a punto de pedirle permiso para usar una herramienta. En sesiones que no pueden mostrar un aviso, como subagentes en segundo plano en [modo no interactivo](/docs/es/headless), Claude Code aún ejecuta estos hooks, y si ningún hook devuelve una decisión, deniega la llamada de herramienta.
1703Use [PermissionRequest decision control](#permissionrequest-decision-control) para permitir o denegar en nombre del usuario.2026Use [control de decisión PermissionRequest](#permissionrequest-decision-control) para permitir o denegar en nombre del usuario.
2027
2028Use este evento cuando necesite una señal en el momento en que Claude solicita permiso para usar una herramienta. Claude Code ejecuta un hook [Notification](#notification) con el tipo `permission_prompt` solo después de que el aviso ha esperado aproximadamente seis segundos.
2029
2030Claude Code no ejecuta hooks PermissionRequest para la [solicitud de red](/docs/es/sandboxing#network-isolation) de un comando en sandbox. Para obtener una señal para ese aviso, use el tipo de notificación `permission_prompt`.
1704 2031
1705Coincide en el nombre de la herramienta, los mismos valores que PreToolUse.2032Coincide en el nombre de la herramienta, los mismos valores que PreToolUse.
1706 2033
1708 Entrada de PermissionRequest2035 Entrada de PermissionRequest
1709</h4>2036</h4>
1710 2037
1711Los hooks PermissionRequest reciben campos `tool_name` y `tool_input` como los hooks PreToolUse, pero sin `tool_use_id`. Un array `permission_suggestions` opcional contiene las opciones "siempre permitir" que el usuario normalmente vería en el diálogo de permiso. La diferencia es cuándo se activa el hook: los hooks PermissionRequest se ejecutan cuando un diálogo de permiso está a punto de mostrarse al usuario, mientras que los hooks PreToolUse se ejecutan antes de la ejecución de la herramienta independientemente del estado de permiso.2038Los hooks PermissionRequest reciben campos `tool_name` e `tool_input` como los hooks PreToolUse, pero sin `tool_use_id`. Para una herramienta MCP, también reciben el objeto [`mcp_server`](#pretooluse-input). Una matriz `permission_suggestions` opcional contiene las [actualizaciones de permiso](#permission-update-entries) que Claude Code sugiere para esta solicitud, como agregar una regla de permiso o cambiar el modo de permiso.
2039
2040La matriz `permission_suggestions` no es una lista exacta de las opciones que ve, porque cada diálogo de permiso construye sus propias opciones. Algunos diálogos, como el de ediciones de archivo, no leen la matriz en absoluto y derivan sus opciones de la solicitud en sí. Un diálogo que sí la lee aún puede retener una opción cuya sugerencia permanece en la matriz, por ejemplo cuando [`allowManagedPermissionRulesOnly`](/docs/es/settings-reference#allowmanagedpermissionrulesonly) oculta opciones de guardado de reglas. También puede ofrecer opciones que no tienen entrada de sugerencia, como [**Sí, y cambiar a modo automático**](/docs/es/permission-modes#switch-permission-modes), que cambia el modo de permiso directamente en lugar de a través de una actualización de permiso.
2041
2042Los hooks PreToolUse se ejecutan antes de cada llamada de herramienta, independientemente de si necesita permiso. Los hooks PermissionRequest se ejecutan solo cuando Claude Code está a punto de pedirle permiso, o cuando de otro modo denegaría automáticamente una llamada que no puede solicitar. Ninguno de los dos eventos se dispara para [`EndConversation`](/docs/es/tools-reference#endconversation-tool-behavior).
1712 2043
1713```json theme={null}2044```json theme={null}
1714{2045{
1741 2072
1742| Campo | Descripción |2073| Campo | Descripción |
1743| :------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |2074| :------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1744| `behavior` | `"allow"` otorga el permiso, `"deny"` lo deniega. Las reglas [Deny and ask](/docs/es/permissions#manage-permissions) aún se evalúan, por lo que un hook que devuelve `"allow"` no anula una regla de denegación coincidente |2075| `behavior` | `"allow"` otorga el permiso, `"deny"` lo deniega. Las [reglas de denegación y pregunta](/docs/es/permissions#manage-permissions) aún se evalúan, por lo que un hook que devuelve `"allow"` no anula una regla de denegación coincidente |
1745| `updatedInput` | Solo para `"allow"`: modifica los parámetros de entrada de la herramienta antes de la ejecución. Reemplaza el objeto de entrada completo, así que incluya campos sin cambios junto con los modificados. La entrada modificada se re-evalúa contra reglas de denegación y pregunta |2076| `updatedInput` | Solo para `"allow"`: modifica los parámetros de entrada de la herramienta antes de la ejecución. Reemplaza el objeto de entrada completo, así que incluya campos sin cambios junto con los modificados. La entrada modificada se re-evalúa contra reglas de denegación y pregunta |
1746| `updatedPermissions` | Solo para `"allow"`: array de [entradas de actualización de permiso](#permission-update-entries) a aplicar, como agregar una regla de permiso o cambiar el modo de permiso de sesión |2077| `updatedPermissions` | Solo para `"allow"`: matriz de [entradas de actualización de permiso](#permission-update-entries) a aplicar, como agregar una regla de permiso o cambiar el modo de permiso de la sesión |
1747| `message` | Solo para `"deny"`: le dice a Claude por qué se denegó el permiso |2078| `message` | Solo para `"deny"`: dice a Claude por qué se denegó el permiso |
1748| `interrupt` | Solo para `"deny"`: si es `true`, detiene a Claude |2079| `interrupt` | Solo para `"deny"`: si es `true`, detiene a Claude |
1749 2080
2081Un hook que sale con 2 sin un objeto `decision` deja el flujo de permiso sin cambios, y su stderr se descarta. Solo el objeto `decision` puede otorgar o denegar la solicitud.
2082
1750```json theme={null}2083```json theme={null}
1751{2084{
1752 "hookSpecificOutput": {2085 "hookSpecificOutput": {
1765 Entradas de actualización de permiso2098 Entradas de actualización de permiso
1766</h4>2099</h4>
1767 2100
1768El campo de salida `updatedPermissions` y el campo de entrada [`permission_suggestions`](#permissionrequest-input) ambos usan el mismo array de objetos de entrada. Cada entrada tiene un `type` que determina sus otros campos, y un `destination` que controla dónde se escribe el cambio.2101El campo de salida `updatedPermissions` y el campo de entrada [`permission_suggestions`](#permissionrequest-input) ambos usan la misma matriz de objetos de entrada. Cada entrada tiene un `type` que determina sus otros campos, y un `destination` que controla dónde se escribe el cambio.
1769 2102
1770| `type` | Campos | Efecto |2103| `type` | Campos | Efecto |
1771| :------------------ | :--------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |2104| :------------------ | :--------------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1772| `addRules` | `rules`, `behavior`, `destination` | Agrega reglas de permiso. `rules` es un array de objetos `{toolName, ruleContent?}`. Omita `ruleContent` para coincidir con toda la herramienta. `behavior` es `"allow"`, `"deny"` o `"ask"` |2105| `addRules` | `rules`, `behavior`, `destination` | Agrega reglas de permiso. `rules` es una matriz de objetos `{toolName, ruleContent?}`. Omita `ruleContent` para hacer coincidir toda la herramienta. `behavior` es `"allow"`, `"deny"`, o `"ask"` |
1773| `replaceRules` | `rules`, `behavior`, `destination` | Reemplaza todas las reglas del `behavior` dado en el `destination` con las `rules` proporcionadas |2106| `replaceRules` | `rules`, `behavior`, `destination` | Reemplaza todas las reglas del `behavior` dado en el `destination` con las `rules` proporcionadas |
1774| `removeRules` | `rules`, `behavior`, `destination` | Elimina reglas coincidentes del `behavior` dado |2107| `removeRules` | `rules`, `behavior`, `destination` | Elimina reglas coincidentes del `behavior` dado |
1775| `setMode` | `mode`, `destination` | Cambia el modo de permiso. Los modos válidos son `default`, `auto`, `acceptEdits`, `dontAsk`, `bypassPermissions`, `plan` y `manual` como alias para `default`. El alias `manual` requiere Claude Code v2.1.200 o posterior |2108| `setMode` | `mode`, `destination` | Cambia el modo de permiso. Los modos válidos son `default`, `auto`, `acceptEdits`, `dontAsk`, `bypassPermissions`, `plan`, y `manual` como alias para `default`. El alias `manual` requiere Claude Code v2.1.200 o posterior |
1776| `addDirectories` | `directories`, `destination` | Agrega directorios de trabajo. `directories` es un array de cadenas de ruta |2109| `addDirectories` | `directories`, `destination` | Agrega directorios de trabajo. `directories` es una matriz de cadenas de ruta |
1777| `removeDirectories` | `directories`, `destination` | Elimina directorios de trabajo |2110| `removeDirectories` | `directories`, `destination` | Elimina directorios de trabajo |
1778 2111
1779<Note>2112<Note>
1780 `setMode` con `bypassPermissions` solo tiene efecto si la sesión se lanzó con modo de omisión ya disponible: `--dangerously-skip-permissions`, `--permission-mode bypassPermissions`, `--allow-dangerously-skip-permissions` o `permissions.defaultMode: "bypassPermissions"` en configuración, y el modo no está deshabilitado por [`permissions.disableBypassPermissionsMode`](/docs/es/permissions#managed-settings). De lo contrario, la actualización es una no-op. `bypassPermissions` nunca se persiste como `defaultMode` independientemente de `destination`.2113 `setMode` con `bypassPermissions` solo toma efecto si inició la sesión con modo de bypass ya disponible: `--dangerously-skip-permissions`, `--permission-mode bypassPermissions`, `--allow-dangerously-skip-permissions`, o `permissions.defaultMode: "bypassPermissions"` en [configuración de usuario, `--settings`, o configuración administrada](/docs/es/settings-reference#permissions-defaultmode). De lo contrario, la actualización es una no-op. La actualización también es una no-op cuando [`permissions.disableBypassPermissionsMode`](/docs/es/permissions#managed-settings) deshabilita el modo, o cuando la sesión comienza en [modo restringido](/docs/es/cli-reference#cli-flags).
2114
2115 `bypassPermissions` nunca se persiste como `defaultMode` independientemente de `destination`.
1781</Note>2116</Note>
1782 2117
1783El campo `destination` en cada entrada determina si el cambio permanece en memoria o persiste en un archivo de configuración.2118El campo `destination` en cada entrada determina si el cambio permanece en memoria o persiste en un archivo de configuración.
1789| `projectSettings` | `.claude/settings.json` |2124| `projectSettings` | `.claude/settings.json` |
1790| `userSettings` | `~/.claude/settings.json` |2125| `userSettings` | `~/.claude/settings.json` |
1791 2126
1792Un hook puede ecoar una de las `permission_suggestions` que recibió como su propia salida `updatedPermissions`, que es equivalente a que el usuario seleccione esa opción "siempre permitir" en el diálogo.2127Un hook puede devolver una de las `permission_suggestions` que recibió como su propia salida `updatedPermissions`.
1793 2128
1794<h3 id="posttooluse">2129<h3 id="posttooluse">
1795 PostToolUse2130 PostToolUse
1799 2134
1800Coincide en el nombre de la herramienta, los mismos valores que PreToolUse.2135Coincide en el nombre de la herramienta, los mismos valores que PreToolUse.
1801 2136
2137Coincida más ampliamente cuando el nombre de la herramienta no es el filtro correcto:
2138
2139* Para ejecutar un hook después de que cualquier herramienta se complete exitosamente, omita el `matcher` o establézcalo en `"*"`. Su hook puede entonces descubrir qué cambió por sí mismo, por ejemplo ejecutando `git status --porcelain`, que también enumera archivos sin seguimiento que `git diff` pierde. Para llamadas de herramienta que fallan, agregue el mismo hook bajo [PostToolUseFailure](#posttoolusefailure).
2140* Para ejecutar un hook cuando un archivo específico cambia en el disco, sin importar qué lo escribió, use [FileChanged](#filechanged). Claude Code no ejecuta un hook `PostToolUse` que coincida con `Edit|Write` cuando un comando `Bash` o un proceso fuera de Claude Code reescribe el mismo archivo.
2141
1802<h4 id="posttooluse-input">2142<h4 id="posttooluse-input">
1803 Entrada de PostToolUse2143 Entrada de PostToolUse
1804</h4>2144</h4>
1805 2145
1806Los hooks `PostToolUse` se activan después de que una herramienta ya se ha ejecutado exitosamente. La entrada incluye tanto `tool_input`, los argumentos enviados a la herramienta, como `tool_response`, el resultado que devolvió. El esquema exacto para ambos depende de la herramienta.2146Los hooks `PostToolUse` se disparan después de que una herramienta ya se ha ejecutado exitosamente. La entrada incluye tanto `tool_input`, los argumentos enviados a la herramienta, como `tool_response`, el resultado que devolvió. El esquema exacto para ambos depende de la herramienta. Las rutas de herramienta de archivo `tool_input` llegan en el mismo formato que para [PreToolUse](#pretooluse-input): siempre absoluto, con los separadores nativos de la plataforma, así que barras invertidas en Windows. Para una herramienta MCP, la entrada también lleva el objeto [`mcp_server`](#pretooluse-input).
1807 2147
1808```json theme={null}2148```json theme={null}
1809{2149{
1819 },2159 },
1820 "tool_response": {2160 "tool_response": {
1821 "filePath": "/path/to/file.txt",2161 "filePath": "/path/to/file.txt",
1822 "success": true2162 "type": "create"
1823 },2163 },
1824 "tool_use_id": "toolu_01ABC123...",2164 "tool_use_id": "toolu_01ABC123...",
1825 "duration_ms": 122165 "duration_ms": 12
1827```2167```
1828 2168
1829| Campo | Descripción |2169| Campo | Descripción |
1830| :------------ | :-------------------------------------------------------------------------------------------------------------------------------------- |2170| :------------ | :--------------------------------------------------------------------------------------------------------------------------------- |
1831| `duration_ms` | Opcional. Tiempo de ejecución de la herramienta en milisegundos. Excluye el tiempo dedicado a solicitudes de permiso y hooks PreToolUse |2171| `duration_ms` | Opcional. Tiempo de ejecución de la herramienta en milisegundos. Excluye el tiempo dedicado a avisos de permiso y hooks PreToolUse |
1832 2172
1833<h4 id="posttooluse-decision-control">2173<h4 id="posttooluse-decision-control">
1834 Control de decisión de PostToolUse2174 Control de decisión de PostToolUse
1837Los hooks `PostToolUse` pueden proporcionar retroalimentación a Claude después de la ejecución de la herramienta. Además de los [campos de salida JSON](#json-output) disponibles para todos los hooks, su script de hook puede devolver estos campos específicos del evento:2177Los hooks `PostToolUse` pueden proporcionar retroalimentación a Claude después de la ejecución de la herramienta. Además de los [campos de salida JSON](#json-output) disponibles para todos los hooks, su script de hook puede devolver estos campos específicos del evento:
1838 2178
1839| Campo | Descripción |2179| Campo | Descripción |
1840| :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------- |2180| :--------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1841| `decision` | `"block"` agrega la `reason` junto al resultado de la herramienta. Claude aún ve la salida original; para reemplazarla, use `updatedToolOutput` |2181| `decision` | `"block"` agrega el `reason` junto al resultado de la herramienta. Claude aún ve la salida original; para reemplazarla, use `updatedToolOutput` |
1842| `reason` | Explicación mostrada a Claude cuando `decision` es `"block"` |2182| `reason` | Explicación mostrada a Claude cuando `decision` es `"block"` |
1843| `additionalContext` | Cadena agregada al contexto de Claude junto con el resultado de la herramienta. Consulte [Agregar contexto para Claude](#add-context-for-claude) |2183| `additionalContext` | Cadena agregada al contexto de Claude junto con el resultado de la herramienta. Consulte [Agregar contexto para Claude](#add-context-for-claude) |
2184| `classifierContext` | Nota breve sobre el resultado de esta llamada para el clasificador de [modo automático](/docs/es/permission-modes#eliminate-prompts-with-auto-mode) en lugar de para Claude. Consulte [Anotar un resultado para el clasificador de modo automático](#annotate-a-result-for-the-auto-mode-classifier). Requiere Claude Code v2.1.236 o posterior |
1844| `updatedToolOutput` | Reemplaza la salida de la herramienta con el valor proporcionado antes de que se envíe a Claude. El valor debe coincidir con la forma de salida de la herramienta |2185| `updatedToolOutput` | Reemplaza la salida de la herramienta con el valor proporcionado antes de que se envíe a Claude. El valor debe coincidir con la forma de salida de la herramienta |
1845| `updatedMCPToolOutput` | Reemplaza la salida para [herramientas MCP](#match-mcp-tools) solo. Prefiera `updatedToolOutput`, que funciona para todas las herramientas |2186| `updatedMCPToolOutput` | Reemplaza la salida solo para [herramientas MCP](#match-mcp-tools). Prefiera `updatedToolOutput`, que funciona para todas las herramientas |
1846 2187
1847El ejemplo a continuación reemplaza la salida de una llamada `Bash`. El valor de reemplazo coincide con la forma de salida de la herramienta `Bash`:2188El ejemplo a continuación reemplaza la salida de una llamada `Bash`. El valor de reemplazo coincide con la forma de salida de la herramienta `Bash`:
1848 2189
1862```2203```
1863 2204
1864<Warning>2205<Warning>
1865 `updatedToolOutput` solo cambia lo que Claude ve. La herramienta ya se ha ejecutado en el momento en que se activa el hook, por lo que cualquier archivo escrito, comando ejecutado o solicitud de red enviada ya ha tenido efecto. La telemetría como spans de herramientas OpenTelemetry y eventos de análisis también capturan la salida original antes de que se ejecute el hook. Para evitar o modificar una llamada a herramienta antes de que se ejecute, use un hook [PreToolUse](#pretooluse) en su lugar.2206 `updatedToolOutput` solo cambia lo que Claude ve. La herramienta ya se ha ejecutado en el momento en que se dispara el hook, por lo que cualquier archivo escrito, comando ejecutado o solicitud de red enviada ya ha tenido efecto. La telemetría como tramos de herramientas OpenTelemetry y eventos de análisis también captura la salida original antes de que se ejecute el hook. Para evitar o modificar una llamada de herramienta antes de que se ejecute, use un hook [PreToolUse](#pretooluse) en su lugar.
1866 2207
1867 El valor de reemplazo debe coincidir con la forma de salida de la herramienta. Las herramientas integradas devuelven objetos estructurados en lugar de cadenas simples. Por ejemplo, `Bash` devuelve un objeto con campos `stdout`, `stderr`, `interrupted` e `isImage`. Para herramientas integradas, un valor que no coincida con el esquema de salida de la herramienta se ignora y se usa la salida original. La salida de herramientas MCP se pasa sin validación de esquema. Eliminar detalles de error que Claude necesita puede hacer que continúe con una suposición falsa.2208 El valor de reemplazo debe coincidir con la forma de salida de la herramienta. Las herramientas integradas devuelven objetos estructurados en lugar de cadenas simples. Por ejemplo, `Bash` devuelve un objeto con campos `stdout`, `stderr`, `interrupted`, e `isImage`. Para herramientas integradas, un valor que no coincida con el esquema de salida de la herramienta se ignora y se usa la salida original. La salida de herramientas MCP se pasa sin validación de esquema. Eliminar detalles de error que Claude necesita puede hacer que continúe con una suposición falsa.
2209</Warning>
2210
2211<h4 id="annotate-a-result-for-the-auto-mode-classifier">
2212 Anotar un resultado para el clasificador de modo automático
2213</h4>
2214
2215Devuelva `classifierContext` para enviar una nota breve sobre el resultado de la llamada de herramienta al clasificador de [modo automático](/docs/es/permission-modes#eliminate-prompts-with-auto-mode) en lugar de a Claude. El clasificador [nunca recibe resultados de herramientas en sí](/docs/es/permission-modes#how-the-classifier-evaluates-actions), por lo que este campo es la forma admitida de decirle algo sobre lo que devolvió una llamada antes de que revise acciones posteriores. El campo requiere Claude Code v2.1.236 o posterior.
2216
2217El ejemplo a continuación dice al clasificador de dónde vino la salida de una consulta:
2218
2219```json theme={null}
2220{
2221 "hookSpecificOutput": {
2222 "hookEventName": "PostToolUse",
2223 "classifierContext": "This query ran against the staging database, not production."
2224 }
2225}
2226```
2227
2228Cuánto peso da el clasificador a la nota depende de dónde configuró el hook:
2229
2230* **Hooks configurados en Claude Code**: para hooks de archivos de configuración, plugins, skills y frontmatter del agente, el clasificador trata la nota como contexto no verificado proporcionado por la aplicación. La nota nunca establece la intención del usuario, y si afirma que aprobó o solicitó algo, el clasificador verifica esa afirmación contra sus propios mensajes en la conversación
2231* **Devoluciones de llamada de Agent SDK en proceso**: cuando una aplicación que integra Claude Code registra el hook como una [devolución de llamada de SDK de TypeScript](/docs/es/agent-sdk/hooks) y devuelve la nota durante la sesión en vivo, el clasificador puede pesar una declaración del usuario retransmitida en la nota como intención del usuario. Tal declaración puede satisfacer un requisito de consentimiento que el clasificador aceptaría de un mensaje que envía, pero nunca levanta un bloqueo que su propio mensaje tampoco podría levantar. Después de que se reanuda una sesión, Claude Code trata las notas restauradas como contexto no verificado. Cuando hooks de ambos grupos anotan la misma llamada, el clasificador trata la nota combinada como contexto no verificado
2232
2233Claude Code aplica estos límites al entregar la nota:
2234
2235* **Longitud**: Claude Code limita las notas para una llamada de herramienta a 2,000 caracteres y trunca el resto. El límite se comparte en cada hook que responde a esa llamada
2236* **Solo respuestas sincrónicas**: Claude Code ignora el campo en la respuesta de un hook que [se ejecuta en segundo plano](#run-hooks-in-the-background), porque esa respuesta llega después de que Claude Code registra el resultado de la herramienta
2237* **Llamadas que el clasificador no registra**: la transcripción del clasificador omite búsquedas de solo lectura como lecturas de archivo y búsquedas. Claude Code descarta una nota adjunta a una de esas llamadas
2238* **Interacción con reescrituras**: cuando la nota describe salida que está reemplazando con `updatedToolOutput`, devuelva ambos campos en la misma respuesta del hook. Claude Code descarta la nota si esa reescritura se rechaza u otro hook la reemplaza. Claude Code entrega una nota que devuelve sin una reescritura incluso cuando otro hook reescribe la salida
2239
2240<Warning>
2241 El clasificador lee el contenido que coloca en `classifierContext` como información del anfitrión de la aplicación de la sesión, así que no copie salida de herramienta no confiable o texto de terceros en él. Mantenga la nota a una afirmación breve sobre esta única llamada, como un hecho sobre su origen o una declaración del usuario sobre ella; no use el campo para entregar mensajes no relacionados o un flujo de eventos.
1868</Warning>2242</Warning>
1869 2243
1870<h3 id="posttoolusefailure">2244<h3 id="posttoolusefailure">
1871 PostToolUseFailure2245 PostToolUseFailure
1872</h3>2246</h3>
1873 2247
1874Se ejecuta cuando falla una herramienta que comenzó a ejecutarse: la herramienta lanzó un error, o una herramienta MCP devolvió un resultado de error. Use esto para registrar fallos, enviar alertas o proporcionar retroalimentación correctiva a Claude.2248Se ejecuta cuando una herramienta que comenzó a ejecutarse falla: la herramienta lanzó un error, o una herramienta MCP devolvió un resultado de error. Úselo para registrar fallas, enviar alertas o proporcionar retroalimentación correctiva a Claude.
1875 2249
1876Coincide en el nombre de la herramienta, los mismos valores que PreToolUse.2250Coincide en el nombre de la herramienta, los mismos valores que PreToolUse.
1877 2251
1878<Note>2252<Note>
1879 Este evento no se activa para llamadas a herramientas rechazadas antes de la ejecución: un nombre de herramienta desconocido, entrada que falla en validación de esquema o específica de herramienta, o una denegación de permiso. Los rechazos de validación se devuelven como resultados `tool_use_error` y ocurren antes de que se ejecuten los hooks, por lo que no activan ni `PreToolUse` ni este evento. Las denegaciones de permiso activan `PreToolUse` pero no este evento; consulte [PermissionDenied](#permissiondenied).2253 Este evento no se dispara para llamadas de herramienta rechazadas antes de la ejecución: un nombre de herramienta desconocido, entrada que falla en validación de esquema o específica de herramienta, o una denegación de permiso. Los rechazos de validación se devuelven como resultados `tool_use_error` y ocurren antes de que se ejecuten los hooks, por lo que no disparan ni `PreToolUse` ni `PostToolUseFailure`. Las denegaciones de permiso disparan `PreToolUse` pero no este evento; consulte [PermissionDenied](#permissiondenied).
1880</Note>2254</Note>
1881 2255
1882<h4 id="posttoolusefailure-input">2256<h4 id="posttoolusefailure-input">
1883 Entrada de PostToolUseFailure2257 Entrada de PostToolUseFailure
1884</h4>2258</h4>
1885 2259
1886Los hooks PostToolUseFailure reciben los mismos campos `tool_name` y `tool_input` que PostToolUse, junto con información de error como campos de nivel superior:2260Los hooks PostToolUseFailure reciben los mismos campos `tool_name` e `tool_input` que PostToolUse, junto con información de error como campos de nivel superior. Para una herramienta MCP, también reciben el objeto [`mcp_server`](#pretooluse-input). Por ejemplo, un comando `npm test` fallido podría entregar:
1887 2261
1888```json theme={null}2262```json theme={null}
1889{2263{
1898 "description": "Run test suite"2272 "description": "Run test suite"
1899 },2273 },
1900 "tool_use_id": "toolu_01ABC123...",2274 "tool_use_id": "toolu_01ABC123...",
1901 "error": "Command exited with non-zero status code 1",2275 "error": "Exit code 1\nError: Cannot find module 'express'",
1902 "is_interrupt": false,2276 "is_interrupt": false,
1903 "duration_ms": 41872277 "duration_ms": 4187
1904}2278}
1905```2279```
1906 2280
1907| Campo | Descripción |2281| Campo | Descripción |
1908| :------------- | :-------------------------------------------------------------------------------------------------------------------------------------- |2282| :------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1909| `error` | Cadena que describe qué salió mal |2283| `error` | Cadena que describe qué salió mal. El formato depende de la herramienta que falló |
1910| `is_interrupt` | Booleano opcional que indica si el fallo fue causado por interrupción del usuario |2284| `is_interrupt` | Booleano opcional. Verdadero cuando el fallo llegó a Claude Code como una interrupción en lugar de como un error que reportó la herramienta. Cancelar una herramienta en ejecución no dispara este hook; el resultado de la herramienta lleva el mensaje de interrupción en su lugar |
1911| `duration_ms` | Opcional. Tiempo de ejecución de la herramienta en milisegundos. Excluye el tiempo dedicado a solicitudes de permiso y hooks PreToolUse |2285| `duration_ms` | Opcional. Tiempo de ejecución de la herramienta en milisegundos. Excluye el tiempo dedicado a avisos de permiso y hooks PreToolUse |
2286
2287La cadena `error` es generalmente el mismo texto que Claude recibe como resultado fallido de la herramienta. Su formato varía según la herramienta y el fallo. Clave su hook en `tool_name`, `is_interrupt`, y la primera línea `Exit code N`; trate el resto de la cadena como texto de visualización, no como un formato estable.
2288
2289* Para Bash y PowerShell, un comando que se ejecutó y salió produce una primera línea `Exit code N`, luego cualquier salida que el comando produjo como un bloque con stdout y stderr intercalados
2290* Una carga también puede llevar un mensaje de fallo desnudo sin línea de código de salida, cuando Claude Code no pudo iniciar el proceso de shell en sí
2291* Claude Code trunca a mitad de cadenas largas alrededor de un marcador `... [N characters truncated] ...`, e puede insertar líneas propias, como `Command timed out after 2m 0s`
1912 2292
1913<h4 id="posttoolusefailure-decision-control">2293<h4 id="posttoolusefailure-decision-control">
1914 Control de decisión de PostToolUseFailure2294 Control de decisión de PostToolUseFailure
1933 PostToolBatch2313 PostToolBatch
1934</h3>2314</h3>
1935 2315
1936Se ejecuta una vez después de que cada llamada a herramienta en un lote se haya resuelto, antes de que Claude Code envíe la siguiente solicitud al modelo. `PostToolUse` se activa una vez por herramienta, lo que significa que se activa simultáneamente cuando Claude hace llamadas a herramientas paralelas. `PostToolBatch` se activa exactamente una vez con el lote completo, por lo que es el lugar correcto para inyectar contexto que dependa del conjunto de herramientas que se ejecutaron en lugar de cualquier herramienta individual. No hay matcher para este evento.2316Se ejecuta una vez después de que cada llamada de herramienta en un lote se haya resuelto, antes de que Claude Code envíe la siguiente solicitud al modelo. `PostToolUse` se dispara una vez por herramienta, lo que significa que se dispara simultáneamente cuando Claude realiza llamadas de herramienta paralelas. `PostToolBatch` se dispara exactamente una vez con el lote completo, por lo que es el lugar correcto para inyectar contexto que dependa del conjunto de herramientas que se ejecutaron en lugar de en cualquier herramienta única. No hay matcher para este evento.
1937 2317
1938<h4 id="posttoolbatch-input">2318<h4 id="posttoolbatch-input">
1939 Entrada de PostToolBatch2319 Entrada de PostToolBatch
1940</h4>2320</h4>
1941 2321
1942Además de los [campos de entrada comunes](#common-input-fields), los hooks PostToolBatch reciben `tool_calls`, un array que describe cada llamada a herramienta en el lote:2322Además de los [campos de entrada comunes](#common-input-fields), los hooks PostToolBatch reciben `tool_calls`, una matriz que describe cada llamada de herramienta en el lote:
1943 2323
1944```json theme={null}2324```json theme={null}
1945{2325{
1965}2345}
1966```2346```
1967 2347
1968`tool_response` contiene el mismo contenido que el modelo recibe en el bloque `tool_result` correspondiente. El valor es una cadena serializada o un array de bloque de contenido, exactamente como lo emitió la herramienta. Para `Read`, eso significa texto con prefijo de número de línea en lugar de contenidos de archivo sin procesar. Las respuestas pueden ser grandes, así que analice solo los campos que necesita.2348`tool_response` contiene el mismo contenido que el modelo recibe en el bloque `tool_result` correspondiente. El valor es una cadena serializada o matriz de bloques de contenido, exactamente como lo emitió la herramienta. Para `Read`, eso significa texto con prefijo de número de línea en lugar de contenidos de archivo sin procesar. Las respuestas pueden ser grandes, así que analice solo los campos que necesita.
1969 2349
1970<Note>2350<Note>
1971 La forma de `tool_response` difiere de la de `PostToolUse`. `PostToolUse` pasa el objeto `Output` estructurado de la herramienta, como `{filePath: "...", success: true}` para `Write`; `PostToolBatch` pasa el contenido `tool_result` serializado que el modelo ve.2351 La forma `tool_response` difiere de la de `PostToolUse`. `PostToolUse` pasa el objeto `Output` estructurado de la herramienta, como `{filePath: "...", type: "create"}` para `Write`; `PostToolBatch` pasa el contenido `tool_result` serializado que ve el modelo.
1972</Note>2352</Note>
1973 2353
1974<h4 id="posttoolbatch-decision-control">2354<h4 id="posttoolbatch-decision-control">
1978Los hooks `PostToolBatch` pueden inyectar contexto para Claude. Además de los [campos de salida JSON](#json-output) disponibles para todos los hooks, su script de hook puede devolver estos campos específicos del evento:2358Los hooks `PostToolBatch` pueden inyectar contexto para Claude. Además de los [campos de salida JSON](#json-output) disponibles para todos los hooks, su script de hook puede devolver estos campos específicos del evento:
1979 2359
1980| Campo | Descripción |2360| Campo | Descripción |
1981| :------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |2361| :------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1982| `additionalContext` | Cadena de contexto inyectada una vez antes de la siguiente llamada al modelo. Consulte [Agregar contexto para Claude](#add-context-for-claude) para detalles de entrega, qué poner en él y cómo las sesiones reanudadas manejan valores pasados |2362| `additionalContext` | Cadena de contexto inyectada una vez antes de la siguiente llamada del modelo. Consulte [Agregar contexto para Claude](#add-context-for-claude) para detalles de entrega, qué poner en él y cómo las sesiones reanudadas manejan valores pasados |
1983 2363
1984```json theme={null}2364```json theme={null}
1985{2365{
1990}2370}
1991```2371```
1992 2372
1993Devolver `decision: "block"` o `continue: false` detiene el bucle agentico antes de la siguiente llamada al modelo.2373Devolver `decision: "block"` o `continue: false` detiene el bucle agéntico antes de la siguiente llamada del modelo. El mensaje de bloqueo viene del JSON `reason` o `stopReason`, o de stderr en salida 2. Lo ve como una advertencia en la transcripción, y permanece en la conversación, por lo que Claude lo ve cuando la conversación continúa.
1994 2374
1995<h3 id="permissiondenied">2375<h3 id="permissiondenied">
1996 PermissionDenied2376 PermissionDenied
1997</h3>2377</h3>
1998 2378
1999Se ejecuta cuando el clasificador de [modo automático](/docs/es/permission-modes#eliminate-prompts-with-auto-mode) deniega una llamada a herramienta. Este hook solo se activa en modo automático: no se ejecuta cuando deniega manualmente un diálogo de permiso, cuando un hook `PreToolUse` bloquea una llamada o cuando una regla `deny` coincide. Use esto para registrar denegaciones del clasificador, ajustar configuración o decirle al modelo que puede reintentar la llamada a herramienta.2379Se ejecuta cuando [modo automático](/docs/es/permission-modes#eliminate-prompts-with-auto-mode) deniega una llamada de herramienta, incluido cuando deniega sin un veredicto del clasificador porque [una verificación de seguridad separada del modo automático rechazó la propia solicitud del clasificador](/docs/es/errors#auto-mode-cannot-determine-the-safety-of-an-action) o su respuesta no se analizó. Este hook solo se dispara en modo automático: no se ejecuta cuando deniega manualmente un diálogo de permiso, cuando un hook `PreToolUse` bloquea una llamada, o cuando una regla `deny` coincide. Úselo para registrar denegaciones, ajustar configuración o decirle al modelo que puede reintentar la llamada de herramienta.
2000 2380
2001Coincide en el nombre de la herramienta, los mismos valores que PreToolUse.2381Coincide en el nombre de la herramienta, los mismos valores que PreToolUse.
2002 2382
2004 Entrada de PermissionDenied2384 Entrada de PermissionDenied
2005</h4>2385</h4>
2006 2386
2007Además de los [campos de entrada comunes](#common-input-fields), los hooks PermissionDenied reciben `tool_name`, `tool_input`, `tool_use_id` y `reason`.2387Además de los [campos de entrada comunes](#common-input-fields), los hooks PermissionDenied reciben `tool_name`, `tool_input`, `tool_use_id`, y `reason`. Para una herramienta MCP, también reciben el objeto [`mcp_server`](#pretooluse-input).
2008 2388
2009```json theme={null}2389```json theme={null}
2010{2390{
2019 "description": "Clean build directory"2399 "description": "Clean build directory"
2020 },2400 },
2021 "tool_use_id": "toolu_01ABC123...",2401 "tool_use_id": "toolu_01ABC123...",
2022 "reason": "Auto mode denied: command targets a path outside the project"2402 "reason": "[Irreversible Local Destruction]"
2023}2403}
2024```2404```
2025 2405
2026| Campo | Descripción |2406| Campo | Descripción |
2027| :------- | :------------------------------------------------------------------------------ |2407| :------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2028| `reason` | La explicación del clasificador para por qué se denegó la llamada a herramienta |2408| `reason` | La razón de la denegación. Para un veredicto del clasificador, en la mayoría de sesiones nombra la regla coincidente entre corchetes, como `[Data Exfiltration]`; consulte [Revisar denegaciones](/docs/es/auto-mode-config#review-denials) para las otras formas. Para una [denegación sin veredicto](#permissiondenied-decision-control), comienza con `Auto mode could not evaluate this action and is blocking it for safety`. Para una denegación porque el modelo del clasificador no estaba disponible, es el texto fijo `Classifier unavailable` |
2029 2409
2030<h4 id="permissiondenied-decision-control">2410<h4 id="permissiondenied-decision-control">
2031 Control de decisión de PermissionDenied2411 Control de decisión de PermissionDenied
2032</h4>2412</h4>
2033 2413
2034Los hooks PermissionDenied pueden decirle al modelo que puede reintentar la llamada a herramienta denegada. Devuelva un objeto JSON con `hookSpecificOutput.retry` establecido en `true`:2414Los hooks PermissionDenied pueden decirle al modelo que puede reintentar la llamada de herramienta denegada. Devuelva un objeto JSON con `hookSpecificOutput.retry` establecido en `true`:
2035 2415
2036```json theme={null}2416```json theme={null}
2037{2417{
2042}2422}
2043```2423```
2044 2424
2045Cuando `retry` es `true`, Claude Code agrega un mensaje a la conversación diciéndole al modelo que puede reintentar la llamada a herramienta. La denegación en sí no se revierte. Si su hook no devuelve JSON, o devuelve `retry: false`, la denegación se mantiene y el modelo recibe el mensaje de rechazo original.2425Cuando `retry` es `true`, Claude Code agrega un mensaje a la conversación diciéndole al modelo que puede reintentar la llamada de herramienta. Claude Code no revierte la denegación en sí. Si su hook no devuelve JSON, o devuelve `retry: false`, la denegación se mantiene y el modelo recibe el mensaje de rechazo original.
2426
2427Claude Code ignora `retry: true` cuando el clasificador produjo [ningún veredicto sobre la acción](/docs/es/errors#auto-mode-cannot-determine-the-safety-of-an-action): su respuesta no se analizó, o una verificación de seguridad separada del modo automático rechazó la propia solicitud del clasificador. Para esas denegaciones, Claude Code ya le dice al modelo en el mensaje de rechazo si reintentar más tarde o continuar.
2046 2428
2047<h3 id="notification">2429<h3 id="notification">
2048 Notification2430 Notification
2050 2432
2051Se ejecuta cuando Claude Code envía notificaciones. Coincide en el tipo de notificación. Omita el matcher para ejecutar hooks para todos los tipos de notificación.2433Se ejecuta cuando Claude Code envía notificaciones. Coincide en el tipo de notificación. Omita el matcher para ejecutar hooks para todos los tipos de notificación.
2052 2434
2053| Matcher | Cuándo se activa |2435Recibe estos eventos de hook incluso con notificaciones de escritorio desactivadas: la configuración `preferredNotifChannel`, incluida `notifications_disabled`, cambia solo cómo se le alerta, no si su hook se ejecuta.
2054| :--------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- |2436
2055| `permission_prompt` | Claude necesita que apruebe un uso de herramienta |2437| Matcher | Cuándo se dispara |
2056| `idle_prompt` | Claude está hecho y esperando su siguiente prompt |2438| :--------------------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2439| `permission_prompt` | Claude necesita su permiso para usar una herramienta o una [solicitud de red](/docs/es/sandboxing#network-isolation) de un comando en sandbox, y el aviso ha esperado aproximadamente seis segundos |
2440| `idle_prompt` | Claude terminó de responder hace aproximadamente 60 segundos y no ha escrito desde entonces |
2057| `auth_success` | La autenticación se completa |2441| `auth_success` | La autenticación se completa |
2058| `elicitation_dialog` | Un servidor MCP abre un formulario de elicitación |2442| `elicitation_dialog` | Un servidor MCP abre un formulario de elicitación y no ha escrito durante aproximadamente seis segundos |
2059| `elicitation_complete` | Un formulario de elicitación MCP se envía o se descarta |2443| `elicitation_url_dialog` | Un servidor MCP le pide que abra una URL de navegador y no ha escrito durante aproximadamente seis segundos |
2060| `elicitation_response` | Una respuesta de elicitación MCP se envía de vuelta al servidor |2444| `elicitation_complete` | Un servidor MCP reporta que una [elicitación de modo URL](#elicitation-input) está completa |
2061| `agent_needs_input` | Una sesión en segundo plano comienza a esperar su entrada. Se activa solo mientras [agent view](/docs/es/agent-view) está abierto en una terminal |2445| `elicitation_response` | Se envía una respuesta de elicitación de MCP de vuelta al servidor |
2062| `agent_completed` | Una sesión en segundo plano termina o falla. Se activa solo mientras [agent view](/docs/es/agent-view) está abierto en una terminal |2446| `agent_needs_input` | Una sesión de fondo comienza a esperar su entrada mientras [vista de agente](/docs/es/agent-view) está abierta en una terminal, o la sesión actual le hace una pregunta de configuración de terminal de [compañero de equipo del agente](/docs/es/agent-teams#choose-a-display-mode) y no ha escrito durante aproximadamente seis segundos |
2447| `agent_completed` | Una sesión de fondo se completa o falla. Se dispara solo mientras [vista de agente](/docs/es/agent-view) está abierta en una terminal |
2448| `quota_auto_resume_fired` | Claude Code continúa su tarea después de que un límite de uso de claude.ai la pausó: en el reinicio, o antes cuando algo que hace en Claude Code durante la espera, como agregar créditos de uso, actualizar su plan o cambiar modelos, hace que el uso esté disponible nuevamente, con la [excepción de configuración de modelo](/docs/es/interactive-mode#wait-for-a-usage-limit-to-reset) |
2449| `quota_auto_resume_stale` | Un límite de uso de claude.ai se reinició mientras su computadora dormía durante más de aproximadamente 30 minutos. Claude Code espera a que presione `Enter` en lugar de continuar. Después de un sueño más corto continúa y dispara `quota_auto_resume_fired` en su lugar |
2450| `quota_auto_resume_disabled` | Claude Code termina su espera por un límite de uso de claude.ai sin continuar su tarea: [`autoContinueAtUsageLimit`](/docs/es/settings-reference#autocontinueatusagelimit) se desactivó o el reinicio se movió más de 24 horas en el futuro durante una espera que Claude Code comenzó por su cuenta, la tarea continuada siguió golpeando el límite, o la continuación fue bloqueada antes de llegar al modelo. No se dispara cuando presiona `Esc` o `Ctrl+C`, o elige **No continuar automáticamente** |
2063 2451
2064Los tipos `agent_needs_input` y `agent_completed` requieren Claude Code v2.1.198 o posterior.2452Los tipos `agent_needs_input` y `agent_completed` requieren Claude Code v2.1.198 o posterior.
2065 2453
2066Use matchers separados para ejecutar diferentes controladores dependiendo del tipo de notificación. Esta configuración desencadena un script de alerta específico de permiso cuando Claude necesita aprobación de permiso y una notificación diferente cuando Claude ha estado inactivo:2454Los tipos `quota_auto_resume_fired`, `quota_auto_resume_stale`, y `quota_auto_resume_disabled` requieren Claude Code v2.1.234 o posterior.
2455
2456En sesiones de terminal, `permission_prompt` para una solicitud de red de un comando en sandbox requiere Claude Code v2.1.246 o posterior.
2457
2458`agent_needs_input` para una pregunta de configuración de terminal de compañero requiere Claude Code v2.1.248 o posterior.
2459
2460<Note>
2461 Los tipos `permission_prompt`, `idle_prompt`, `elicitation_dialog`, y `elicitation_url_dialog` comparten su tiempo con notificaciones de escritorio, así que en sesiones de terminal solo los ve cuando parece que está lejos de la terminal:
2462
2463 * Espere `permission_prompt` una vez que no haya escrito durante aproximadamente seis segundos. El temporizador comienza cuando aparece el aviso de permiso, y cada pulsación de tecla lo difiere. Para ejecutar un hook inmediatamente cuando Claude solicita permiso para usar una herramienta, use [PermissionRequest](#permissionrequest) en su lugar.
2464 * Espere `idle_prompt` aproximadamente 60 segundos después de que Claude termine de responder, y solo si no ha escrito desde entonces. Claude Code no envía `idle_prompt` mientras espera a que se reinicie un límite de uso de claude.ai. Cuando la espera termina por sí sola, uno de los tipos `quota_auto_resume_*` se dispara en su lugar.
2465 * Espere `elicitation_dialog` para un formulario de elicitación, o `elicitation_url_dialog` para una solicitud de URL de navegador, una vez que no haya escrito durante aproximadamente seis segundos. Ambos comparten la misma puerta de seis segundos que `permission_prompt`: el temporizador comienza cuando aparece el diálogo, y cada pulsación de tecla lo difiere.
2466
2467 Una solicitud de permiso o elicitación que llega mientras otro diálogo está en pantalla mantiene la misma puerta de seis segundos, cronometrada desde cuando llega la solicitud. Su notificación puede llegar a usted mientras la solicitud aún espera detrás del diálogo abierto.
2468</Note>
2469
2470Claude Code cronometra `permission_prompt` diferente en sesiones donde envía solicitudes de permiso a la devolución de llamada [`canUseTool`](/docs/es/agent-sdk/user-input) de Agent SDK, que es cómo Claude Desktop y la extensión VS Code alojan Claude Code:
2471
2472* Espere `permission_prompt` aproximadamente seis segundos después de que Claude solicita permiso. Claude Code no lo difiere mientras escribe.
2473* Si usted o un hook [PermissionRequest](#permissionrequest) responden antes, Claude Code no ejecuta `permission_prompt`.
2474* Establezca [`CLAUDE_CODE_DISABLE_PERMISSION_PROMPT_NOTIFY_HOOKS`](/docs/es/env-vars) en `1` para desactivar `permission_prompt` en estas sesiones.
2475
2476Antes de v2.1.233, `permission_prompt` no se disparaba en estas sesiones.
2477
2478Use matchers separados para ejecutar diferentes manejadores dependiendo del tipo de notificación. Esta configuración dispara un script de alerta específico de permiso cuando Claude necesita aprobación de permiso y una notificación diferente cuando Claude ha estado inactivo:
2067 2479
2068```json theme={null}2480```json theme={null}
2069{2481{
2096 Entrada de Notification2508 Entrada de Notification
2097</h4>2509</h4>
2098 2510
2099Además de los [campos de entrada comunes](#common-input-fields), los hooks Notification reciben `message` con el texto de notificación, un `title` opcional y `notification_type` que indica qué tipo se activó.2511Además de los [campos de entrada comunes](#common-input-fields), los hooks Notification reciben `message` con el texto de notificación, un `title` opcional, y `notification_type` que indica qué tipo se disparó.
2100 2512
2101```json theme={null}2513```json theme={null}
2102{2514{
2110}2522}
2111```2523```
2112 2524
2113Los hooks Notification no pueden bloquear o modificar notificaciones. Están destinados a efectos secundarios como reenviar la notificación a un servicio externo. Los [campos de salida JSON](#json-output) comunes como `systemMessage` se aplican.2525Los hooks Notification no pueden bloquear o modificar notificaciones. Claude Code descarta sus campos `systemMessage` y `continue` pero aún emite [`terminalSequence`](#emit-terminal-notifications), en el que se basa el ejemplo de notificación de escritorio. Los hooks Notification están destinados a efectos secundarios como reenviar la notificación a un servicio externo.
2114 2526
2115<h3 id="subagentstart">2527<h3 id="subagentstart">
2116 SubagentStart2528 SubagentStart
2117</h3>2529</h3>
2118 2530
2119Se ejecuta cuando se genera un subagente de Claude Code a través de la herramienta Agent. Admite matchers para filtrar por nombre de tipo de agente. Para agentes integrados, este es el nombre del agente como `general-purpose`, `Explore` o `Plan`. Para [subagentes personalizados](/docs/es/sub-agents), este es el campo `name` del frontmatter del agente, no el nombre del archivo.2531Se ejecuta cuando Claude genera un subagente con la herramienta Agent, cuando Claude [reanuda un subagente](/docs/es/sub-agents#resume-subagents), y cada vez que un compañero de [equipo de agente](/docs/es/agent-teams) en proceso maneja un nuevo mensaje. Admite matchers para filtrar por nombre de tipo de agente. Para agentes integrados, este es el nombre del agente como `general-purpose`, `Explore`, o `Plan`. Para [subagentes personalizados](/docs/es/sub-agents), este es el campo `name` del frontmatter del agente, no el nombre del archivo.
2120 2532
2121Para subagentes enviados por un [plugin](/docs/es/plugins), el tipo de agente es el identificador con alcance de plugin como `my-plugin:reviewer`, no el nombre del frontmatter desnudo. El colon coloca un nombre con alcance de plugin en la ruta de expresión regular, así que ancle el matcher con `^` y `$` para una coincidencia exacta: `^my-plugin:reviewer$`.2533Para subagentes enviados por un [plugin](/docs/es/plugins), el tipo de agente es el identificador con alcance de plugin como `my-plugin:reviewer`, no el nombre de frontmatter desnudo. Los dos puntos colocan un nombre con alcance de plugin en la ruta de expresión regular, así que ancle el matcher con `^` y `$` para una coincidencia exacta: `^my-plugin:reviewer$`.
2122 2534
2123<h4 id="subagentstart-input">2535<h4 id="subagentstart-input">
2124 Entrada de SubagentStart2536 Entrada de SubagentStart
2137}2549}
2138```2550```
2139 2551
2140Los hooks SubagentStart no pueden bloquear la creación de subagentes, pero pueden inyectar contexto en el subagente. Además de los [campos de salida JSON](#json-output) disponibles para todos los hooks, puede devolver:2552Los hooks SubagentStart no pueden bloquear la creación del subagente, pero pueden inyectar contexto en el subagente. Además de los [campos de salida JSON](#json-output) disponibles para todos los hooks, puede devolver:
2141 2553
2142| Campo | Descripción |2554| Campo | Descripción |
2143| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |2555| :------------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
2152}2564}
2153```2565```
2154 2566
2567Cuando el hook se ejecuta nuevamente para el mismo subagente, Claude Code inyecta el contexto devuelto solo cuando el contexto del subagente no contiene ya la copia de una ejecución anterior. La copia inyectada al inicio permanece en su lugar, dejando el [caché de prompt](/docs/es/prompt-caching#subagents-and-the-cache) del subagente intacto. Después de que la [compactación automática](/docs/es/sub-agents#auto-compaction) descarta esa copia, Claude Code inyecta el contexto de la siguiente ejecución nuevamente.
2568
2155<h3 id="subagentstop">2569<h3 id="subagentstop">
2156 SubagentStop2570 SubagentStop
2157</h3>2571</h3>
2162 Entrada de SubagentStop2576 Entrada de SubagentStop
2163</h4>2577</h4>
2164 2578
2165Además de los [campos de entrada comunes](#common-input-fields), los hooks SubagentStop reciben `stop_hook_active`, `agent_id`, `agent_type`, `agent_transcript_path` y `last_assistant_message`. El campo `agent_type` es el valor usado para filtrado de matcher. El `transcript_path` es la transcripción de la sesión principal, mientras que `agent_transcript_path` es la propia transcripción del subagente almacenada en una carpeta `subagents/` anidada. El campo `last_assistant_message` contiene el contenido de texto de la respuesta final del subagente, por lo que los hooks pueden acceder a él sin analizar el archivo de transcripción.2579Además de los [campos de entrada comunes](#common-input-fields), los hooks SubagentStop reciben `stop_hook_active`, `agent_id`, `agent_type`, `agent_transcript_path`, y `last_assistant_message`. El campo `agent_type` es el valor utilizado para filtrado de matcher. El `transcript_path` es la transcripción de la sesión principal, mientras que `agent_transcript_path` es la propia transcripción del subagente almacenada en una carpeta `subagents/` anidada. El campo `last_assistant_message` contiene el contenido de texto de la respuesta final del subagente, por lo que los hooks pueden acceder a él sin analizar el archivo de transcripción.
2580
2581En Claude Code v2.1.271 o posterior, un subagente que se ejecuta con la herramienta [`SubagentHandback`](/docs/es/tools-reference) entrega su informe a través de esa herramienta antes de que se detenga. El campo `last_assistant_message` luego contiene el texto de cierre del subagente, si lo hay, que no es el informe entregado. El informe es la entrada `message` de esa llamada, que un hook `PreToolUse` o `PostToolUse` que coincida en `SubagentHandback` recibe como `tool_input.message`.
2166 2582
2167Los hooks SubagentStop también reciben los arrays `background_tasks` y `session_crons` descritos bajo [Stop input](#stop-input), disponibles en Claude Code v2.1.145 o posterior. Ambos arrays están limitados a la sesión padre, no al subagente.2583Los hooks SubagentStop también reciben las matrices `background_tasks` y `session_crons` descritas en [Entrada de Stop](#stop-input). Ambas matrices tienen alcance a la sesión padre, no al subagente.
2168 2584
2169```json theme={null}2585```json theme={null}
2170{2586{
2183}2599}
2184```2600```
2185 2601
2186Los hooks SubagentStop usan el mismo formato de control de decisión que los [hooks Stop](#stop-decision-control), incluyendo `hookSpecificOutput.additionalContext` con `hookEventName` establecido en `"SubagentStop"`, para retroalimentación sin error que mantiene el subagente en ejecución. Devolver `decision: "block"` con una `reason` mantiene el subagente en ejecución y entrega `reason` al subagente como su siguiente instrucción. Para inyectar contexto en la sesión padre después de que un subagente regresa, use un hook [`PostToolUse`](#posttooluse) en la herramienta `Agent` en su lugar.2602Los hooks SubagentStop usan el mismo formato de control de decisión que [hooks Stop](#stop-decision-control), incluido `hookSpecificOutput.additionalContext` con `hookEventName` establecido en `"SubagentStop"`, para retroalimentación sin error que mantiene el subagente ejecutándose. Devolver `decision: "block"` con un `reason` mantiene el subagente ejecutándose y entrega `reason` al subagente como su siguiente instrucción. Un hook que bloquea saliendo con 2 entrega su mensaje stderr de la misma manera. Para inyectar contexto en la sesión padre después de que un subagente devuelve, use un hook [`PostToolUse`](#posttooluse) en la herramienta `Agent` en su lugar.
2187 2603
2188<h3 id="taskcreated">2604<h3 id="taskcreated">
2189 TaskCreated2605 TaskCreated
2190</h3>2606</h3>
2191 2607
2192Se ejecuta cuando se está creando una tarea a través de la herramienta `TaskCreate`. Use esto para aplicar convenciones de nomenclatura, requerir descripciones de tareas o evitar que se creen ciertas tareas.2608Se ejecuta cuando se está creando una tarea a través de la herramienta `TaskCreate`. Úselo para hacer cumplir convenciones de nomenclatura, requerir descripciones de tareas o evitar que se creen ciertas tareas. En una [sesión sin las herramientas Task](/docs/es/tools-reference#task-tool-availability), este evento no se dispara.
2193 2609
2194Cuando un hook `TaskCreated` sale con código 2, la tarea no se crea y el mensaje de stderr se devuelve al modelo como retroalimentación. Para detener al compañero completamente en lugar de re-ejecutarlo, devuelva JSON con `{"continue": false, "stopReason": "..."}`. Los hooks TaskCreated no admiten matchers y se activan en cada ocurrencia.2610Los hooks TaskCreated no admiten matchers y se disparan en cada ocurrencia.
2195 2611
2196<h4 id="taskcreated-input">2612<h4 id="taskcreated-input">
2197 Entrada de TaskCreated2613 Entrada de TaskCreated
2198</h4>2614</h4>
2199 2615
2200Además de los [campos de entrada comunes](#common-input-fields), los hooks TaskCreated reciben `task_id`, `task_subject` y opcionalmente `task_description`, `teammate_name` y `team_name`.2616Además de los [campos de entrada comunes](#common-input-fields), los hooks TaskCreated reciben `task_id`, `task_subject`, y opcionalmente `task_description`, `teammate_name`, y `team_name`.
2201 2617
2202```json theme={null}2618```json theme={null}
2203{2619{
2204 "session_id": "abc123",2620 "session_id": "abc123",
2205 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",2621 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
2206 "cwd": "/Users/...",2622 "cwd": "/Users/...",
2207 "permission_mode": "default",
2208 "hook_event_name": "TaskCreated",2623 "hook_event_name": "TaskCreated",
2209 "task_id": "task-001",2624 "task_id": "task-001",
2210 "task_subject": "Implement user authentication",2625 "task_subject": "Implement user authentication",
2215```2630```
2216 2631
2217| Campo | Descripción |2632| Campo | Descripción |
2218| :----------------- | :-------------------------------------------------------------------------- |2633| :----------------- | :--------------------------------------------------------------------------------- |
2219| `task_id` | Identificador de la tarea que se está creando |2634| `task_id` | Identificador de la tarea que se está creando |
2220| `task_subject` | Título de la tarea |2635| `task_subject` | Título de la tarea |
2221| `task_description` | Descripción detallada de la tarea. Puede estar ausente |2636| `task_description` | Descripción detallada de la tarea. Puede estar ausente |
2222| `teammate_name` | Nombre del compañero que crea la tarea. Puede estar ausente |2637| `teammate_name` | Nombre del compañero que está creando la tarea. Puede estar ausente |
2223| `team_name` | Nombre del equipo derivado de la sesión; se eliminará en una versión futura |2638| `team_name` | Deprecado. Nombre de equipo derivado de sesión; se eliminará en una versión futura |
2224 2639
2225<h4 id="taskcreated-decision-control">2640<h4 id="taskcreated-decision-control">
2226 Control de decisión de TaskCreated2641 Control de decisión de TaskCreated
2227</h4>2642</h4>
2228 2643
2229Los hooks TaskCreated admiten dos formas de controlar la creación de tareas:2644Un hook TaskCreated puede bloquear la creación de dos formas. De cualquier manera, Claude Code elimina la tarea y devuelve su mensaje a Claude como el error de la herramienta. Claude Code ignora `continue: false` de este evento y Claude continúa trabajando.
2230 2645
2231* **Código de salida 2**: la tarea no se crea y el mensaje de stderr se devuelve al modelo como retroalimentación.2646* **Código de salida 2**: Claude Code devuelve el texto stderr como el mensaje.
2232* **JSON `{"continue": false, "stopReason": "..."}`**: detiene al compañero completamente, coincidiendo con el comportamiento del hook `Stop`. El `stopReason` se muestra al usuario.2647* **JSON `{"decision": "block", "reason": "..."}`**: Claude Code devuelve `reason` como el mensaje.
2233 2648
2234Este ejemplo bloquea tareas cujos asuntos no siguen el formato requerido:2649Este ejemplo bloquea tareas cuyos asuntos no siguen el formato requerido:
2235 2650
2236```bash theme={null}2651```bash theme={null}
2237#!/bin/bash2652#!/bin/bash
2250 TaskCompleted2665 TaskCompleted
2251</h3>2666</h3>
2252 2667
2253Se ejecuta cuando una tarea está siendo marcada como completada. Esto se activa en dos situaciones: cuando cualquier agente marca explícitamente una tarea como completada a través de la herramienta TaskUpdate, o cuando un compañero de [equipo de agentes](/docs/es/agent-teams) termina su turno con tareas en progreso. Use esto para aplicar criterios de finalización como pasar pruebas o verificaciones de lint antes de que una tarea pueda cerrarse.2668Se ejecuta cuando se está marcando una tarea como completada. Esto se dispara en dos situaciones: cuando cualquier agente marca explícitamente una tarea como completada a través de la herramienta TaskUpdate, o cuando un compañero de [equipo de agente](/docs/es/agent-teams) termina su turno con tareas en progreso. Úselo para hacer cumplir criterios de finalización como pasar pruebas o verificaciones de lint antes de que una tarea pueda cerrarse.
2254 2669
2255Cuando un hook `TaskCompleted` sale con código 2, la tarea no se marca como completada y el mensaje de stderr se devuelve al modelo como retroalimentación. Para detener al compañero completamente en lugar de re-ejecutarlo, devuelva JSON con `{"continue": false, "stopReason": "..."}`. Los hooks TaskCompleted no admiten matchers y se activan en cada ocurrencia.2670Los hooks TaskCompleted no admiten matchers y se disparan en cada ocurrencia.
2256 2671
2257<h4 id="taskcompleted-input">2672<h4 id="taskcompleted-input">
2258 Entrada de TaskCompleted2673 Entrada de TaskCompleted
2259</h4>2674</h4>
2260 2675
2261Además de los [campos de entrada comunes](#common-input-fields), los hooks TaskCompleted reciben `task_id`, `task_subject` y opcionalmente `task_description`, `teammate_name` y `team_name`.2676Además de los [campos de entrada comunes](#common-input-fields), los hooks TaskCompleted reciben `task_id`, `task_subject`, y opcionalmente `task_description`, `teammate_name`, y `team_name`.
2262 2677
2263```json theme={null}2678```json theme={null}
2264{2679{
2276```2691```
2277 2692
2278| Campo | Descripción |2693| Campo | Descripción |
2279| :----------------- | :-------------------------------------------------------------------------- |2694| :----------------- | :--------------------------------------------------------------------------------- |
2280| `task_id` | Identificador de la tarea que se está completando |2695| `task_id` | Identificador de la tarea que se está completando |
2281| `task_subject` | Título de la tarea |2696| `task_subject` | Título de la tarea |
2282| `task_description` | Descripción detallada de la tarea. Puede estar ausente |2697| `task_description` | Descripción detallada de la tarea. Puede estar ausente |
2283| `teammate_name` | Nombre del compañero que completa la tarea. Puede estar ausente |2698| `teammate_name` | Nombre del compañero que está completando la tarea. Puede estar ausente |
2284| `team_name` | Nombre del equipo derivado de la sesión; se eliminará en una versión futura |2699| `team_name` | Deprecado. Nombre de equipo derivado de sesión; se eliminará en una versión futura |
2285 2700
2286<h4 id="taskcompleted-decision-control">2701<h4 id="taskcompleted-decision-control">
2287 Control de decisión de TaskCompleted2702 Control de decisión de TaskCompleted
2289 2704
2290Los hooks TaskCompleted admiten dos formas de controlar la finalización de tareas:2705Los hooks TaskCompleted admiten dos formas de controlar la finalización de tareas:
2291 2706
2292* **Código de salida 2**: la tarea no se marca como completada y el mensaje de stderr se devuelve al modelo como retroalimentación.2707* **Código de salida 2**: la tarea no se marca como completada y el mensaje stderr se devuelve al modelo como retroalimentación.
2293* **JSON `{"continue": false, "stopReason": "..."}`**: detiene al compañero completamente, coincidiendo con el comportamiento del hook `Stop`. El `stopReason` se muestra al usuario.2708* **JSON `{"continue": false, "stopReason": "..."}`**: cuando un compañero que termina su turno disparó el evento, detiene completamente al compañero, coincidiendo con el comportamiento del hook `Stop`. El `stopReason` se muestra al usuario. Cuando la herramienta `TaskUpdate` disparó el evento, Claude Code ignora `continue: false`; el código de salida 2 aún bloquea la finalización.
2294 2709
2295Este ejemplo ejecuta pruebas y bloquea la finalización de tareas si fallan:2710Este ejemplo ejecuta pruebas y bloquea la finalización de tareas si fallan:
2296 2711
2299INPUT=$(cat)2714INPUT=$(cat)
2300TASK_SUBJECT=$(echo "$INPUT" | jq -r '.task_subject')2715TASK_SUBJECT=$(echo "$INPUT" | jq -r '.task_subject')
2301 2716
2302# Ejecute el conjunto de pruebas2717# Run the test suite
2303if ! npm test 2>&1; then2718if ! npm test 2>&1; then
2304 echo "Tests not passing. Fix failing tests before completing: $TASK_SUBJECT" >&22719 echo "Tests not passing. Fix failing tests before completing: $TASK_SUBJECT" >&2
2305 exit 22720 exit 2
2312 Stop2727 Stop
2313</h3>2728</h3>
2314 2729
2315Se ejecuta cuando el agente principal de Claude Code ha terminado de responder. No se ejecuta si la detención ocurrió debido a una interrupción del usuario. Los errores de API activan [StopFailure](#stopfailure) en su lugar.2730Se ejecuta cuando el agente principal de Claude Code ha terminado de responder. No se ejecuta si la detención ocurrió debido a una interrupción del usuario. Los errores de API disparan [StopFailure](#stopfailure) en su lugar.
2316 2731
2317<Tip>2732<Tip>
2318 El comando [`/goal`](/docs/es/goal) es un atajo integrado para un hook Stop basado en prompt con alcance de sesión. Úselo cuando desee que Claude siga trabajando hasta que se cumpla una condición sin escribir configuración de hook.2733 El comando [`/goal`](/docs/es/goal) es un atajo integrado para un hook Stop basado en prompt con alcance de sesión. Úselo cuando quiera que Claude continúe trabajando hacia una condición sin escribir configuración de hook.
2319</Tip>2734</Tip>
2320 2735
2321<h4 id="stop-input">2736<h4 id="stop-input">
2322 Entrada de Stop2737 Entrada de Stop
2323</h4>2738</h4>
2324 2739
2325Además de los [campos de entrada comunes](#common-input-fields), los hooks Stop reciben `stop_hook_active`, `last_assistant_message`, `background_tasks` y `session_crons`. El campo `stop_hook_active` es `true` cuando Claude Code ya está continuando como resultado de un hook de parada. Verifique este valor o procese la transcripción para evitar bloquear en una condición que nunca se resolverá. Claude Code anula el hook y termina el turno después de 8 bloqueos consecutivos.2740Además de los [campos de entrada comunes](#common-input-fields), los hooks Stop reciben `stop_hook_active`, `last_assistant_message`, `background_tasks`, y `session_crons`. El campo `stop_hook_active` es `true` cuando Claude Code ya está continuando como resultado de un hook stop. Verifique este valor o procese la transcripción para evitar bloquear en una condición que nunca se resolverá. Claude Code anula el hook y termina el turno después de 8 bloqueos consecutivos.
2326 2741
2327El campo `last_assistant_message` contiene el contenido de texto de la respuesta final de Claude, por lo que los hooks pueden acceder a él sin analizar el archivo de transcripción.2742El campo `last_assistant_message` contiene el contenido de texto de la respuesta final de Claude, por lo que los hooks pueden acceder a él sin analizar el archivo de transcripción. Para hooks que actúan en el turno recién completado, como hooks de lectura en voz alta o notificación, use este campo en lugar de leer `transcript_path`: el archivo de transcripción no se garantiza que incluya el mensaje final en el tiempo de Stop en todas las versiones.
2328 2743
2329Los arrays `background_tasks` y `session_crons`, disponibles en Claude Code v2.1.145 o posterior, permiten que los hooks distingan "la sesión está hecha" de "la sesión está en pausa esperando que el trabajo en segundo plano la despierte". Ambos arrays están presentes cuando el registro de tareas es accesible y están vacíos cuando nada está en vuelo o programado.2744Las matrices `background_tasks` y `session_crons` permiten que los hooks distingan "sesión hecha" de "sesión pausada esperando que el trabajo de fondo la despierte". Ambas matrices están presentes cuando el registro de tareas es accesible y están vacías cuando nada está en vuelo o programado.
2330 2745
2331Cada entrada en `background_tasks` describe una tarea en vuelo y usa estos campos:2746Cada entrada en `background_tasks` describe una tarea en vuelo y usa estos campos:
2332 2747
2333| Campo | Descripción |2748| Campo | Descripción |
2334| :------------ | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |2749| :------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2335| `id` | Identificador de tarea |2750| `id` | Identificador de tarea |
2336| `type` | Etiqueta de tipo de tarea amigable como `shell`, `subagent`, `monitor`, `workflow`, `teammate`, `cloud session` o `MCP task`. Cada etiqueta identifica qué característica de Claude Code creó la tarea. Vuelve al discriminante sin procesar para tipos no reconocidos |2751| `type` | Etiqueta de tipo de tarea amigable como `shell`, `subagent`, `monitor`, `workflow`, `teammate`, `cloud session`, o `MCP task`. Cada etiqueta identifica qué característica de Claude Code creó la tarea. Vuelve al discriminante sin procesar para tipos no reconocidos |
2337| `status` | Estado actual de la tarea |2752| `status` | Estado actual de la tarea |
2338| `description` | Descripción de texto libre, limitada a 1000 caracteres con un marcador `… [+N chars]` en cadena cuando se recorta |2753| `description` | Descripción de texto libre, limitada a 1000 caracteres con un marcador `… [+N chars]` en cadena cuando se recorta |
2339| `command` | Línea de comando de shell, limitada a 1000 caracteres. Presente solo para tareas `shell` |2754| `command` | Línea de comando de shell, limitada a 1000 caracteres. Presente solo para tareas `shell` |
2342| `tool` | Nombre de herramienta MCP. Presente solo para tareas `monitor` y `MCP task` |2757| `tool` | Nombre de herramienta MCP. Presente solo para tareas `monitor` y `MCP task` |
2343| `name` | Nombre del flujo de trabajo. Presente solo para tareas `workflow` |2758| `name` | Nombre del flujo de trabajo. Presente solo para tareas `workflow` |
2344 2759
2345Cada entrada en `session_crons` describe un despertar programado con alcance de sesión, originado en `CronCreate`, `ScheduleWakeup` y `/loop`:2760Cada entrada en `session_crons` describe un despertar programado con alcance de sesión, originado de `CronCreate`, `ScheduleWakeup`, y `/loop`:
2346 2761
2347| Campo | Descripción |2762| Campo | Descripción |
2348| :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |2763| :---------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
2394| `reason` | Requerido cuando `decision` es `"block"`. Le dice a Claude por qué debe continuar |2809| `reason` | Requerido cuando `decision` es `"block"`. Le dice a Claude por qué debe continuar |
2395| `hookSpecificOutput.additionalContext` | Retroalimentación sin error para Claude. La conversación continúa para que Claude pueda actuar sobre ella, pero a diferencia de `decision: "block"` se muestra en la transcripción como retroalimentación de hook en lugar de un error de hook |2810| `hookSpecificOutput.additionalContext` | Retroalimentación sin error para Claude. La conversación continúa para que Claude pueda actuar sobre ella, pero a diferencia de `decision: "block"` se muestra en la transcripción como retroalimentación de hook en lugar de un error de hook |
2396 2811
2812Un hook que bloquea saliendo con 2 se enruta de la misma manera que `reason`: Claude recibe el mensaje stderr como la explicación de por qué debe continuar.
2813
2397```json theme={null}2814```json theme={null}
2398{2815{
2399 "decision": "block",2816 "decision": "block",
2401}2818}
2402```2819```
2403 2820
2404Use `additionalContext` cuando el hook está funcionando como se diseñó y dando orientación a Claude, como "ejecute el conjunto de pruebas antes de terminar". Mantiene la conversación a través de las mismas protecciones de bucle que `decision: "block"`, es decir, la entrada `stop_hook_active` y el límite de 8 continuaciones consecutivas, pero la transcripción la etiqueta como `Stop hook feedback` y no se muestra ninguna notificación de error de hook:2821Use `additionalContext` cuando el hook está funcionando como se diseñó y dando orientación a Claude, como "ejecutar el conjunto de pruebas antes de terminar". Mantiene la conversación a través de las mismas protecciones de bucle que `decision: "block"`, es decir, la entrada `stop_hook_active` y el límite de 8 continuaciones consecutivas, pero la transcripción la etiqueta como `Stop hook feedback` y no se muestra ninguna notificación de error de hook:
2405 2822
2406```json theme={null}2823```json theme={null}
2407{2824{
2416 StopFailure2833 StopFailure
2417</h3>2834</h3>
2418 2835
2419Se ejecuta en lugar de [Stop](#stop) cuando el turno termina debido a un error de API. La salida y el código de salida se ignoran. Use esto para registrar fallos, enviar alertas o tomar acciones de recuperación cuando Claude no puede completar una respuesta debido a límites de velocidad, problemas de autenticación u otros errores de API.2836Se ejecuta en lugar de [Stop](#stop) cuando el turno termina debido a un error de API. Claude Code ignora la salida y el código de salida del hook, aparte de [`terminalSequence`](#emit-terminal-notifications). Úselo para registrar fallas, enviar alertas o tomar acciones de recuperación cuando Claude no puede completar una respuesta debido a límites de velocidad, problemas de autenticación u otros errores de API.
2420 2837
2421<h4 id="stopfailure-input">2838<h4 id="stopfailure-input">
2422 Entrada de StopFailure2839 Entrada de StopFailure
2423</h4>2840</h4>
2424 2841
2425Además de los [campos de entrada comunes](#common-input-fields), los hooks StopFailure reciben `error`, `error_details` opcional y `last_assistant_message` opcional. El campo `error` identifica el tipo de error y se usa para filtrado de matcher.2842Además de los [campos de entrada comunes](#common-input-fields), los hooks StopFailure reciben `error`, `error_details` opcional, y `last_assistant_message` opcional. El campo `error` identifica el tipo de error y se utiliza para filtrado de matcher.
2426 2843
2427| Campo | Descripción |2844| Campo | Descripción |
2428| :----------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |2845| :----------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2429| `error` | Tipo de error: `rate_limit`, `overloaded`, `authentication_failed`, `oauth_org_not_allowed`, `billing_error`, `invalid_request`, `model_not_found`, `server_error`, `max_output_tokens` u `unknown` |2846| `error` | Tipo de error: `rate_limit`, `overloaded`, `authentication_failed`, `oauth_org_not_allowed`, `account_on_hold`, `billing_error`, `invalid_request`, `model_not_found`, `server_error`, `max_output_tokens`, `cloud_credential_error`, o `unknown` |
2430| `error_details` | Detalles adicionales sobre el error, cuando estén disponibles |2847| `error_details` | Detalles adicionales sobre el error, cuando esté disponible |
2431| `last_assistant_message` | El texto de error renderizado mostrado en la conversación. A diferencia de `Stop` y `SubagentStop`, donde este campo contiene la salida conversacional de Claude, para `StopFailure` contiene la cadena de error de API en sí, como `"API Error: Rate limit reached"` |2848| `last_assistant_message` | El texto de error renderizado mostrado en la conversación. A diferencia de `Stop` y `SubagentStop`, donde este campo contiene la salida conversacional de Claude, para `StopFailure` contiene la cadena de error de API en sí, como `"API Error: Rate limit reached"` |
2432 2849
2433```json theme={null}2850```json theme={null}
2448 TeammateIdle2865 TeammateIdle
2449</h3>2866</h3>
2450 2867
2451Se ejecuta cuando un compañero de [equipo de agentes](/docs/es/agent-teams) está a punto de quedarse inactivo después de terminar su turno. Use esto para aplicar puertas de calidad antes de que un compañero deje de trabajar, como requerir que pasen verificaciones de lint o verificar que existan archivos de salida.2868Se ejecuta cuando un compañero de [equipo de agente](/docs/es/agent-teams) está a punto de quedarse inactivo después de terminar su turno. Úselo para hacer cumplir puertas de calidad antes de que un compañero deje de trabajar, como requerir que pasen verificaciones de lint o verificar que existan archivos de salida.
2452 2869
2453Cuando un hook `TeammateIdle` sale con código 2, el compañero recibe el mensaje de stderr como retroalimentación y continúa trabajando en lugar de quedarse inactivo. Para detener al compañero completamente en lugar de re-ejecutarlo, devuelva JSON con `{"continue": false, "stopReason": "..."}`. Los hooks TeammateIdle no admiten matchers y se activan en cada ocurrencia.2870Los hooks TeammateIdle no admiten matchers y se disparan en cada ocurrencia.
2454 2871
2455<h4 id="teammateidle-input">2872<h4 id="teammateidle-input">
2456 Entrada de TeammateIdle2873 Entrada de TeammateIdle
2471```2888```
2472 2889
2473| Campo | Descripción |2890| Campo | Descripción |
2474| :-------------- | :-------------------------------------------------------------------------- |2891| :-------------- | :--------------------------------------------------------------------------------- |
2475| `teammate_name` | Nombre del compañero que está a punto de quedarse inactivo |2892| `teammate_name` | Nombre del compañero que está a punto de quedarse inactivo |
2476| `team_name` | Nombre del equipo derivado de la sesión; se eliminará en una versión futura |2893| `team_name` | Deprecado. Nombre de equipo derivado de sesión; se eliminará en una versión futura |
2477 2894
2478<h4 id="teammateidle-decision-control">2895<h4 id="teammateidle-decision-control">
2479 Control de decisión de TeammateIdle2896 Control de decisión de TeammateIdle
2481 2898
2482Los hooks TeammateIdle admiten dos formas de controlar el comportamiento del compañero:2899Los hooks TeammateIdle admiten dos formas de controlar el comportamiento del compañero:
2483 2900
2484* **Código de salida 2**: el compañero recibe el mensaje de stderr como retroalimentación y continúa trabajando en lugar de quedarse inactivo.2901* **Código de salida 2**: el compañero recibe el mensaje stderr como retroalimentación y continúa trabajando en lugar de quedarse inactivo.
2485* **JSON `{"continue": false, "stopReason": "..."}`**: detiene al compañero completamente, coincidiendo con el comportamiento del hook `Stop`. El `stopReason` se muestra al usuario.2902* **JSON `{"continue": false, "stopReason": "..."}`**: detiene completamente al compañero, coincidiendo con el comportamiento del hook `Stop`. El `stopReason` se muestra al usuario.
2486 2903
2487Este ejemplo verifica que exista un artefacto de compilación antes de permitir que un compañero se quede inactivo:2904Este ejemplo verifica que existe un artefacto de compilación antes de permitir que un compañero se quede inactivo:
2488 2905
2489```bash theme={null}2906```bash theme={null}
2490#!/bin/bash2907#!/bin/bash
2501 ConfigChange2918 ConfigChange
2502</h3>2919</h3>
2503 2920
2504Se ejecuta cuando un archivo de configuración cambia durante una sesión. Use esto para auditar cambios de configuración, aplicar políticas de seguridad o bloquear modificaciones no autorizadas a archivos de configuración.2921Se ejecuta cuando un archivo de configuración cambia durante una sesión. Úselo para auditar cambios de configuración, hacer cumplir políticas de seguridad o bloquear modificaciones no autorizadas en archivos de configuración.
2505 2922
2506Los hooks ConfigChange se activan para cambios en archivos de configuración, configuración de política administrada y archivos de skill. El campo `source` en la entrada le dice qué tipo de configuración cambió, y el campo `file_path` opcional proporciona la ruta al archivo cambiado.2923Claude Code ejecuta hooks ConfigChange cuando un archivo de configuración, un archivo de política administrada o un archivo de skill cambia. Para política administrada, solo los ejecuta cuando `managed-settings.json` o un archivo en `managed-settings.d/` cambia. Aplica [configuración administrada por servidor](/docs/es/server-managed-settings) y cambios en preferencias administradas de macOS o política de registro de Windows sin ejecutarlos. En WSL con [`wslInheritsWindowsSettings`](/docs/es/settings-reference#wslinheritswindowssettings), también aplica un archivo de configuración administrada de Windows modificado en su sondeo de política sin ejecutarlos.
2507 2924
2508El matcher filtra en la fuente de configuración:2925El matcher filtra en la fuente de configuración:
2509 2926
2510| Matcher | Cuándo se activa |2927| Matcher | Cuándo se dispara |
2511| :----------------- | :------------------------------------------------ |2928| :----------------- | :------------------------------------------------------------------- |
2512| `user_settings` | `~/.claude/settings.json` cambia |2929| `user_settings` | `~/.claude/settings.json` cambia |
2513| `project_settings` | `.claude/settings.json` cambia |2930| `project_settings` | `.claude/settings.json` cambia |
2514| `local_settings` | `.claude/settings.local.json` cambia |2931| `local_settings` | `.claude/settings.local.json` cambia |
2515| `policy_settings` | Cambios de configuración de política administrada |2932| `policy_settings` | `managed-settings.json` o un archivo en `managed-settings.d/` cambia |
2516| `skills` | Un archivo de skill en `.claude/skills/` cambia |2933| `skills` | Un archivo de skill en `.claude/skills/` cambia |
2517 2934
2518Este ejemplo registra todos los cambios de configuración para auditoría de seguridad:2935Este ejemplo registra todos los cambios de configuración para auditoría de seguridad:
2556 Control de decisión de ConfigChange2973 Control de decisión de ConfigChange
2557</h4>2974</h4>
2558 2975
2559Los hooks ConfigChange pueden bloquear cambios de configuración para que no tengan efecto. Use código de salida 2 o un JSON `decision` para evitar el cambio. Cuando se bloquea, la nueva configuración no se aplica a la sesión en ejecución.2976Los hooks ConfigChange pueden bloquear cambios de configuración para que no surtan efecto. Use código de salida 2 o un JSON `decision` para evitar el cambio. Cuando se bloquea, la nueva configuración no se aplica a la sesión en ejecución.
2560 2977
2561| Campo | Descripción |2978| Campo | Descripción |
2562| :--------- | :--------------------------------------------------------------------------------------- |2979| :--------- | :--------------------------------------------------------------------------------------- |
2563| `decision` | `"block"` evita que el cambio de configuración se aplique. Omita para permitir el cambio |2980| `decision` | `"block"` evita que se aplique el cambio de configuración. Omita para permitir el cambio |
2564| `reason` | Explicación mostrada al usuario cuando `decision` es `"block"` |2981| `reason` | Aceptado pero nunca mostrado |
2565 2982
2566```json theme={null}2983```json theme={null}
2567{2984{
2570}2987}
2571```2988```
2572 2989
2573Los cambios de `policy_settings` no pueden bloquearse. Los hooks aún se activan para fuentes de `policy_settings`, por lo que puede usarlos para registro de auditoría, pero cualquier decisión de bloqueo se ignora. Esto asegura que la configuración administrada por empresa siempre tenga efecto.2990Los cambios `policy_settings` no se pueden bloquear. Los hooks aún se disparan para fuentes `policy_settings` cuando un archivo de configuración administrada en la máquina cambia, para que pueda usarlos para registrar esas ediciones, pero cualquier decisión de bloqueo se ignora. Esto asegura que la configuración administrada por empresa siempre surta efecto. Claude Code no ejecuta hooks `ConfigChange` cuando llegan o se actualizan [configuración administrada por servidor](/docs/es/server-managed-settings).
2991
2992Claude Code actúa sobre la decisión de bloqueo de la salida JSON de un hook ConfigChange y descarta `systemMessage` y `continue`. Un cambio bloqueado no muestra ningún mensaje a usted o a Claude, ya sea que bloquee con `reason` o con stderr en salida 2. Claude Code solo escribe una línea en el registro de depuración.
2574 2993
2575<h3 id="cwdchanged">2994<h3 id="cwdchanged">
2576 CwdChanged2995 CwdChanged
2577</h3>2996</h3>
2578 2997
2579Se ejecuta cuando el directorio de trabajo cambia durante una sesión, por ejemplo cuando Claude ejecuta un comando `cd`. Use esto para reaccionar a cambios de directorio: recargar variables de entorno, activar cadenas de herramientas específicas del proyecto o ejecutar scripts de configuración automáticamente. Se empareja con [FileChanged](#filechanged) para herramientas como [direnv](https://direnv.net/) que administran el entorno por directorio.2998Se ejecuta cuando un comando de shell en la conversación principal cambia el directorio de trabajo, por ejemplo cuando Claude ejecuta un comando `cd`. Úselo para reaccionar a cambios de directorio: recargar variables de entorno, activar cadenas de herramientas específicas del proyecto o ejecutar scripts de configuración automáticamente. Se empareja con [FileChanged](#filechanged) para herramientas como [direnv](https://direnv.net/) que administran el entorno por directorio.
2580 2999
2581Los hooks CwdChanged tienen acceso a `CLAUDE_ENV_FILE`. Las variables escritas en ese archivo persisten en comandos Bash posteriores para la sesión, al igual que en los [hooks SessionStart](#persist-environment-variables).3000Los hooks CwdChanged tienen acceso a [`CLAUDE_ENV_FILE`](#persist-environment-variables). Las variables escritas en ese archivo persisten en comandos Bash posteriores hasta el siguiente evento CwdChanged, cuando Claude Code las borra.
2582 3001
2583CwdChanged no admite matchers y se activa en cada cambio de directorio.3002CwdChanged no admite matchers y se dispara en cada ocurrencia.
2584 3003
2585<h4 id="cwdchanged-input">3004<h4 id="cwdchanged-input">
2586 Entrada de CwdChanged3005 Entrada de CwdChanged
2603 Salida de CwdChanged3022 Salida de CwdChanged
2604</h4>3023</h4>
2605 3024
2606Además de los [campos de salida JSON](#json-output) disponibles para todos los hooks, los hooks CwdChanged pueden devolver `watchPaths` para establecer dinámicamente qué rutas de archivo [FileChanged](#filechanged) monitorea:3025Además de los [campos de salida JSON](#json-output) disponibles para todos los hooks, los hooks CwdChanged pueden devolver `watchPaths` para establecer dinámicamente qué rutas de archivo [FileChanged](#filechanged) observa:
2607 3026
2608| Campo | Descripción |3027| Campo | Descripción |
2609| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |3028| :----------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2610| `watchPaths` | Array de rutas absolutas. Reemplaza la lista de monitoreo dinámica actual. Las rutas de su configuración de `matcher` siempre se monitorean. Devolver un array vacío borra la lista dinámica, que es típico al entrar en un nuevo directorio |3029| `watchPaths` | Matriz de rutas absolutas. Reemplaza la lista de observación dinámica actual. Las rutas de su configuración `matcher` siempre se observan. Devolver una matriz vacía borra la lista dinámica, que es típico al entrar en un nuevo directorio |
2611 3030
2612Los hooks CwdChanged no tienen control de decisión. No pueden bloquear el cambio de directorio.3031Los hooks CwdChanged no tienen control de decisión. No pueden bloquear el cambio de directorio.
2613 3032
3033Claude Code lee `watchPaths` y `systemMessage` de su salida JSON y descarta `continue`. En sesiones interactivas, muestra el `systemMessage` como una breve notificación de terminal. El mensaje no llega al flujo de mensajes de SDK.
3034
3035<h3 id="directoryadded">
3036 DirectoryAdded
3037</h3>
3038
3039Se ejecuta después de agregar un directorio de trabajo a mitad de sesión con el comando `/add-dir`, o después de que un cliente de SDK agregue uno con la solicitud de control `register_repo_root`. Úselo para preparar un repositorio recién agregado, por ejemplo instalando sus dependencias.
3040
3041Claude Code no dispara este evento cuando:
3042
3043* Pasa un directorio con la bandera de inicio `--add-dir`; [SessionStart](#sessionstart) cubre esos directorios
3044* Agrega un directorio en la pestaña Workspace `/permissions`
3045* Agrega un directorio que ya es un directorio de trabajo o está dentro de uno
3046
3047Claude Code dispara DirectoryAdded después de actualizar el estado de sandbox y permiso, por lo que las herramientas en sandbox ya ven el nuevo directorio cuando se ejecuta su hook. Los comandos del hook en sí se ejecutan sin sandbox.
3048
3049Claude Code no espera el hook: la adición se completa inmediatamente, y el hook se ejecuta en segundo plano con el tiempo de espera predeterminado de 600 segundos.
3050
3051El matcher filtra en cómo se agregó el directorio:
3052
3053| Matcher | Cuándo se dispara |
3054| :------------------- | :-------------------------------------------------------------------------------------- |
3055| `slash_command` | Agrega un directorio con `/add-dir` |
3056| `register_repo_root` | Un cliente de SDK agrega un directorio con la solicitud de control `register_repo_root` |
3057
3058<h4 id="directoryadded-input">
3059 Entrada de DirectoryAdded
3060</h4>
3061
3062Además de los [campos de entrada comunes](#common-input-fields), los hooks DirectoryAdded reciben `directory` y `source`.
3063
3064| Campo | Descripción |
3065| :---------- | :--------------------------------------------------------------------------------------------------------------------------- |
3066| `directory` | Ruta absoluta del directorio que se agregó |
3067| `source` | Cómo se agregó el directorio, `"slash_command"` para `/add-dir` o `"register_repo_root"` para la solicitud de control de SDK |
3068
3069```json theme={null}
3070{
3071 "session_id": "abc123",
3072 "transcript_path": "/Users/.../.claude/projects/.../transcript.jsonl",
3073 "cwd": "/Users/my-project",
3074 "hook_event_name": "DirectoryAdded",
3075 "directory": "/Users/my-other-repo",
3076 "source": "slash_command"
3077}
3078```
3079
3080Los hooks DirectoryAdded no tienen control de decisión. No pueden bloquear la adición, que ya se ha completado cuando se ejecuta el hook. Claude Code descarta el campo `continue` de su salida JSON y muestra el resto diferente por fuente:
3081
3082* `slash_command`: Claude Code entrega el `systemMessage` del hook a Claude como contexto en el siguiente turno de conversación, en lugar de mostrárselo. Un recuento de hooks fallidos aparece en la transcripción. La salida de fallo completo va al registro de depuración
3083* `register_repo_root`: Claude Code escribe la salida `systemMessage` y la salida de fallo solo en el registro de depuración
3084
2614<h3 id="filechanged">3085<h3 id="filechanged">
2615 FileChanged3086 FileChanged
2616</h3>3087</h3>
2617 3088
2618Se ejecuta cuando un archivo monitoreado cambia en el disco. Útil para recargar variables de entorno cuando se modifican archivos de configuración del proyecto.3089Se ejecuta cuando un archivo observado cambia en el disco. Claude Code detecta cambios con un observador del sistema de archivos, no inspeccionando llamadas de herramientas, por lo que ejecuta el hook sin importar qué cambió el archivo: una llamada de herramienta `Edit` o `Write`, un script que Claude ejecuta con `Bash`, o un proceso fuera de Claude Code completamente. Un uso común es recargar variables de entorno cuando cambian archivos de configuración del proyecto.
2619 3090
2620El `matcher` para este evento sirve dos propósitos:3091El `matcher` para este evento sirve dos propósitos:
2621 3092
2622* **Construir la lista de vigilancia**: el valor se divide en `|` y cada segmento se registra como un nombre de archivo literal en el directorio de trabajo, por lo que `".envrc|.env"` vigila exactamente esos dos archivos. Los patrones regex no son útiles aquí: un valor como `^\.env` vigilaría un archivo literalmente nombrado `^\.env`.3093* **Construir la lista de observación**: el valor se divide en `|` y cada segmento se registra como un nombre de archivo literal en el directorio de trabajo, por lo que `".envrc|.env"` observa exactamente esos dos archivos. Los patrones regex no son útiles aquí: un valor como `^\.env` observaría un archivo literalmente nombrado `^\.env`.
2623* **Filtrar qué hooks se ejecutan**: cuando cambia un archivo vigilado, el mismo valor filtra qué grupos de hooks se ejecutan usando las [reglas de matcher](#matcher-patterns) estándar contra el basename del archivo cambiado.3094* **Filtrar qué hooks se ejecutan**: cuando un archivo observado cambia, el mismo valor filtra qué grupos de hooks se ejecutan usando las [reglas de matcher](#matcher-patterns) estándar contra el nombre base del archivo cambiado.
2624 3095
2625Los hooks FileChanged tienen acceso a `CLAUDE_ENV_FILE`. Las variables escritas en ese archivo persisten en comandos Bash posteriores para la sesión, al igual que en los [hooks SessionStart](#persist-environment-variables).3096Este ejemplo normaliza los finales de línea en `data.csv` después de cualquier cambio, incluido un comando `Bash` o un script externo reescribiendo el archivo:
3097
3098```json theme={null}
3099{
3100 "hooks": {
3101 "FileChanged": [
3102 {
3103 "matcher": "data.csv",
3104 "hooks": [
3105 {
3106 "type": "command",
3107 "command": "/path/to/normalize-line-endings.sh"
3108 }
3109 ]
3110 }
3111 ]
3112 }
3113}
3114```
3115
3116El hook lee la ruta absoluta del archivo cambiado del campo `file_path` de la [entrada JSON](#filechanged-input) en stdin. Su guardia `grep` prueba lo mismo que `perl` elimina, un CR al final de una línea, por lo que la ejecución después de una normalización sale sin tocar el archivo. Una guardia más suelta se repite para siempre, porque `perl -i` reescribe el archivo incluso cuando no sustituye nada y Claude Code ejecuta el hook nuevamente después de cada reescritura. Guarde este script en `/path/to/normalize-line-endings.sh` y hágalo ejecutable:
3117
3118```bash theme={null}
3119#!/bin/bash
3120FILE=$(jq -r .file_path)
3121if grep -q $'\r$' "$FILE"; then
3122 perl -pi -e 's/\r$//' "$FILE"
3123fi
3124```
3125
3126Para confirmar que el hook funciona, pida a Claude que agregue una línea CRLF a `data.csv` con un comando `Bash`. Claude Code ejecuta el hook y el archivo termina con finales LF.
3127
3128Para observar archivos que no puede nombrar por adelantado, devuelva [`watchPaths`](#filechanged-output) de un hook para actualizar la lista de observación dinámicamente. Claude Code comienza el observador solo cuando algo nombra un archivo para observar, por lo que inicie la lista con un grupo FileChanged cuyo matcher nombre al menos un archivo, o con un hook [SessionStart](#sessionstart-decision-control) o [CwdChanged](#cwdchanged) que devuelva `watchPaths`. El matcher aún filtra qué grupos de hooks se ejecutan cuando un archivo observado cambia, así que dé al grupo que maneja rutas dinámicas un matcher omitido, que coincide con cada archivo observado y no agrega nada a la lista de observación. Un matcher `"*"` también coincide con cada archivo, pero Claude Code lo registra en la lista de observación como un archivo literal nombrado `*`.
3129
3130Los hooks FileChanged tienen acceso a [`CLAUDE_ENV_FILE`](#persist-environment-variables). Las variables escritas en ese archivo persisten en comandos Bash posteriores hasta el siguiente evento [CwdChanged](#cwdchanged), cuando Claude Code las borra.
2626 3131
2627<h4 id="filechanged-input">3132<h4 id="filechanged-input">
2628 Entrada de FileChanged3133 Entrada de FileChanged
2631Además de los [campos de entrada comunes](#common-input-fields), los hooks FileChanged reciben `file_path` y `event`.3136Además de los [campos de entrada comunes](#common-input-fields), los hooks FileChanged reciben `file_path` y `event`.
2632 3137
2633| Campo | Descripción |3138| Campo | Descripción |
2634| :---------- | :------------------------------------------------------------------------------------------------------------------------ |3139| :---------- | :------------------------------------------------------------------------------------------------------------------------- |
2635| `file_path` | Ruta absoluta al archivo que cambió |3140| `file_path` | Ruta absoluta al archivo que cambió |
2636| `event` | Qué sucedió: `"change"` para un archivo modificado, `"add"` para un archivo creado o `"unlink"` para un archivo eliminado |3141| `event` | Qué sucedió: `"change"` para un archivo modificado, `"add"` para un archivo creado, o `"unlink"` para un archivo eliminado |
2637 3142
2638```json theme={null}3143```json theme={null}
2639{3144{
2650 Salida de FileChanged3155 Salida de FileChanged
2651</h4>3156</h4>
2652 3157
2653Además de los [campos de salida JSON](#json-output) disponibles para todos los hooks, los hooks FileChanged pueden devolver `watchPaths` para actualizar dinámicamente qué rutas de archivo se monitorean:3158Además de los [campos de salida JSON](#json-output) disponibles para todos los hooks, los hooks FileChanged pueden devolver `watchPaths` para actualizar dinámicamente qué rutas de archivo se observan:
2654 3159
2655| Campo | Descripción |3160| Campo | Descripción |
2656| :----------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |3161| :----------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
2657| `watchPaths` | Array de rutas absolutas. Reemplaza la lista de monitoreo dinámica actual. Las rutas de su configuración de `matcher` siempre se monitorean. Use esto cuando su script de hook descubra archivos adicionales para monitorear basados en el archivo cambiado |3162| `watchPaths` | Matriz de rutas absolutas. Reemplaza la lista de observación dinámica actual. Las rutas de su configuración `matcher` siempre se observan. Úselo cuando su script de hook descubra archivos adicionales para observar basándose en el archivo cambiado |
3163
3164Los hooks FileChanged no tienen control de decisión. No pueden bloquear el cambio de archivo que ocurre.
2658 3165
2659Los hooks FileChanged no tienen control de decisión. No pueden bloquear el cambio de archivo.3166Claude Code lee `watchPaths` y `systemMessage` de su salida JSON y descarta `continue`. En sesiones interactivas, muestra el `systemMessage` como una breve notificación de terminal. El mensaje no llega al flujo de mensajes de SDK.
2660 3167
2661<h3 id="worktreecreate">3168<h3 id="worktreecreate">
2662 WorktreeCreate3169 WorktreeCreate
2663</h3>3170</h3>
2664 3171
2665Se ejecuta cuando se está creando un worktree, ya sea desde `claude --worktree` o desde un [subagente usando `isolation: "worktree"`](/docs/es/sub-agents#choose-the-subagent-scope). Por defecto Claude Code crea la copia de trabajo aislada con `git worktree`. Configurar un hook WorktreeCreate reemplaza ese comportamiento predeterminado de git, permitiéndole usar un sistema de control de versiones diferente como SVN, Perforce o Mercurial.3172Se ejecuta cuando se está creando un worktree, ya sea desde `claude --worktree`, desde un [subagente usando `isolation: "worktree"`](/docs/es/sub-agents#choose-the-subagent-scope), o para una [sesión de fondo](/docs/es/agent-view#how-file-edits-are-isolated) que Claude Code aísla en su propio worktree. De forma predeterminada, Claude Code crea la copia de trabajo aislada con `git worktree`. Configurar un hook WorktreeCreate reemplaza ese comportamiento de git predeterminado, permitiéndole usar un sistema de control de versiones diferente como SVN, Perforce o Mercurial.
2666 3173
2667Debido a que el hook reemplaza el comportamiento predeterminado completamente, [`.worktreeinclude`](/docs/es/worktrees#copy-gitignored-files-into-worktrees) no se procesa. Si necesita copiar archivos de configuración local como `.env` en el nuevo worktree, hágalo dentro de su script de hook.3174Debido a que el hook reemplaza el comportamiento predeterminado completamente, [`.worktreeinclude`](/docs/es/worktrees#copy-gitignored-files-into-worktrees) no se procesa. Si necesita copiar archivos de configuración local como `.env` en el nuevo worktree, hágalo dentro de su script de hook.
2668 3175
2669El hook debe devolver la ruta al directorio de worktree creado. Claude Code usa esta ruta como el directorio de trabajo para la sesión aislada. Consulte [WorktreeCreate output](#worktreecreate-output) para saber cómo cada tipo de hook devuelve la ruta.3176El hook debe devolver la ruta al directorio del worktree creado. Claude Code usa esta ruta como el directorio de trabajo para la sesión aislada. Consulte [Salida de WorktreeCreate](#worktreecreate-output) para saber cómo cada tipo de hook devuelve la ruta.
3177
3178Claude Code actúa sobre el éxito del hook y la ruta devuelta, y descarta `systemMessage` y `continue`.
2670 3179
2671Este ejemplo crea una copia de trabajo SVN e imprime la ruta para que Claude Code la use. Reemplace la URL del repositorio con la suya:3180Este ejemplo crea una copia de trabajo SVN e imprime la ruta para que Claude Code la use. Reemplace la URL del repositorio con la suya:
2672 3181
2693 Entrada de WorktreeCreate3202 Entrada de WorktreeCreate
2694</h4>3203</h4>
2695 3204
2696Además de los [campos de entrada comunes](#common-input-fields), los hooks WorktreeCreate reciben el campo `name`. Este es un identificador slug para el nuevo worktree, especificado por el usuario o generado automáticamente, por ejemplo `bold-oak-a3f2`.3205Además de los [campos de entrada comunes](#common-input-fields), los hooks WorktreeCreate reciben el campo `name`. Este es un identificador slug para el nuevo worktree, ya sea especificado por el usuario o generado automáticamente, por ejemplo `bold-oak-a3f2`.
2697 3206
2698```json theme={null}3207```json theme={null}
2699{3208{
2709 Salida de WorktreeCreate3218 Salida de WorktreeCreate
2710</h4>3219</h4>
2711 3220
2712Los hooks WorktreeCreate no usan el modelo de decisión de permitir/bloquear estándar. En su lugar, el éxito o fallo del hook determina el resultado. El hook debe devolver la ruta al directorio de worktree creado:3221Los hooks WorktreeCreate no usan el modelo de decisión de permitir/bloquear estándar. En su lugar, el éxito o fallo del hook determina el resultado. El hook debe devolver la ruta al directorio del worktree creado:
3222
3223* **Hooks de comando** (`type: "command"`): imprima la ruta como la última línea no vacía de stdout. Claude Code elimina códigos de escape ANSI antes de leer esa línea, por lo que los banners de inicio de shell impresos antes de su `echo` se ignoran. Redirija cualquier otra salida de hook a stderr.
3224* **Hooks HTTP** (`type: "http"`): devuelva `{ "hookSpecificOutput": { "hookEventName": "WorktreeCreate", "worktreePath": "/absolute/path" } }` en el cuerpo de la respuesta.
2713 3225
2714* **Hooks de comando** (`type: "command"`): imprimen la ruta como la última línea no vacía de stdout. Claude Code elimina códigos de escape ANSI antes de leer esa línea, por lo que los banners de inicio de shell impresos antes de su `echo` se ignoran. Redirija cualquier otra salida de hook a stderr.3226Si el hook falla o no produce una ruta, la creación del worktree falla con un error.
2715* **Hooks HTTP** (`type: "http"`): devuelven `{ "hookSpecificOutput": { "hookEventName": "WorktreeCreate", "worktreePath": "/absolute/path" } }` en el cuerpo de la respuesta.
2716 3227
2717Si el hook falla o no produce ruta, la creación de worktree falla con un error.3228Claude Code resuelve una ruta relativa contra el directorio en el que se ejecutó el hook, colapsando cualquier segmento `.` o `..` en él. Si la ruta resultante no es un directorio en el que Claude Code pueda entrar, la sesión imprime un error que nombra la ruta y sale con código 1.
2718 3229
2719Claude Code resuelve una ruta relativa contra el directorio en el que se ejecutó el hook. Si la ruta resultante no es un directorio al que Claude Code pueda entrar, la sesión imprime un error nombrando la ruta y sale con código 1. Antes de v2.1.205, una ruta relativa o una ruta que no existía en el disco causaba un bloqueo de la sesión al inicio, y con `-p` se detenía durante aproximadamente 30 segundos antes de salir con código 0.3230Claude Code rechaza una ruta absoluta que contiene segmentos `.` o `..`, y cualquier ruta que pase a través de un symlink debajo de la raíz del repositorio, porque un symlink comprometido en el repositorio podría redirigir el worktree fuera de él. El error nombra el componente rechazado. Devuelva una ruta normalizada que no pase a través de un symlink dentro del repositorio. Antes de v2.1.216, la creación del worktree seguía la ruta del hook sin este cribado.
2720 3231
2721<h3 id="worktreeremove">3232<h3 id="worktreeremove">
2722 WorktreeRemove3233 WorktreeRemove
2723</h3>3234</h3>
2724 3235
2725Se ejecuta cuando se está eliminando un worktree, ya sea cuando sale de una sesión `--worktree` y elige eliminarlo, o cuando un subagente con `isolation: "worktree"` finaliza. Esta es la contraparte de limpieza de [WorktreeCreate](#worktreecreate).3236Se ejecuta cuando se está eliminando un worktree. Este es el homólogo de limpieza de [WorktreeCreate](#worktreecreate). El evento se dispara cuando:
3237
3238* sale de una sesión `--worktree` y elige eliminarla
3239* un subagente con `isolation: "worktree"` se completa
3240* elimina una [sesión de fondo](/docs/es/agent-view#what-deleting-a-session-removes) cuyo worktree creó el hook
2726 3241
2727Para worktrees basados en git, Claude Code maneja la limpieza automáticamente con `git worktree remove`. Si configuró un hook WorktreeCreate para un sistema de control de versiones que no es git, emparéjelo con un hook WorktreeRemove para manejar la limpieza. Sin uno, el directorio de worktree se deja en el disco.3242Para worktrees basados en git, Claude Code maneja la limpieza automáticamente con `git worktree remove`. Si configuró un hook WorktreeCreate para un sistema de control de versiones que no es git, emparéjelo con un hook WorktreeRemove para manejar la limpieza. Sin uno, el directorio del worktree se deja en el disco.
3243
3244Claude Code descarta los [campos de salida JSON](#json-output) de un hook WorktreeRemove, como `systemMessage` y `continue`.
3245
3246Para una eliminación de sesión de fondo, Claude Code verifica la ruta del worktree almacenada antes de ejecutar el hook y rechaza una ruta que es un symlink o pasa a través de uno debajo de la raíz del repositorio. El hook se ejecuta para un worktree que aún contiene archivos solo cuando confirma la eliminación en [vista de agente](/docs/es/agent-view#what-deleting-a-session-removes); para tal worktree, [`claude rm`](/docs/es/agent-view#manage-sessions-from-the-shell) mantiene la sesión y el worktree en su lugar. Antes de v2.1.216, el hook se ejecutaba en la ruta almacenada sin estas verificaciones.
2728 3247
2729Claude Code pasa la ruta devuelta por WorktreeCreate como `worktree_path` en la entrada del hook. Este ejemplo lee esa ruta y elimina el directorio:3248Claude Code pasa la ruta devuelta por WorktreeCreate como `worktree_path` en la entrada del hook. Este ejemplo lee esa ruta y elimina el directorio:
2730 3249
2761}3280}
2762```3281```
2763 3282
2764Los hooks WorktreeRemove no tienen control de decisión. No pueden bloquear la eliminación de worktree pero pueden realizar tareas de limpieza como eliminar estado de control de versiones o archivar cambios. Los fallos de hook se registran solo en modo de depuración.3283El código de salida de un hook WorktreeRemove decide el resultado. Cuando un hook sale con código distinto de cero y el directorio en `worktree_path` aún existe después, la eliminación falla:
3284
3285* El worktree permanece en el disco, y el comando del hook y stderr van al [registro de depuración](#debug-hooks).
3286* Si estaba eliminando una sesión de fondo, la sesión también permanece. El mensaje de rechazo en [vista de agente](/docs/es/agent-view#what-deleting-a-session-removes) reporta cómo terminó el hook, como `exited 1`, cita el inicio de su stderr, y dice si eliminar la sesión nuevamente elimina el directorio de todas formas.
2765 3287
2766<h3 id="precompact">3288<h3 id="precompact">
2767 PreCompact3289 PreCompact
2769 3291
2770Se ejecuta antes de que Claude Code esté a punto de ejecutar una operación de compactación.3292Se ejecuta antes de que Claude Code esté a punto de ejecutar una operación de compactación.
2771 3293
2772El valor del matcher indica si la compactación fue desencadenada manualmente o automáticamente:3294El valor del matcher indica si la compactación fue disparada manualmente o automáticamente:
2773 3295
2774| Matcher | Cuándo se activa |3296| Matcher | Cuándo se dispara |
2775| :------- | :--------------------------------------------------------------- |3297| :------- | :------------------------------------------------------------------------------------------------------------------------------------------- |
2776| `manual` | `/compact` |3298| `manual` | `/compact` |
2777| `auto` | Compactación automática cuando la ventana de contexto está llena |3299| `auto` | Compactación automática cuando la conversación alcanza la [ventana de compactación automática](/docs/es/model-config#set-the-auto-compact-window) |
3300
3301Salga con código 2 para bloquear la compactación. Para un `/compact` manual, el mensaje stderr se muestra al usuario. También puede bloquear devolviendo JSON con `"decision": "block"`.
2778 3302
2779Salga con código 2 para bloquear la compactación. Para un `/compact` manual, el mensaje de stderr se muestra al usuario. También puede bloquear devolviendo JSON con `"decision": "block"`.3303Bloquear la compactación automática tiene diferentes efectos dependiendo de cuándo se dispare. Si la compactación fue disparada de forma proactiva antes del límite de contexto, Claude Code la omite y la conversación continúa sin compactar. Si la compactación fue disparada para recuperarse de un error de límite de contexto ya devuelto por la API, el error subyacente surge y la solicitud actual falla.
2780 3304
2781Bloquear la compactación automática tiene diferentes efectos dependiendo de cuándo se active. Si la compactación fue desencadenada de forma proactiva antes del límite de contexto, Claude Code la omite y la conversación continúa sin compactar. Si la compactación fue desencadenada para recuperarse de un error de límite de contexto ya devuelto por la API, el error subyacente aparece y la solicitud actual falla.3305Claude Code descarta los campos `systemMessage` y `continue` de un hook PreCompact.
2782 3306
2783<h4 id="precompact-input">3307<h4 id="precompact-input">
2784 Entrada de PreCompact3308 Entrada de PreCompact
2785</h4>3309</h4>
2786 3310
2787Además de los [campos de entrada comunes](#common-input-fields), los hooks PreCompact reciben `trigger` e `custom_instructions`. Para `manual`, `custom_instructions` contiene lo que el usuario pasa a `/compact`. Para `auto`, `custom_instructions` está vacío.3311Además de los [campos de entrada comunes](#common-input-fields), los hooks PreCompact reciben `trigger` e `custom_instructions`. Para `manual`, `custom_instructions` contiene lo que el usuario pasa a `/compact` y es `null` cuando no pasa nada. Para `auto`, `custom_instructions` es `null`.
2788 3312
2789```json theme={null}3313```json theme={null}
2790{3314{
2793 "cwd": "/Users/...",3317 "cwd": "/Users/...",
2794 "hook_event_name": "PreCompact",3318 "hook_event_name": "PreCompact",
2795 "trigger": "manual",3319 "trigger": "manual",
2796 "custom_instructions": ""3320 "custom_instructions": null
2797}3321}
2798```3322```
2799 3323
2801 PostCompact3325 PostCompact
2802</h3>3326</h3>
2803 3327
2804Se ejecuta después de que Claude Code completa una operación de compactación. Use este evento para reaccionar al nuevo estado compactado, por ejemplo para registrar el resumen generado o actualizar el estado externo.3328Se ejecuta después de que Claude Code completa una operación de compactación. Úselo para reaccionar al nuevo estado compactado, por ejemplo para registrar el resumen generado o actualizar el estado externo. Claude Code descarta los campos `systemMessage` y `continue` de un hook PostCompact.
2805 3329
2806Los mismos valores de matcher se aplican que para `PreCompact`:3330Los mismos valores de matcher se aplican que para `PreCompact`:
2807 3331
2808| Matcher | Cuándo se activa |3332| Matcher | Cuándo se dispara |
2809| :------- | :-------------------------------------------------------------------------- |3333| :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------ |
2810| `manual` | Después de `/compact` |3334| `manual` | Después de `/compact` |
2811| `auto` | Después de compactación automática cuando la ventana de contexto está llena |3335| `auto` | Después de compactación automática cuando la conversación alcanza la [ventana de compactación automática](/docs/es/model-config#set-the-auto-compact-window) |
2812 3336
2813<h4 id="postcompact-input">3337<h4 id="postcompact-input">
2814 Entrada de PostCompact3338 Entrada de PostCompact
2827}3351}
2828```3352```
2829 3353
2830Los hooks PostCompact no tienen control de decisión. No pueden afectar el resultado de compactación pero pueden realizar tareas de seguimiento.3354Los hooks PostCompact no tienen control de decisión. No pueden afectar el resultado de la compactación pero pueden realizar tareas de seguimiento.
3355
3356<h3 id="premodelswitch">
3357 PreModelSwitch
3358</h3>
3359
3360Se ejecuta antes de que Claude Code aplique un cambio de modelo que solicitó usted o un cliente. Úselo para bloquear un cambio, requerir confirmación o mostrar cuánto costará el cambio antes de que suceda.
3361
3362PreModelSwitch requiere Claude Code v2.1.251 o posterior. Claude Code lo ejecuta para estas solicitudes:
3363
3364* `/model <name>` y el selector `/model`
3365* El selector de modelo `Option+P` o `Alt+P`
3366* La configuración Model en `/config`
3367* Activar [modo rápido](/docs/es/fast-mode) cuando eso cambia el modelo de la sesión
3368* Una solicitud `set_model`, o un cambio de modelo en una solicitud `apply_flag_settings`, desde un anfitrión [Agent SDK](/docs/es/agent-sdk/typescript#query-object) o [Control Remoto](/docs/es/remote-control)
3369
3370Claude Code no ejecuta hooks PreModelSwitch para cambios que realiza por su cuenta, como un [fallback de modelo automático](/docs/es/model-config#automatic-model-fallback) o restaurar el modelo cuando reanuda una sesión. Esos cambios llegan a [PostModelSwitch](#postmodelswitch) solo.
3371
3372Claude Code compara el matcher contra el nombre canónico del modelo al que la sesión está cambiando, ignorando cualquier sufijo `[1m]`. Un alias como `opus`, un ID de modelo fechado y un ID específico del proveedor como un ID de modelo de Amazon Bedrock todos coinciden con el único nombre canónico al que se resuelven, por lo que `claude-opus-5` cubre cada deletreo de Opus 5.
3373
3374Cuando Claude Code no puede determinar un nombre canónico para el objetivo, por ejemplo un ID de modelo personalizado que solo su [puerta de enlace LLM](/docs/es/llm-gateway) conoce, ejecuta cada hook PreModelSwitch independientemente del matcher. Un hook que bloquea debe verificar `to_model` de su entrada en lugar de confiar solo en el matcher.
3375
3376Escriba el matcher como un nombre exacto, una lista separada por `|` como `claude-opus-4-6|claude-opus-5`, o una expresión regular como `.*opus.*`. Este ejemplo usa un matcher de nombre exacto y también verifica `to_model` de la entrada del hook, por lo que rechaza un cambio a Opus 4.6 saliendo con código 2 y permite cualquier otro objetivo:
3377
3378<Tabs>
3379 <Tab title="macOS/Linux">
3380 El comando verifica `to_model` con `jq`:
3381
3382 ```json theme={null}
3383 {
3384 "hooks": {
3385 "PreModelSwitch": [
3386 {
3387 "matcher": "claude-opus-4-6",
3388 "hooks": [
3389 {
3390 "type": "command",
3391 "command": "jq -e '.to_model | test(\"opus-4-6\")' > /dev/null && { echo 'Opus 4.6 is retired for this project. Use a newer model.' >&2; exit 2; }; exit 0"
3392 }
3393 ]
3394 }
3395 ]
3396 }
3397 }
3398 ```
3399 </Tab>
3400
3401 <Tab title="Windows (PowerShell)">
3402 Registre un hook de comando que ejecute un script a través de PowerShell:
3403
3404 ```json theme={null}
3405 {
3406 "hooks": {
3407 "PreModelSwitch": [
3408 {
3409 "matcher": "claude-opus-4-6",
3410 "hooks": [
3411 {
3412 "type": "command",
3413 "command": "powershell.exe",
3414 "args": [
3415 "-NoProfile",
3416 "-ExecutionPolicy",
3417 "Bypass",
3418 "-File",
3419 "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-opus-46.ps1"
3420 ]
3421 }
3422 ]
3423 }
3424 ]
3425 }
3426 }
3427 ```
3428
3429 Guarde este script en `.claude/hooks/block-opus-46.ps1` en su proyecto:
3430
3431 ```powershell theme={null}
3432 $hookInput = [Console]::In.ReadToEnd() | ConvertFrom-Json
3433 if ($hookInput.to_model -match 'opus-4-6') {
3434 [Console]::Error.WriteLine('Opus 4.6 is retired for this project. Use a newer model.')
3435 exit 2
3436 }
3437 exit 0
3438 ```
3439 </Tab>
3440</Tabs>
3441
3442Para confirmar que el hook funciona, ejecute `/model claude-opus-4-6` desde una sesión que ejecuta un modelo diferente. Claude Code mantiene el modelo actual e informa que un hook PreModelSwitch bloqueó el cambio, con su mensaje como la razón.
3443
3444<h4 id="premodelswitch-input">
3445 Entrada de PreModelSwitch
3446</h4>
3447
3448Además de los [campos de entrada comunes](#common-input-fields), los hooks PreModelSwitch reciben los campos en esta tabla. Los últimos cinco describen qué cuesta reenviar la conversación al nuevo modelo, para que un hook pueda mostrar esa cifra antes de que suceda el cambio.
3449
3450| Campo | Tipo | Descripción |
3451| :-------------------------- | :-------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
3452| `from_model` | string | ID de modelo del que cambia el cambio |
3453| `to_model` | string | ID de modelo al que cambia el cambio. El matcher compara contra el nombre canónico de este modelo |
3454| `requested_model` | string o `null` | El modelo que la solicitud nombró: un alias como `opus`, un ID de modelo completo, o `null` cuando la solicitud fue para el modelo predeterminado |
3455| `source` | string | De dónde vino la solicitud: `"command"` para `/model <name>`, la configuración Model en `/config`, o activar modo rápido; `"picker"` para un selector de modelo; `"sdk"` para una solicitud `set_model`, o un cambio de modelo en una solicitud `apply_flag_settings`, desde un anfitrión Agent SDK o Control Remoto |
3456| `context_tokens` | number | Tokens que la siguiente solicitud reenvía como su prompt: los tokens de entrada, lectura de caché, creación de caché y salida de la última respuesta en la conversación principal, combinados. `0` antes de la primera respuesta |
3457| `prompt_cache_warm` | boolean | Si el caché de prompt del modelo actual probablemente aún esté caliente, lo que significa que el cambio lo pierde |
3458| `cache_ttl` | string | [Duración de vida del caché de prompt](/docs/es/prompt-caching#cache-lifetime) que Claude Code solicita para esta sesión: `"5m"` o `"1h"` |
3459| `estimated_cache_write_usd` | number | Costo estimado en dólares estadounidenses de escribir `context_tokens` en el caché de prompt en `to_model` a la tasa `cache_ttl`, excluyendo la siguiente respuesta. El servidor puede no necesitar re-cachear todo el contexto, así que trátelo como una estimación |
3460| `pricing` | string | Cómo Claude Code fijó el precio de `estimated_cache_write_usd`: `"configured"` a sus propias tasas de la organización cuando las ha configurado, `"catalog"` a precio de lista, o `"default"` cuando `to_model` no tiene precio conocido y Claude Code asumió una tasa predeterminada |
3461
3462Este ejemplo muestra la entrada para `/model opus` en una sesión que ejecuta Sonnet 5:
3463
3464```json theme={null}
3465{
3466 "session_id": "abc123",
3467 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
3468 "cwd": "/Users/...",
3469 "hook_event_name": "PreModelSwitch",
3470 "from_model": "claude-sonnet-5",
3471 "to_model": "claude-opus-5",
3472 "requested_model": "opus",
3473 "source": "command",
3474 "context_tokens": 182340,
3475 "prompt_cache_warm": true,
3476 "cache_ttl": "5m",
3477 "estimated_cache_write_usd": 1.1396,
3478 "pricing": "catalog"
3479}
3480```
3481
3482<h4 id="premodelswitch-decision-control">
3483 Control de decisión de PreModelSwitch
3484</h4>
3485
3486Los hooks `PreModelSwitch` pueden cancelar el cambio, pedir al usuario que lo confirme, o permitir que continúe. El código de salida 2 o un `decision: "block"` de nivel superior cancela el cambio.
3487
3488Para un control más fino, devuelva `permissionDecision` y `permissionDecisionReason` en un objeto `hookSpecificOutput`, como en [PreToolUse](#pretooluse-decision-control). `PreModelSwitch` acepta `"allow"`, `"deny"`, y `"ask"`. No acepta `"defer"`, `updatedInput`, o `additionalContext`. La tabla a continuación describe ambos campos:
3489
3490| Campo | Descripción |
3491| :------------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
3492| `permissionDecision` | `"allow"` continúa y omite la [confirmación que Claude Code muestra mientras el caché de prompt está caliente](/docs/es/prompt-caching#switching-models). `"deny"` cancela el cambio. `"ask"` solicita al usuario que lo confirme |
3493| `permissionDecisionReason` | Para `"deny"`, se muestra al usuario como la razón por la que se bloqueó el cambio, o se devuelve como el error para una solicitud `set_model`. Para `"ask"`, se muestra en el aviso de confirmación. Se ignora para `"allow"` |
3494
3495Solo `/model` en una sesión interactiva puede mostrar el aviso `"ask"`. En todas las otras superficies, incluido modo no interactivo con la bandera `-p`, `/config`, y solicitudes `set_model`, Claude Code trata `"ask"` como un rechazo.
3496
3497Este ejemplo pide al usuario que confirme y cita el recuento de tokens de `context_tokens`:
3498
3499```json theme={null}
3500{
3501 "hookSpecificOutput": {
3502 "hookEventName": "PreModelSwitch",
3503 "permissionDecision": "ask",
3504 "permissionDecisionReason": "Switching now re-sends about 180k tokens to the new model. Continue?"
3505 }
3506}
3507```
3508
3509Cuando múltiples hooks PreModelSwitch devuelven decisiones diferentes, la precedencia es `deny` > `ask` > `allow`.
3510
3511Claude Code muestra al usuario cualquier `systemMessage` que devuelva su hook independientemente de la decisión, por lo que un hook de informe de costos puede devolver `{"systemMessage": "..."}` y salir con 0.
3512
3513Un hook PreModelSwitch que no responde antes de su tiempo de espera bloquea el cambio. En [PreToolUse](#timeouts), por el contrario, un hook de comando que agota el tiempo de espera permite que la llamada de herramienta continúe. El tiempo de espera predeterminado para este evento es 30 segundos. `PreModelSwitch` ejecuta solo hooks `command`, `http`, y `mcp_tool`, por lo que los valores predeterminados `prompt` y `agent` no se aplican.
3514
3515Un hook que sale con un código distinto de 0 o 2 y no imprime ninguna decisión JSON no bloquea: Claude Code muestra su stderr y aplica el cambio, como se describe en [Otros códigos de salida](#other-exit-codes).
3516
3517<h3 id="postmodelswitch">
3518 PostModelSwitch
3519</h3>
3520
3521Se ejecuta después de que cambia el modelo de la sesión. Úselo para dar orientación específica del modelo a Claude sin editar cada CLAUDE.md, por ejemplo una instrucción de toda la organización que se aplica en ciertos modelos.
3522
3523PostModelSwitch requiere Claude Code v2.1.251 o posterior. No puede bloquear, porque el modelo ya ha cambiado. Claude Code ejecuta hooks PostModelSwitch después de cualquiera de estos cambios:
3524
3525* Un cambio que solicitó usted o un cliente
3526* Un [fallback de modelo automático](/docs/es/model-config#automatic-model-fallback), que cambia el modelo de la sesión
3527* Una configuración como [`opusplan`](/docs/es/model-config#opusplan-model-setting) entrando o saliendo del modo de plan
3528* Claude Code restaurando el modelo cuando reanuda una sesión
3529
3530Claude Code no ejecuta hooks PostModelSwitch cuando un modelo de una [cadena de modelo de fallback](/docs/es/model-config#fallback-model-chains) sirve un turno, porque esa sustitución dura un turno y deja el modelo de la sesión sin cambios.
3531
3532El matcher sigue las mismas reglas que [PreModelSwitch](#premodelswitch): Claude Code compara contra el nombre canónico del modelo al que la sesión cambió.
3533
3534Este ejemplo agrega orientación siempre que el modelo de la sesión cambia a cualquier modelo Opus:
3535
3536```json theme={null}
3537{
3538 "hooks": {
3539 "PostModelSwitch": [
3540 {
3541 "matcher": ".*opus.*",
3542 "hooks": [
3543 {
3544 "type": "command",
3545 "command": "echo 'On Opus, delegate implementation work to subagents and keep this conversation for planning and review.'"
3546 }
3547 ]
3548 }
3549 ]
3550 }
3551}
3552```
3553
3554Para confirmar que el hook funciona, cambie a un modelo Opus desde una sesión que ejecuta un modelo diferente, por ejemplo ejecute `/model opus` desde una sesión Sonnet, luego pregunte a Claude qué orientación tiene sobre el modelo actual.
3555
3556<h4 id="postmodelswitch-input">
3557 Entrada de PostModelSwitch
3558</h4>
3559
3560Los hooks PostModelSwitch reciben los mismos campos que [PreModelSwitch](#premodelswitch-input), con `hook_event_name` establecido en `"PostModelSwitch"` y dos valores `source` más: `"auto"` para un fallback automático u otro cambio que Claude Code realizó por su cuenta, y `"resume"` para el modelo restaurado cuando reanuda una sesión.
3561
3562`requested_model` es `null` cuando `source` es `"auto"`. Cuando `source` es `"resume"`, es la configuración de modelo guardada que Claude Code restauró.
3563
3564<h4 id="postmodelswitch-decision-control">
3565 Control de decisión de PostModelSwitch
3566</h4>
3567
3568Claude Code toma su stdout de texto plano del hook [](#exit-code-0) en salida 0, o `additionalContext` de salida JSON, y lo entrega a Claude con la siguiente solicitud después del cambio. Además de los [campos de salida JSON](#json-output) disponibles para todos los hooks, puede devolver:
3569
3570| Campo | Descripción |
3571| :------------------ | :--------------------------------------------------------------------------------------------------------------------------------- |
3572| `additionalContext` | Cadena agregada al contexto de Claude con la siguiente solicitud. Consulte [Agregar contexto para Claude](#add-context-for-claude) |
3573
3574Si el hook no se ha completado dentro de cinco segundos después de que envía la siguiente solicitud, Claude Code envía esa solicitud sin la salida y la adjunta a la siguiente solicitud en su lugar. Si el modelo cambia varias veces antes de la siguiente solicitud, Claude Code entrega solo la salida para el modelo de destino del último cambio.
2831 3575
2832<h3 id="sessionend">3576<h3 id="sessionend">
2833 SessionEnd3577 SessionEnd
2838El campo `reason` en la entrada del hook indica por qué terminó la sesión:3582El campo `reason` en la entrada del hook indica por qué terminó la sesión:
2839 3583
2840| Razón | Descripción |3584| Razón | Descripción |
2841| :---------------------------- | :------------------------------------------------------- |3585| :---------------------------- | :----------------------------------------------------------------------------------- |
2842| `clear` | Sesión borrada con comando `/clear` |3586| `clear` | Sesión borrada con comando `/clear` |
2843| `resume` | Sesión cambiada a través de `/resume` interactivo |3587| `resume` | Sesión cambiada a través de `/resume` interactivo |
2844| `logout` | Usuario cerró sesión |3588| `logout` | Usuario cerró sesión |
2845| `prompt_input_exit` | Usuario salió mientras la entrada del prompt era visible |3589| `prompt_input_exit` | Usuario salió mientras la entrada de prompt era visible |
2846| `bypass_permissions_disabled` | El modo de permisos de omisión fue deshabilitado |
2847| `other` | Otras razones de salida |3590| `other` | Otras razones de salida |
3591| `bypass_permissions_disabled` | Eliminado en v2.1.234; Claude Code no lo envía. Elimine de sus matchers `SessionEnd` |
2848 3592
2849<h4 id="sessionend-input">3593<h4 id="sessionend-input">
2850 Entrada de SessionEnd3594 Entrada de SessionEnd
2851</h4>3595</h4>
2852 3596
2853Además de los [campos de entrada comunes](#common-input-fields), los hooks SessionEnd reciben un campo `reason` que indica por qué terminó la sesión. Consulte la tabla de razones anterior para todos los valores.3597Además de los [campos de entrada comunes](#common-input-fields), los hooks SessionEnd reciben un campo `reason` que indica por qué terminó la sesión. Consulte la [tabla de razones](#sessionend) anterior para todos los valores.
2854 3598
2855```json theme={null}3599```json theme={null}
2856{3600{
2862}3606}
2863```3607```
2864 3608
2865Los hooks SessionEnd no tienen control de decisión. No pueden bloquear la terminación de sesión pero pueden realizar tareas de limpieza.3609Los hooks SessionEnd no tienen control de decisión. No pueden bloquear la terminación de la sesión pero pueden realizar tareas de limpieza. Claude Code descarta sus [campos de salida JSON](#json-output), como `systemMessage`.
3610
3611Los hooks SessionEnd tienen un tiempo de espera predeterminado de 1.5 segundos. Se aplica cuando sale, ejecuta `/clear`, o cambia sesiones con `/resume` interactivo. Puede dar a un hook más tiempo de dos formas:
2866 3612
2867Los hooks SessionEnd tienen un tiempo de espera predeterminado de 1,5 segundos. Esto se aplica tanto a la salida de sesión como a `/clear` y al cambio de sesiones a través de `/resume` interactivo. Si un hook necesita más tiempo, establezca un `timeout` por hook en la configuración del hook. El presupuesto general se aumenta automáticamente al tiempo de espera por hook más alto configurado en archivos de configuración, hasta 60 segundos. Los tiempos de espera establecidos en hooks proporcionados por plugins no aumentan el presupuesto. Para anular el presupuesto explícitamente, establezca la variable de entorno `CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` en milisegundos.3613* **`timeout` por hook**: establezca `timeout` en la configuración de ese hook. El presupuesto general se eleva automáticamente para coincidir con el `timeout` por hook más alto en sus archivos de configuración, hasta 60 segundos. Si eleva el presupuesto de esta manera, un hook sin su propio `timeout` aún mantiene el predeterminado. Los tiempos de espera establecidos en hooks proporcionados por plugins no elevan el presupuesto.
3614* **`CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS`**: establezca esta variable de entorno en milisegundos para anular el presupuesto explícitamente. El valor que establezca también se convierte en el tiempo de espera para cada hook sin su propio `timeout`.
3615
3616Este ejemplo establece el presupuesto en 5 segundos:
2868 3617
2869```bash theme={null}3618```bash theme={null}
2870CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS=5000 claude3619CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS=5000 claude
2871```3620```
2872 3621
3622Antes de v2.1.268, `CLAUDE_CODE_SESSIONEND_HOOKS_TIMEOUT_MS` solo elevaba el presupuesto general, y un hook sin su propio `timeout` aún se cancelaba después de 1.5 segundos.
3623
2873<h3 id="elicitation">3624<h3 id="elicitation">
2874 Elicitation3625 Elicitation
2875</h3>3626</h3>
2876 3627
2877Se ejecuta cuando un servidor MCP solicita entrada del usuario a mitad de la tarea. Por defecto, Claude Code muestra un diálogo interactivo para que el usuario responda. Los hooks pueden interceptar esta solicitud y responder programáticamente, omitiendo el diálogo completamente.3628Se ejecuta cuando un servidor MCP solicita entrada del usuario a mitad de tarea. De forma predeterminada, Claude Code muestra un diálogo interactivo para que el usuario responda. Los hooks pueden interceptar esta solicitud y responder programáticamente, omitiendo completamente el diálogo.
2878 3629
2879El campo matcher coincide con el nombre del servidor MCP.3630El campo matcher coincide contra el nombre del servidor MCP.
2880 3631
2881<h4 id="elicitation-input">3632<h4 id="elicitation-input">
2882 Entrada de Elicitation3633 Entrada de Elicitation
2883</h4>3634</h4>
2884 3635
2885Además de los [campos de entrada comunes](#common-input-fields), los hooks Elicitation reciben `mcp_server_name`, `message` y campos opcionales `mode`, `url`, `elicitation_id` y `requested_schema`.3636Además de los [campos de entrada comunes](#common-input-fields), los hooks Elicitation reciben `mcp_server_name`, `message`, y campos opcionales `mode`, `url`, `elicitation_id`, y `requested_schema`.
2886 3637
2887Para elicitación en modo formulario (el caso más común):3638Para elicitación de modo de formulario, el caso más común:
2888 3639
2889```json theme={null}3640```json theme={null}
2890{3641{
2891 "session_id": "abc123",3642 "session_id": "abc123",
2892 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",3643 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
2893 "cwd": "/Users/...",3644 "cwd": "/Users/...",
2894 "permission_mode": "default",
2895 "hook_event_name": "Elicitation",3645 "hook_event_name": "Elicitation",
2896 "mcp_server_name": "my-mcp-server",3646 "mcp_server_name": "my-mcp-server",
2897 "message": "Please provide your credentials",3647 "message": "Please provide your credentials",
2905}3655}
2906```3656```
2907 3657
2908Para elicitación en modo URL (autenticación basada en navegador):3658Para elicitación de modo URL, utilizada para autenticación basada en navegador:
2909 3659
2910```json theme={null}3660```json theme={null}
2911{3661{
2912 "session_id": "abc123",3662 "session_id": "abc123",
2913 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",3663 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
2914 "cwd": "/Users/...",3664 "cwd": "/Users/...",
2915 "permission_mode": "default",
2916 "hook_event_name": "Elicitation",3665 "hook_event_name": "Elicitation",
2917 "mcp_server_name": "my-mcp-server",3666 "mcp_server_name": "my-mcp-server",
2918 "message": "Please authenticate",3667 "message": "Please authenticate",
2944| `action` | `accept`, `decline`, `cancel` | Si aceptar, rechazar o cancelar la solicitud |3693| `action` | `accept`, `decline`, `cancel` | Si aceptar, rechazar o cancelar la solicitud |
2945| `content` | object | Valores de campo de formulario a enviar. Solo se usa cuando `action` es `accept` |3694| `content` | object | Valores de campo de formulario a enviar. Solo se usa cuando `action` es `accept` |
2946 3695
2947El código de salida 2 deniega la elicitación y muestra stderr al usuario.3696El código de salida 2 deniega la elicitación. Claude Code no muestra su mensaje stderr en ningún lugar.
3697
3698Claude Code actúa sobre `hookSpecificOutput` de la salida JSON de un hook Elicitation y descarta `systemMessage` y `continue`.
2948 3699
2949<h3 id="elicitationresult">3700<h3 id="elicitationresult">
2950 ElicitationResult3701 ElicitationResult
2951</h3>3702</h3>
2952 3703
2953Se ejecuta después de que un usuario responde a una elicitación MCP. Los hooks pueden observar, modificar o bloquear la respuesta antes de que se envíe de vuelta al servidor MCP.3704Se ejecuta después de que un usuario responde a una elicitación de MCP. Los hooks pueden observar, modificar o bloquear la respuesta antes de que se devuelva al servidor MCP.
2954 3705
2955El campo matcher coincide con el nombre del servidor MCP.3706El campo matcher coincide contra el nombre del servidor MCP.
2956 3707
2957<h4 id="elicitationresult-input">3708<h4 id="elicitationresult-input">
2958 Entrada de ElicitationResult3709 Entrada de ElicitationResult
2959</h4>3710</h4>
2960 3711
2961Además de los [campos de entrada comunes](#common-input-fields), los hooks ElicitationResult reciben `mcp_server_name`, `action` y campos opcionales `mode`, `elicitation_id` y `content`.3712Además de los [campos de entrada comunes](#common-input-fields), los hooks ElicitationResult reciben `mcp_server_name`, `action`, y campos opcionales `mode`, `elicitation_id`, y `content`.
2962 3713
2963```json theme={null}3714```json theme={null}
2964{3715{
2965 "session_id": "abc123",3716 "session_id": "abc123",
2966 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",3717 "transcript_path": "/Users/.../.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
2967 "cwd": "/Users/...",3718 "cwd": "/Users/...",
2968 "permission_mode": "default",
2969 "hook_event_name": "ElicitationResult",3719 "hook_event_name": "ElicitationResult",
2970 "mcp_server_name": "my-mcp-server",3720 "mcp_server_name": "my-mcp-server",
2971 "action": "accept",3721 "action": "accept",
2992```3742```
2993 3743
2994| Campo | Valores | Descripción |3744| Campo | Valores | Descripción |
2995| :-------- | :---------------------------- | :----------------------------------------------------------------------------------- |3745| :-------- | :---------------------------- | :---------------------------------------------------------------------------------------- |
2996| `action` | `accept`, `decline`, `cancel` | Anula la acción del usuario |3746| `action` | `accept`, `decline`, `cancel` | Anula la acción del usuario |
2997| `content` | object | Anula valores de campo de formulario. Solo significativo cuando `action` es `accept` |3747| `content` | object | Anula los valores del campo de formulario. Solo significativo cuando `action` es `accept` |
3748
3749El código de salida 2 bloquea la respuesta, cambiando la acción efectiva a `decline`. Claude Code no muestra su mensaje stderr en ningún lugar.
2998 3750
2999El código de salida 2 bloquea la respuesta, cambiando la acción efectiva a `decline`.3751Claude Code actúa sobre `hookSpecificOutput` de la salida JSON de un hook ElicitationResult y descarta `systemMessage` y `continue`.
3000 3752
3001<h2 id="prompt-based-hooks">3753<h2 id="prompt-based-hooks">
3002 Hooks basados en prompts3754 Hooks basados en prompts
3024 3776
3025* `ConfigChange`3777* `ConfigChange`
3026* `CwdChanged`3778* `CwdChanged`
3779* `DirectoryAdded`
3027* `Elicitation`3780* `Elicitation`
3028* `ElicitationResult`3781* `ElicitationResult`
3029* `FileChanged`3782* `FileChanged`
3030* `InstructionsLoaded`3783* `InstructionsLoaded`
3784* `MessageDisplay`
3031* `Notification`3785* `Notification`
3032* `PostCompact`3786* `PostCompact`
3787* `PostModelSwitch`
3033* `PreCompact`3788* `PreCompact`
3789* `PreModelSwitch`
3034* `SessionEnd`3790* `SessionEnd`
3035* `StopFailure`3791* `StopFailure`
3036* `SubagentStart`3792* `SubagentStart`
3037* `WorktreeCreate`3793* `WorktreeCreate`
3038* `WorktreeRemove`3794* `WorktreeRemove`
3039 3795
3040`SessionStart` y `Setup` admiten hooks `command` y `mcp_tool`. No admiten hooks `http`, `prompt` o `agent`.3796`SessionStart` y `Setup` admiten hooks `command` y `mcp_tool`, y [MCP tool hook fields](#mcp-tool-hook-fields) describe cuándo se ejecutan sus hooks `mcp_tool`. No admiten hooks `http`, `prompt` o `agent`.
3041 3797
3042<h3 id="how-prompt-based-hooks-work">3798<h3 id="how-prompt-based-hooks-work">
3043 Cómo funcionan los hooks basados en prompts3799 Cómo funcionan los hooks basados en prompts
3053 Configuración de hook de prompt3809 Configuración de hook de prompt
3054</h3>3810</h3>
3055 3811
3056Establezca `type` en `"prompt"` y proporcione una cadena `prompt` en lugar de un `command`. Use el marcador de posición `$ARGUMENTS` para inyectar datos de entrada JSON del hook en su texto de prompt. Claude Code envía el prompt combinado e entrada a un modelo Claude rápido, que devuelve una decisión JSON.3812Establezca `type` en `"prompt"` y proporcione una cadena `prompt` en lugar de un `command`. Use el marcador de posición `$ARGUMENTS` para inyectar datos de entrada JSON del hook en su texto de prompt.
3057 3813
3058Este hook `Stop` le pide al LLM que evalúe si todas las tareas están completas antes de permitir que Claude finalice:3814Este hook `Stop` le pide al LLM que evalúe si todas las tareas están completas antes de permitir que Claude finalice:
3059 3815
3075```3831```
3076 3832
3077| Campo | Requerido | Descripción |3833| Campo | Requerido | Descripción |
3078| :---------------- | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |3834| :---------------- | :-------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
3079| `type` | sí | Debe ser `"prompt"` |3835| `type` | sí | Debe ser `"prompt"` |
3080| `prompt` | sí | El texto del prompt a enviar al LLM. Use `$ARGUMENTS` como marcador de posición para la entrada JSON del hook. Si `$ARGUMENTS` no está presente, la entrada JSON se agrega al prompt |3836| `prompt` | sí | El texto del prompt a enviar al LLM. Use `$ARGUMENTS` como marcador de posición para la entrada JSON del hook. Si `$ARGUMENTS` no está presente, la entrada JSON se agrega al prompt |
3081| `model` | no | Modelo a usar para evaluación. Por defecto es un modelo rápido |3837| `model` | no | Modelo a usar para evaluación. Por defecto es un modelo rápido |
3082| `timeout` | no | Tiempo de espera en segundos. Predeterminado: 30 |3838| `timeout` | no | Tiempo de espera en segundos. Predeterminado: 30 |
3083| `continueOnBlock` | no | Cuando el prompt devuelve `ok: false`, retroalimente la razón a Claude y continúe el turno en lugar de detener. Predeterminado: `false`. Implementado como `continue: true` en la `decision: "block"` resultante. Consulte [Esquema de respuesta](#response-schema) para el comportamiento por evento |3839| `continueOnBlock` | no | En los eventos a los que se aplica, `true` retroalimenta una razón `ok: false` a Claude y continúa en lugar de terminar el turno. Predeterminado: `false`. Consulte [Esquema de respuesta](#response-schema) para el comportamiento por evento |
3084 3840
3085<h3 id="response-schema">3841<h3 id="response-schema">
3086 Esquema de respuesta3842 Esquema de respuesta
3091```json theme={null}3847```json theme={null}
3092{3848{
3093 "ok": true | false,3849 "ok": true | false,
3094 "reason": "Explanation for the decision"3850 "reason": "Explanation for the decision",
3851 "impossible": true | false
3095}3852}
3096```3853```
3097 3854
3098| Campo | Descripción |3855| Campo | Descripción |
3099| :------- | :------------------------------------------------------------------------------------------------------------------ |3856| :----------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
3100| `ok` | `true` para permitir. `false` produce una `decision: "block"`. Consulte el comportamiento por evento a continuación |3857| `ok` | `true` para permitir. Para `false`, consulte el comportamiento por evento a continuación |
3101| `reason` | Requerido cuando `ok` es `false`. Se usa como la razón del bloqueo |3858| `reason` | Requerido cuando `ok` es `false` |
3859| `impossible` | Opcional. El modelo lo devuelve con `ok: false` cuando juzga que la condición nunca puede satisfacerse. En `Stop` y `SubagentStop`, Claude Code permite que el turno termine en lugar de retroalimentar la razón. Los hooks de agente y otros eventos lo ignoran |
3102 3860
3103Lo que sucede en `ok: false` depende del evento:3861Lo que sucede en `ok: false` depende del evento:
3104 3862
3105* `Stop` y `SubagentStop`: la razón se retroalimenta a Claude como su siguiente instrucción y el turno continúa3863* `Stop` y `SubagentStop`: la razón se retroalimenta a Claude como su siguiente instrucción y el turno continúa, a menos que la respuesta también establezca `impossible: true`, en cuyo caso Claude Code permite la detención y el turno termina
3106* `PreToolUse`: la llamada de herramienta se deniega y la razón se devuelve a Claude como el error de la herramienta, equivalente a un hook de comando con `permissionDecision: "deny"`3864* `PreToolUse`: la llamada de herramienta se deniega; por defecto el turno termina y la razón de denegación aparece en el chat como una línea de advertencia. Establezca `continueOnBlock: true` para devolver la razón a Claude como el error de la herramienta para que pueda ajustarse y continuar, equivalente a un hook de comando con `permissionDecision: "deny"`. Antes de v2.1.210, la razón de denegación se devolvía a Claude como el error de la herramienta y el turno continuaba
3107* `PostToolUse`: por defecto el turno termina y la razón aparece en el chat como una línea de advertencia. Establezca `continueOnBlock: true` para retroalimentar la razón a Claude y continuar el turno en lugar de detener3865* `PostToolUse`: por defecto el turno termina y la razón aparece en el chat como una línea de advertencia. Establezca `continueOnBlock: true` para retroalimentar la razón a Claude y continuar el turno en lugar de detener
3108* `PostToolBatch`, `UserPromptSubmit` y `UserPromptExpansion`: el turno termina y la razón aparece como una línea de advertencia. Estos eventos terminan el turno en `decision: "block"` independientemente de `continue`3866* `PostToolBatch`, `UserPromptSubmit` y `UserPromptExpansion`: el turno termina y la razón aparece como una línea de advertencia. Estos eventos terminan el turno en `decision: "block"` independientemente de `continue`
3109* `PostToolUseFailure`, `TaskCreated` y `TaskCompleted`: la razón se devuelve a Claude como un error de herramienta, similar a `PreToolUse`3867* `PostToolUseFailure` y `TaskCreated`: la razón se devuelve a Claude como un error de herramienta y el turno continúa, independientemente de `continueOnBlock`
3868* `TaskCompleted`: cuando se activa porque una tarea se marca como completada durante un turno, la razón se devuelve a Claude como un error de herramienta y el turno continúa, independientemente de `continueOnBlock`. Cuando se activa porque un compañero se detiene, se comporta como `TeammateIdle` y detiene al compañero por defecto
3110* `TeammateIdle`: por defecto el compañero se detiene y la razón aparece como una línea de advertencia. Establezca `continueOnBlock: true` para retroalimentar la razón al compañero y mantenerlo trabajando en su lugar3869* `TeammateIdle`: por defecto el compañero se detiene y la razón aparece como una línea de advertencia. Establezca `continueOnBlock: true` para retroalimentar la razón al compañero y mantenerlo trabajando en su lugar
3111* `PermissionRequest`: `ok: false` no tiene efecto. Para denegar una aprobación desde un hook, use un [hook de comando](#command-hook-fields) que devuelva `hookSpecificOutput.decision.behavior: "deny"`3870* `PermissionRequest`: `ok: false` no tiene efecto. Para denegar una aprobación desde un hook, use un [hook de comando](#command-hook-fields) que devuelva `hookSpecificOutput.decision.behavior: "deny"`
3112* `PermissionDenied`: `ok: false` no tiene efecto porque la denegación ya sucedió. La única salida que este evento lee es `hookSpecificOutput.retry`, que los hooks de prompt y agente no pueden establecer. Se ejecutan en este evento, pero su salida se descarta. Use un [hook de comando](#command-hook-fields) para devolver `retry`3871* `PermissionDenied`: `ok: false` no tiene efecto porque la denegación ya sucedió. La única salida que este evento lee es `hookSpecificOutput.retry`, que los hooks de prompt y agente no pueden establecer. Se ejecutan en este evento, pero su salida se descarta. Use un [hook de comando](#command-hook-fields) para devolver `retry`
3117 Verificar múltiples condiciones antes de detener3876 Verificar múltiples condiciones antes de detener
3118</h3>3877</h3>
3119 3878
3120Este hook `Stop` usa un prompt detallado para verificar tres condiciones antes de permitir que Claude se detenga. Los hooks `SubagentStop` usan el mismo formato para evaluar si un [subagente](/docs/es/sub-agents) debe detenerse. Si `"ok"` es `false`, Claude continúa trabajando con la razón proporcionada como su siguiente instrucción:3879Este hook `Stop` usa un prompt detallado para verificar tres condiciones antes de permitir que Claude se detenga. Los hooks `SubagentStop` usan el mismo formato para evaluar si un [subagente](/docs/es/sub-agents) debe detenerse. Si el modelo devuelve `"ok": false` porque la condición aún no se cumple, Claude continúa trabajando con la razón proporcionada como su siguiente instrucción:
3121 3880
3122```json theme={null}3881```json theme={null}
3123{3882{
31561. Claude Code genera un subagente con su prompt y la entrada JSON del hook39151. Claude Code genera un subagente con su prompt y la entrada JSON del hook
31572. El subagente puede usar herramientas como Read, Grep y Glob para investigar39162. El subagente puede usar herramientas como Read, Grep y Glob para investigar
31583. Después de hasta 50 turnos, el subagente devuelve una decisión estructurada `{ "ok": true/false }`39173. Después de hasta 50 turnos, el subagente devuelve una decisión estructurada `{ "ok": true/false }`
31594. Claude Code procesa la decisión de la misma manera que un hook de prompt39184. Claude Code permite la acción si `ok` es `true`. Si `ok` es `false`, Claude Code maneja el bloqueo de la misma manera que un hook de prompt con `continueOnBlock: true` en ese evento, como se indica en [Esquema de respuesta](#response-schema)
3160 3919
3161Los hooks de agente son útiles cuando la verificación requiere inspeccionar archivos reales o salida de prueba, no solo evaluar los datos de entrada del hook solos.3920Los hooks de agente son útiles cuando la verificación requiere inspeccionar archivos reales o salida de prueba, no solo evaluar los datos de entrada del hook solos.
3162 3921
3164 Configuración de hook de agente3923 Configuración de hook de agente
3165</h3>3924</h3>
3166 3925
3167Establezca `type` en `"agent"` y proporcione una cadena `prompt`. Los campos de configuración son los mismos que los [hooks de prompt](#prompt-hook-configuration), con un tiempo de espera predeterminado más largo:3926Establezca `type` en `"agent"` y proporcione una cadena `prompt`, usando `$ARGUMENTS` como marcador de posición para la entrada JSON del hook. Los campos de configuración son los mismos que los [hooks de prompt](#prompt-hook-configuration), excepto que los hooks de agente tienen un tiempo de espera predeterminado más largo de 60 segundos y no tienen campo `continueOnBlock`.
3168
3169| Campo | Requerido | Descripción |
3170| :-------- | :-------- | :---------------------------------------------------------------------------------------------------------- |
3171| `type` | sí | Debe ser `"agent"` |
3172| `prompt` | sí | Prompt que describe qué verificar. Use `$ARGUMENTS` como marcador de posición para la entrada JSON del hook |
3173| `model` | no | Modelo a usar. Por defecto es un modelo rápido |
3174| `timeout` | no | Tiempo de espera en segundos. Predeterminado: 60 |
3175 3927
3176El esquema de respuesta es el mismo que los hooks de prompt: `{ "ok": true }` para permitir o `{ "ok": false, "reason": "..." }` para bloquear.3928El esquema de respuesta es `{ "ok": true }` para permitir o `{ "ok": false, "reason": "..." }` para bloquear. En `ok: false`, Claude Code maneja un hook de agente de la manera que maneja un [hook de prompt con `continueOnBlock: true`](#response-schema) en el mismo evento; los hooks de agente no tienen campo `continueOnBlock` y no admiten el campo `impossible` del hook de prompt.
3177 3929
3178Este hook `Stop` verifica que todas las pruebas unitarias pasen antes de permitir que Claude finalice:3930Este hook `Stop` verifica que todas las pruebas unitarias pasen antes de permitir que Claude finalice:
3179 3931
3207 3959
3208Agregue `"async": true` a la configuración de un hook de comando para ejecutarlo en segundo plano sin bloquear a Claude. Este campo solo está disponible en hooks `type: "command"`.3960Agregue `"async": true` a la configuración de un hook de comando para ejecutarlo en segundo plano sin bloquear a Claude. Este campo solo está disponible en hooks `type: "command"`.
3209 3961
3210Este hook ejecuta un script de prueba después de cada llamada a herramienta `Write`. Claude continúa trabajando inmediatamente mientras `run-tests.sh` se ejecuta durante hasta 120 segundos. Cuando el script finaliza, su salida se entrega en el siguiente turno de conversación:3962Este hook ejecuta un script de prueba después de cada llamada a herramienta `Write`. Claude continúa trabajando inmediatamente mientras `run-tests.sh` se ejecuta. Cuando el script finaliza, su salida se entrega en el siguiente turno de conversación:
3211 3963
3212```json theme={null}3964```json theme={null}
3213{3965{
3219 {3971 {
3220 "type": "command",3972 "type": "command",
3221 "command": "/path/to/run-tests.sh",3973 "command": "/path/to/run-tests.sh",
3222 "async": true,3974 "async": true
3223 "timeout": 120
3224 }3975 }
3225 ]3976 ]
3226 }3977 }
3229}3980}
3230```3981```
3231 3982
3232El campo `timeout` establece el tiempo máximo en segundos para el proceso de fondo. Si no se especifica, los hooks asincronos usan el mismo predeterminado de 10 minutos que los hooks sincronos.3983Una vez que un hook asincrónico se está ejecutando en segundo plano, Claude Code no aplica `timeout` en él. Claude Code aún aplica `timeout` en un hook que ejecuta con `asyncRewake`.
3984
3985Claude Code entrega los resultados de un hook asincrónico solo mientras se ejecuta la sesión:
3986
3987* En [modo no interactivo](/docs/es/headless) con la bandera `-p`, Claude Code mata cualquier hook asincrónico que aún se esté ejecutando al finalizar y lo finaliza con resultado `cancelled`
3988* Si el trabajo de su hook debe sobrevivir a una sesión `claude -p`, inicie un proceso completamente desacoplado desde él
3233 3989
3234<h3 id="how-async-hooks-execute">3990<h3 id="how-async-hooks-execute">
3235 Cómo se ejecutan los hooks asincronos3991 Cómo se ejecutan los hooks asincronos
3237 3993
3238Cuando se activa un hook asincrónico, Claude Code inicia el proceso del hook e inmediatamente continúa sin esperar a que finalice. El hook recibe la misma entrada JSON a través de stdin que un hook sincrónico.3994Cuando se activa un hook asincrónico, Claude Code inicia el proceso del hook e inmediatamente continúa sin esperar a que finalice. El hook recibe la misma entrada JSON a través de stdin que un hook sincrónico.
3239 3995
3240Después de que el proceso de fondo sale, si el hook produjo una respuesta JSON con un campo `additionalContext`, ese contenido se entrega a Claude como contexto en el siguiente turno de conversación. Un campo `systemMessage` se muestra a usted, no a Claude.3996Después de que el proceso de fondo sale, Claude Code entrega los campos `additionalContext` y `systemMessage` de la respuesta JSON del hook a Claude en el siguiente turno de conversación. A diferencia del `systemMessage` de un hook sincrónico, ninguno de estos campos se le muestra a usted.
3241 3997
3242Claude Code valida esa respuesta JSON contra el mismo [esquema de salida](#json-output) que los hooks sincronos, y descarta cualquier campo cuyo valor tenga el tipo incorrecto, como un `systemMessage` que no sea una cadena, en lugar de entregarlo. Ejecute con `--debug` para ver una advertencia que nombre cada campo descartado. Antes de v2.1.202, la salida JSON malformada de un hook asincrónico podría bloquear la sesión, y el bloqueo se repetía cada vez que se reanudaba la sesión.3998Claude Code valida esa respuesta JSON contra el mismo [esquema de salida](#json-output) que los hooks sincronos, y descarta cualquier campo cuyo valor tenga el tipo incorrecto, como un `systemMessage` que no sea una cadena, en lugar de entregarlo. Ejecute con `--debug` para ver una advertencia que nombre cada campo descartado. Antes de v2.1.202, la salida JSON malformada de un hook asincrónico podría bloquear la sesión, y el bloqueo se repetía cada vez que se reanudaba la sesión.
3243 3999
3287 "type": "command",4043 "type": "command",
3288 "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/run-tests-async.sh",4044 "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/run-tests-async.sh",
3289 "args": [],4045 "args": [],
3290 "async": true,4046 "async": true
3291 "timeout": 300
3292 }4047 }
3293 ]4048 ]
3294 }4049 }
3301 Limitaciones4056 Limitaciones
3302</h3>4057</h3>
3303 4058
3304Los hooks asincronos tienen varias restricciones en comparación con los hooks sincronos:4059Los hooks asincronos tienen restricciones adicionales en comparación con los hooks sincronos:
3305 4060
3306* Solo los hooks `type: "command"` admiten `async`. Los hooks basados en prompts no pueden ejecutarse de forma asincrónica.
3307* Los hooks asincronos no pueden bloquear llamadas a herramientas o devolver decisiones. En el momento en que se completa el hook, la acción desencadenante ya ha procedido.
3308* La salida del hook se entrega en el siguiente turno de conversación. Si la sesión está inactiva, la respuesta espera hasta la siguiente interacción del usuario. Excepción: un hook `asyncRewake` que sale con código 2 despierta a Claude inmediatamente incluso cuando la sesión está inactiva.4061* La salida del hook se entrega en el siguiente turno de conversación. Si la sesión está inactiva, la respuesta espera hasta la siguiente interacción del usuario. Excepción: un hook `asyncRewake` que sale con código 2 despierta a Claude inmediatamente incluso cuando la sesión está inactiva.
3309* Cada ejecución crea un proceso de fondo separado. No hay deduplicación en múltiples activaciones del mismo hook asincrónico.4062* Cada ejecución crea un proceso de fondo separado. No hay deduplicación en múltiples activaciones del mismo hook asincrónico.
3310 4063
3316 Descargo de responsabilidad4069 Descargo de responsabilidad
3317</h3>4070</h3>
3318 4071
3319Los hooks de comando se ejecutan con los permisos completos del usuario del sistema.
3320
3321<Warning>4072<Warning>
3322 Los hooks de comando ejecutan comandos de shell con sus permisos de usuario completos. Pueden modificar, eliminar o acceder a cualquier archivo al que su cuenta de usuario pueda acceder. Revise y pruebe todos los comandos de hook antes de agregarlos a su configuración.4073 Los hooks de comando ejecutan comandos de shell con sus permisos de usuario completos. Pueden modificar, eliminar o acceder a cualquier archivo al que su cuenta de usuario pueda acceder. Revise y pruebe todos los comandos de hook antes de agregarlos a su configuración.
3323</Warning>4074</Warning>
3324 4075
4076<h3 id="workspace-trust">
4077 Confianza del espacio de trabajo
4078</h3>
4079
4080Claude Code verifica la confianza del espacio de trabajo antes de ejecutar cualquier hook desde un archivo de configuración. Lo que cuenta como confiable depende del tipo de sesión:
4081
4082* **Sesión interactiva**: Claude Code retiene los hooks de todos los archivos de configuración, incluido su propio `~/.claude/settings.json`, hasta que acepte el [diálogo de confianza del espacio de trabajo](/docs/es/permissions#project-allow-rules-and-workspace-trust) para la carpeta, o para un directorio principal cuya confianza se extienda a ella
4083* **Sesión `-p` o SDK**: Claude Code nunca muestra el diálogo y trata la carpeta como confiable, por lo que los hooks confirmados en el `.claude/settings.json` de un repositorio se ejecutan en una carpeta que nunca ha confiado
4084
4085Antes de ejecutar `claude -p` en un repositorio que no escribió, revise sus archivos de configuración `.claude/`, comience con [`--bare`](/docs/es/headless#start-faster-with-bare-mode), o [desactive los hooks para esa ejecución](#disable-or-remove-hooks) con `--settings '{"disableAllHooks": true}'`. Los hooks de frontmatter en un subagente de proyecto siguen una regla más estricta que los hooks de archivo de configuración. [Lo que se ejecuta antes de confiar en una carpeta](/docs/es/permissions#what-runs-before-you-trust-a-folder) enumera cada tipo de contenido de repositorio por tipo de sesión.
4086
3325<h3 id="security-best-practices">4087<h3 id="security-best-practices">
3326 Mejores prácticas de seguridad4088 Mejores prácticas de seguridad
3327</h3>4089</h3>
3338 Herramienta PowerShell en Windows4100 Herramienta PowerShell en Windows
3339</h2>4101</h2>
3340 4102
3341En Windows, puede ejecutar hooks individuales en PowerShell estableciendo `"shell": "powershell"` en un hook de comando. Los hooks generan PowerShell directamente, por lo que esto funciona independientemente de si `CLAUDE_CODE_USE_POWERSHELL_TOOL` está establecido. Claude Code detecta automáticamente `pwsh.exe`, el ejecutable de PowerShell 7 y posterior, y recurre a `powershell.exe` para Windows PowerShell 5.1.4103En Windows, puede ejecutar hooks individuales en PowerShell estableciendo `"shell": "powershell"` en un hook de comando. Claude Code detecta automáticamente `pwsh.exe`, el ejecutable de PowerShell 7 y posterior, y recurre a `powershell.exe` para Windows PowerShell 5.1.
3342 4104
3343```json theme={null}4105```json theme={null}
3344{4106{
3379 Depurar hooks4141 Depurar hooks
3380</h2>4142</h2>
3381 4143
3382Los detalles de ejecución de hooks, incluyendo qué hooks coincidieron, sus códigos de salida y stdout y stderr completos, se escriben en el archivo de registro de depuración. Inicie Claude Code con `claude --debug-file <path>` para escribir el registro en una ubicación conocida, o ejecute `claude --debug` y lea el registro en `~/.claude/debug/<session-id>.txt`. La bandera `--debug` no imprime en la terminal.4144Los detalles de ejecución de hooks se escriben en el archivo de registro de depuración. Inicie Claude Code con `claude --debug-file <path>` para escribir el registro en una ubicación conocida, o ejecute `claude --debug` y lea el registro en `~/.claude/debug/<session-id>.txt`. La bandera `--debug` no imprime en la terminal.
4145
4146Por ejemplo, un hook `PostToolUse` en `Write` cuyo comando imprime `hook-ran` produce entradas como:
3383 4147
3384```text theme={null}4148```text theme={null}
3385[DEBUG] Executing hooks for PostToolUse:Write41492026-07-19T02:03:24.382Z [DEBUG] Hook output does not start with {, treating as plain text
3386[DEBUG] Found 1 hook commands to execute41502026-07-19T02:03:24.382Z [DEBUG] "Hook PostToolUse:Write (PostToolUse) success:\nhook-ran"
3387[DEBUG] Executing hook command: <Your command> with timeout 600000ms
3388[DEBUG] Hook command completed with status 0: <Your stdout>
3389```4151```
3390 4152
3391Para detalles de coincidencia de hooks más granulares, establezca `CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose` para ver líneas de registro adicionales como recuentos de matchers de hooks y coincidencia de consultas.4153Para detalles de coincidencia de hooks más granulares, establezca `CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose` para ver líneas de registro adicionales como recuentos de matchers de hooks y coincidencia de consultas.
3392 4154
3393Para solucionar problemas comunes como hooks que no se activan, bucles infinitos de hooks Stop o errores de configuración, consulte [Limitaciones y solución de problemas](/docs/es/hooks-guide#limitations-and-troubleshooting) en la guía. Para un recorrido de diagnóstico más amplio que cubra `/context`, `/doctor` y precedencia de configuración, consulte [Depure su configuración](/docs/es/debug-your-config).4155Para solucionar problemas comunes como hooks que no se activan, hooks Stop que siguen bloqueando, o errores de configuración, consulte [Limitaciones y solución de problemas](/docs/es/hooks-guide#limitations-and-troubleshooting) en la guía. Para un recorrido de diagnóstico más amplio que cubra `/context`, `/doctor` y precedencia de configuración, consulte [Depure su configuración](/docs/es/debug-your-config).