Hooks
Los hooks permiten observar, controlar y ampliar el bucle del agente mediante scripts personalizados. Define hooks en archivos hooks.json a nivel de proyecto o de usuario, o instálalos mediante plugins desde Personalizar. Los hooks son procesos que se ejecutan y se comunican mediante stdio usando JSON en ambas direcciones. Se ejecutan antes o después de etapas definidas del bucle del agente y pueden observar, bloquear o modificar su comportamiento.
Con los hooks, puedes:
- Ejecutar formateadores después de las ediciones
- Añadir analítica a los eventos
- Analizar PII o secretos
- Restringir operaciones de riesgo (p. ej., escrituras SQL)
- Controlar la ejecución de subagentes (herramienta Task)
- Inyectar contexto al inicio de la sesión
¿Buscas integraciones listas para usar? Consulta integraciones con socios para conocer soluciones de seguridad, gobernanza y gestión de secretos de nuestros socios del ecosistema.
Cursor permite cargar hooks desde herramientas de terceros como Claude Code. Consulta Hooks de terceros para obtener más información sobre compatibilidad y configuración.
Categorías de hooks
Los hooks se dividen en tres categorías según el evento que los activa:
Hooks de Agent (Cmd+K/Agent Chat) se activan durante una sesión del agente:
sessionStart/sessionEnd- Gestión del ciclo de vida de la sesiónpreToolUse/postToolUse/postToolUseFailure- Hooks genéricos para el uso de herramientas (se activan con todas las herramientas)subagentStart/subagentStop- Ciclo de vida de los subagentes (herramienta Task)beforeShellExecution/afterShellExecution- Controlan los comandos de shellbeforeMCPExecution/afterMCPExecution- Controlan el uso de herramientas MCPbeforeReadFile/afterFileEdit- Controlan el acceso a archivos y las edicionesbeforeSubmitPrompt- Validan las instrucciones antes de enviarlaspreCompact- Supervisan la compactación de la ventana de contextostop- Gestiona la finalización del agenteafterAgentResponse/afterAgentThought- Realizan un seguimiento de las respuestas del agente
Hooks de Tab (finalizaciones en línea) se activan en operaciones autónomas de Tab:
beforeTabFileRead- Controlan el acceso a archivos para las finalizaciones de TabafterTabFileEdit- Procesan las ediciones de Tab tras realizarlas
Hooks del ciclo de vida de la app se activan fuera de cualquier sesión del agente:
workspaceOpen- Se activa cuando Cursor abre un espacio de trabajo y cada vez que cambia una carpeta del espacio de trabajo. Puede devolver rutas de plugins adicionales que se cargarán para el espacio de trabajo actual.
Estas superficies de hooks independientes permiten aplicar distintas políticas a las operaciones autónomas de Tab, las operaciones de Agent dirigidas por el usuario y el inicio del espacio de trabajo.
Compatibilidad con agentes en la nube
Los agentes en la nube ejecutan hooks basados en comandos de tu repositorio. Si tienes hooks definidos en .cursor/hooks.json en la raíz de tu proyecto, los agentes en la nube los detectan y los ejecutan durante su trabajo.
En los planes Enterprise, los agentes en la nube también ejecutan hooks de equipo y hooks gestionados por la empresa configurados a través del Panel de control web.
Los agentes en la nube a veces comienzan en un entorno de solo lectura durante las primeras interacciones de exploración. Los hooks no se ejecutan durante esas interacciones. Se ejecutan una vez que el agente cuenta con un entorno con permisos de escritura.
Hooks compatibles
Los siguientes hooks se ejecutan en agentes en la nube:
| Hook | Compatible |
|---|---|
beforeShellExecution | Sí |
afterShellExecution | Sí |
beforeReadFile | Sí |
afterFileEdit | Sí |
preToolUse | Sí |
postToolUse | Sí |
postToolUseFailure | Sí |
subagentStart | Sí |
subagentStop | Sí |
beforeSubmitPrompt | Sí |
preCompact | Sí |
afterAgentResponse | Sí |
afterAgentThought | Sí |
stop | Sí |
Hooks no disponibles en agentes en la nube
Algunos hooks no se aplican a los agentes en la nube debido a diferencias en el entorno de ejecución:
| Hook | Motivo |
|---|---|
sessionStart | Se pospone, ya que los agentes en la nube pueden iniciarse en un entorno de solo lectura. Los hooks no se cargan en ese entorno, por lo que un sessionStart en la nube se activaría demasiado tarde (después de la primera escritura), en lugar de al inicio real de la sesión. |
sessionEnd | Los agentes en la nube no tienen un límite de sesión asociado a la duración del Editor. sessionEnd está vinculado a la sesión del IDE, no a un chat con un agente en la nube. |
beforeMCPExecution / afterMCPExecution | Se pospone, ya que los agentes en la nube pueden iniciarse en un entorno de solo lectura, donde los hooks no se cargan y no está claro cuándo deben ejecutarse los hooks de MCP. |
beforeTabFileRead / afterTabFileEdit | Las finalizaciones en línea de Tab son una función del IDE y no se ejecutan en agentes en la nube. |
workspaceOpen | Este es un hook del ciclo de vida del IDE y no se aplica a los agentes en la nube. |
Fuentes de configuración
Los agentes en la nube cargan hooks de estas fuentes:
- Hooks de proyecto (
.cursor/hooks.jsonen tu repo): Se cargan y ejecutan durante el trabajo del agente en la nube. - Hooks de equipo (Enterprise): Se distribuyen desde el panel de control y se ejecutan en agentes en la nube.
- Hooks de Enterprise (Enterprise): Hooks gestionados en todo el sistema que se ejecutan en agentes en la nube.
Los hooks de nivel de usuario (~/.cursor/hooks.json) no están disponibles en los agentes en la nube. Las VM de los agentes en la nube no tienen acceso a la configuración de tu directorio personal local.
Limitaciones según el tipo de ejecución
Los agentes en la nube solo ejecutan hooks basados en comandos. Los hooks basados en prompts requieren una conexión de autenticación entre el hook y el bucle del agente, que no está disponible en el entorno de ejecución en la nube.
Inicio rápido
Crea un archivo hooks.json. Puedes crearlo a nivel de proyecto (<project>/.cursor/hooks.json) o en tu directorio personal (~/.cursor/hooks.json). Los hooks de proyecto solo se aplican a ese proyecto, mientras que los hooks del directorio personal se aplican globalmente.
Para crear hooks de usuario que se apliquen globalmente, crea ~/.cursor/hooks.json:
{ "version": 1, "hooks": { "afterFileEdit": [{ "command": "./hooks/format.sh" }] }}Crea el script del hook en ~/.cursor/hooks/format.sh:
#!/bin/bash# Lee la entrada, realiza alguna acción y termina con 0cat > /dev/nullexit 0Hazlo ejecutable:
chmod +x ~/.cursor/hooks/format.shCursor supervisa los archivos de configuración de hooks y los recarga automáticamente. El hook se ejecuta después de cada edición de archivo.
Tipos de hooks
Los hooks admiten dos tipos de ejecución: basada en comandos (predeterminada) y basada en prompts (evaluada por un LLM).
Hooks basados en comandos
Los hooks de comandos ejecutan scripts de shell que reciben datos JSON a través de stdin y devuelven datos JSON a través de stdout.
{ "hooks": { "beforeShellExecution": [ { "command": "./scripts/approve-network.sh", "timeout": 30, "matcher": "curl|wget|nc" } ] }}Comportamiento del código de salida:
- Código de salida
0- El hook se ejecutó correctamente; usa la salida JSON - Código de salida
2- Bloquea la acción (equivale a devolverpermission: "deny") - Otros códigos de salida - El hook falló; la acción continúa (por defecto, no se bloquea en caso de error)
Hooks basados en prompts
Los hooks basados en prompts usan un LLM para evaluar una condición en lenguaje natural. Sirven para aplicar políticas sin necesidad de escribir scripts personalizados.
{ "hooks": { "beforeShellExecution": [ { "type": "prompt", "prompt": "Does this command look safe to execute? Only allow read-only operations.", "timeout": 10 } ] }}Funciones:
- Devuelve una respuesta estructurada de
{ ok: boolean, reason?: string } - Usa un modelo rápido para evaluaciones ágiles
- El marcador
$ARGUMENTSse reemplaza automáticamente por el JSON de entrada del hook - Si no está
$ARGUMENTS, la entrada del hook se añade automáticamente - Campo
modelopcional para anular el modelo de LLM predeterminado
Ejemplos
Los ejemplos siguientes usan las rutas ./hooks/..., que funcionan con los hooks de usuario (~/.cursor/hooks.json), ya que los scripts se ejecutan desde ~/.cursor/. Para los hooks de proyecto (<project>/.cursor/hooks.json), usa en su lugar las rutas .cursor/hooks/..., ya que los scripts se ejecutan desde la raíz del proyecto.
{ "version": 1, "hooks": { "sessionStart": [ { "command": "./hooks/session-init.sh" } ], "sessionEnd": [ { "command": "./hooks/audit.sh" } ], "beforeShellExecution": [ { "command": "./hooks/audit.sh" }, { "command": "./hooks/block-git.sh" } ], "beforeMCPExecution": [ { "command": "./hooks/audit.sh" } ], "afterShellExecution": [ { "command": "./hooks/audit.sh" } ], "afterMCPExecution": [ { "command": "./hooks/audit.sh" } ], "afterFileEdit": [ { "command": "./hooks/audit.sh" } ], "beforeSubmitPrompt": [ { "command": "./hooks/audit.sh" } ], "preCompact": [ { "command": "./hooks/audit.sh" } ], "stop": [ { "command": "./hooks/audit.sh" } ], "beforeTabFileRead": [ { "command": "./hooks/redact-secrets-tab.sh" } ], "afterTabFileEdit": [ { "command": "./hooks/format-tab.sh" } ] }}Hook de automatización stop en TypeScript
Elige TypeScript si necesitas JSON tipado, E/S de archivos persistente y llamadas HTTP en un mismo hook. Este hook stop basado en Bun registra en disco los recuentos de fallos por conversación, envía telemetría estructurada a una API interna y puede programar automáticamente un reintento cuando el agente falla dos veces seguidas.
{ "version": 1, "hooks": { "stop": [ { "command": "bun run .cursor/hooks/track-stop.ts --stop" } ] }}Establece AGENT_TELEMETRY_URL con el endpoint interno que debe recibir los resúmenes de ejecución.
Hook de protección para manifiestos de Python
Python destaca cuando necesitas bibliotecas avanzadas de análisis. Este hook usa pyyaml para inspeccionar manifiestos de Kubernetes antes de ejecutar kubectl apply; Bash tendría dificultades para analizar de forma segura archivos YAML con varios documentos.
{ "version": 1, "hooks": { "beforeShellExecution": [ { "command": "python3 .cursor/hooks/kube_guard.py" } ] }}Instala PyYAML (por ejemplo, pip install pyyaml) en todos los entornos donde se ejecuten tus scripts de hooks para que la importación del analizador funcione correctamente.
Integraciones con socios
Colaboramos con proveedores del ecosistema que han desarrollado compatibilidad con hooks para Cursor. Estas integraciones incluyen análisis de seguridad, gobernanza, gestión de secretos y más.
Gobernanza y visibilidad de MCP
| partner | Descripción |
|---|---|
| MintMCP | Cree un inventario completo de servidores MCP, supervise los patrones de uso de las herramientas y analice las respuestas para detectar datos confidenciales antes de que lleguen al modelo de IA. |
| Oasis Security | Aplique políticas de mínimo privilegio a las acciones de los agentes de IA y mantenga registros de auditoría completos en todos los sistemas de la empresa. |
| Runlayer | Encapsule las herramientas MCP e intégrelas con su intermediario MCP para centralizar el control y la visibilidad de las interacciones entre agentes y herramientas. |
Seguridad del código y mejores prácticas
| partner | Descripción |
|---|---|
| Corridor | Obtén comentarios en tiempo real sobre la implementación del código y las decisiones de diseño de seguridad mientras escribes código. |
| Semgrep | Analiza automáticamente el código generado por IA en busca de vulnerabilidades y recibe comentarios en tiempo real para regenerarlo hasta resolver las vulnerabilidades de seguridad. |
Seguridad de las dependencias
| partner | Descripción |
|---|---|
| Endor Labs | Intercepta la instalación de paquetes y analiza dependencias maliciosas para evitar ataques a la cadena de suministro antes de que lleguen a tu base de código. |
Seguridad de los agentes
| partner | Descripción |
|---|---|
| Snyk | Supervisa en tiempo real las acciones de los agentes con Evo Agent Guard para detectar y prevenir problemas como la inyección de prompts y las llamadas a herramientas peligrosas. |
Gestión de secretos
| Partner | Descripción |
|---|---|
| 1Password | Verifica que los archivos de entorno de 1Password Environments estén correctamente montados antes de ejecutar comandos de shell, lo que permite acceder a secretos justo a tiempo sin escribir credenciales en el disco. |
Para más información sobre nuestros partners de hooks, consulta la publicación del blog Hooks para equipos de seguridad y plataforma.
Configuración
Define hooks en un archivo hooks.json. La configuración puede existir en varios niveles. Se ejecutan todos los hooks coincidentes de cada fuente; cuando las respuestas entran en conflicto, prevalecen las fuentes de mayor prioridad durante la fusión:
~/.cursor/├── hooks.json└── hooks/ ├── audit.sh └── block-git.sh- Enterprise (gestionado por MDM en todo el sistema):
- macOS:
/Library/Application Support/Cursor/hooks.json - Linux/WSL:
/etc/cursor/hooks.json - Windows:
C:\\ProgramData\\Cursor\\hooks.json
- macOS:
- Equipo (distribuido desde Cloud, solo para Enterprise):
- Se configura en el Panel de control web y se sincroniza automáticamente con todos los miembros del equipo
- Proyecto (específico del proyecto):
<project-root>/.cursor/hooks.json- Los hooks de proyecto se ejecutan en cualquier espacio de trabajo de confianza y se incluyen en el control de versiones junto con el proyecto
- Usuario (específico del usuario):
~/.cursor/hooks.json
Orden de prioridad (de mayor a menor): Enterprise → Equipo → Proyecto → Usuario
El objeto hooks asigna nombres de hooks a arrays de definiciones de hooks. Actualmente, cada definición admite una propiedad command que puede ser una cadena de shell, una ruta absoluta o una ruta relativa. El directorio de trabajo depende del origen del hook:
- Hooks de proyecto (
.cursor/hooks.jsonen un repositorio): Se ejecutan desde la raíz del proyecto - Hooks de usuario (
~/.cursor/hooks.json): Se ejecutan desde~/.cursor/ - Hooks de Enterprise (configuración de todo el sistema): Se ejecutan desde el directorio de configuración de Enterprise
- Hooks de equipo (distribuidos desde Cloud): Se ejecutan desde el directorio de hooks gestionados
Para los hooks de proyecto, usa rutas como .cursor/hooks/script.sh (relativas a la raíz del proyecto), no ./hooks/script.sh (que buscaría <project>/hooks/script.sh).
Archivo de configuración
Este ejemplo muestra un archivo de hooks a nivel de usuario (~/.cursor/hooks.json). Para los hooks a nivel de proyecto, cambia rutas como ./hooks/script.sh por .cursor/hooks/script.sh:
{ "version": 1, "hooks": { "sessionStart": [{ "command": "./session-init.sh" }], "sessionEnd": [{ "command": "./audit.sh" }], "preToolUse": [ { "command": "./hooks/validate-tool.sh", "matcher": "Shell|Read|Write" } ], "postToolUse": [{ "command": "./hooks/audit-tool.sh" }], "subagentStart": [{ "command": "./hooks/validate-subagent.sh" }], "subagentStop": [{ "command": "./hooks/audit-subagent.sh" }], "beforeShellExecution": [{ "command": "./script.sh" }], "afterShellExecution": [{ "command": "./script.sh" }], "afterMCPExecution": [{ "command": "./script.sh" }], "afterFileEdit": [{ "command": "./format.sh" }], "preCompact": [{ "command": "./audit.sh" }], "stop": [{ "command": "./audit.sh", "loop_limit": 10 }], "beforeTabFileRead": [{ "command": "./redact-secrets-tab.sh" }], "afterTabFileEdit": [{ "command": "./format-tab.sh" }], "workspaceOpen": [{ "command": "./register-workspace-plugins.sh" }] }}Los hooks de Agent (sessionStart, sessionEnd, preToolUse, postToolUse, postToolUseFailure, subagentStart, subagentStop, beforeShellExecution, afterShellExecution, beforeMCPExecution, afterMCPExecution, beforeReadFile, afterFileEdit, beforeSubmitPrompt, preCompact, stop, afterAgentResponse, afterAgentThought) se aplican a las operaciones de Cmd+K y Agent Chat. Los hooks de Tab (beforeTabFileRead, afterTabFileEdit) se aplican específicamente a las finalizaciones en línea de Tab. El hook del ciclo de vida de la aplicación (workspaceOpen) se activa al abrir un espacio de trabajo y cuando cambian las carpetas del espacio de trabajo, independientemente de cualquier sesión del agente.
Opciones de configuración global
| Opción | Tipo | Predeterminado | Descripción |
|---|---|---|---|
version | número | 1 | Versión del esquema de configuración |
Opciones de configuración por script
| Opción | Tipo | Predeterminado | Descripción |
|---|---|---|---|
command | string | obligatorio | Ruta o comando del script |
type | "command" | "prompt" | "command" |
timeout | number | valor predeterminado de la plataforma | Tiempo de espera de ejecución en segundos |
loop_limit | number | null | 5 |
failClosed | boolean | false | Cuando es true, los errores del hook (bloqueo, tiempo de espera o JSON no válido) bloquean la acción en lugar de permitir que continúe. Útil para hooks críticos para la seguridad. |
matcher | object | - | Criterios de filtro que determinan cuándo se ejecuta el hook |
Configuración de matchers
Los matchers permiten filtrar cuándo se ejecuta un hook. El campo al que se aplica cada matcher depende del hook:
{ "hooks": { "preToolUse": [ { "command": "./validate-shell.sh", "matcher": "Shell" } ], "subagentStart": [ { "command": "./validate-explore.sh", "matcher": "explore|shell" } ], "beforeShellExecution": [ { "command": "./approve-network.sh", "matcher": "curl|wget|nc " } ] }}- subagentStart: El matcher se aplica al tipo de subagente (p. ej.,
explore,shell,generalPurpose). Úsalo para ejecutar hooks solo cuando se inicie un tipo específico de subagente. El ejemplo anterior ejecutavalidate-explore.shsolo para subagentes de exploración o de shell. - beforeShellExecution: El matcher se aplica a la cadena del comando de shell. Úsalo para ejecutar hooks solo cuando el comando coincida con un patrón (p. ej., llamadas de red o eliminación de archivos). El ejemplo anterior ejecuta
approve-network.shsolo cuando el comando contienecurl,wgetonc.
Matchers disponibles por hook:
- preToolUse / postToolUse / postToolUseFailure: Filtra por tipo de herramienta. Los valores incluyen
Shell,Read,Write,Grep,Delete,Tasky herramientas MCP con el formatoMCP:<tool_name>. - subagentStart / subagentStop: Filtra por tipo de subagente (
generalPurpose,explore,shell, etc.). - beforeShellExecution / afterShellExecution: Filtra por el texto del comando de shell; el matcher se aplica a la cadena completa del comando.
- beforeReadFile: Filtra por tipo de herramienta (
TabRead,Read, etc.). - afterFileEdit: Filtra por tipo de herramienta (
TabWrite,Write, etc.). - beforeSubmitPrompt: Se aplica al valor
UserPromptSubmit. - stop: Se aplica al valor
Stop. - afterAgentResponse: Se aplica al valor
AgentResponse. - afterAgentThought: Se aplica al valor
AgentThought.
Distribución en equipos
Los hooks pueden distribuirse a los miembros del equipo mediante hooks de proyecto (a través del control de versiones), herramientas de MDM o el sistema de distribución en la nube de Cursor.
Hooks de proyecto (control de versiones)
Los hooks de proyecto son la forma más sencilla de compartir hooks con tu equipo. Coloca un archivo hooks.json en <project-root>/.cursor/hooks.json y súbelo a tu repositorio. Cuando los miembros del equipo abren el proyecto en un espacio de trabajo de confianza, Cursor carga y ejecuta automáticamente los hooks de proyecto.
Los agentes en la nube también cargan estos hooks de proyecto cuando trabajan en tu repositorio en la nube.
Los hooks de proyecto:
- Se almacenan en el control de versiones junto con tu código
- Se cargan automáticamente para todos los miembros del equipo en espacios de trabajo de confianza
- Pueden ser específicos del proyecto (p. ej., para aplicar estándares de formato a una base de código concreta)
- Requieren un espacio de trabajo de confianza para ejecutarse (por seguridad)
Distribución mediante MDM
Distribuye hooks en toda tu organización mediante herramientas de gestión de dispositivos móviles (MDM). Coloca el archivo hooks.json y los scripts de hooks en los directorios de destino de cada máquina.
Directorio de inicio del usuario (distribución por usuario):
~/.cursor/hooks.json~/.cursor/hooks/(para scripts de hooks)
Directorios globales (distribución para todo el sistema):
- macOS:
/Library/Application Support/Cursor/hooks.json - Linux/WSL:
/etc/cursor/hooks.json - Windows:
C:\\ProgramData\\Cursor\\hooks.json
Nota: La distribución mediante MDM está totalmente gestionada por tu organización. Cursor no implementa ni gestiona archivos a través de tu solución MDM. Asegúrate de que tu equipo interno de TI o seguridad se encargue de la configuración, la implementación y las actualizaciones conforme a las políticas de tu organización.
Distribución en la nube (solo Enterprise)
Los equipos Enterprise pueden usar la distribución nativa en la nube de Cursor para sincronizar automáticamente los hooks con todos los miembros del equipo. Configure los hooks en el Panel de control web. Cursor entrega automáticamente los hooks configurados a todas las máquinas cliente cuando los miembros del equipo inician sesión.
La distribución en la nube ofrece:
- Sincronización automática con todos los miembros del equipo (cada treinta minutos)
- Selección por sistema operativo para hooks específicos de cada plataforma
- Gestión centralizada desde el panel de control
Los administradores de Enterprise pueden crear, editar y gestionar hooks de equipo desde el panel de control sin necesidad de acceder a máquinas individuales.
Contacte con ventas para obtener la distribución de hooks en la nube para Enterprise.
Referencia
Esquema común
Entrada (todos los hooks)
Todos los hooks reciben un conjunto básico de campos, además de los campos específicos de cada hook:
{ "conversation_id": "string", "generation_id": "string", "model": "string", "model_id": "string", "model_params": [{ "id": "string", "value": "string" }], "hook_event_name": "string", "cursor_version": "string", "workspace_roots": ["<path>"], "user_email": "string | null", "transcript_path": "string | null"}| Campo | Tipo | Descripción | |
|---|---|---|---|
conversation_id | string | ID estable de la conversación a lo largo de varias interacciones | |
generation_id | string | La generación actual, que cambia con cada mensaje del usuario | |
model | string | Slug del modelo heredado configurado para el composer que activó el hook | |
model_id | string (optional) | ID estructurado del modelo seleccionado, cuando está disponible | |
model_params | array (optional) | Parámetros del modelo seleccionado, como thinking, contexto o esfuerzo. Cada elemento tiene un id y un value. | |
hook_event_name | string | El hook que se está ejecutando | |
cursor_version | string | Versión de la aplicación Cursor (p. ej., "1.7.2") | |
workspace_roots | string[] | Lista de carpetas raíz del espacio de trabajo (normalmente solo una, pero los espacios de trabajo multirraíz pueden tener varias) | |
user_email | string | null | Dirección de correo electrónico del usuario autenticado, si está disponible |
transcript_path | string | null | Ruta al archivo de transcripción de la conversación principal (null si las transcripciones están desactivadas) |
Los hooks del ciclo de vida de la aplicación (workspaceOpen) se activan fuera de cualquier sesión del agente, por lo que la solicitud omite conversation_id, generation_id, model, session_id y transcript_path. Aun así, reciben hook_event_name, cursor_version, workspace_roots y user_email.
Eventos de hooks
preToolUse
Se invoca antes de ejecutar cualquier herramienta. Es un hook genérico que se activa con todos los tipos de herramientas (Shell, Read, Write, MCP, Task, etc.). Usa matchers para filtrar herramientas específicas.
// Entrada{ "tool_name": "Shell", "tool_input": { "command": "npm install", "working_directory": "/project" }, "tool_use_id": "abc123", "cwd": "/project", "model": "claude-opus-4-7-thinking-max", "model_id": "claude-opus-4-7", "model_params": [ { "id": "thinking", "value": "true" }, { "id": "context", "value": "1m" }, { "id": "effort", "value": "max" } ], "agent_message": "Installing dependencies..."}// Salida{ "permission": "allow" | "deny", "user_message": "<message shown in client when denied>", "agent_message": "<message sent to agent when denied>", "updated_input": { "command": "npm ci" }}| Campo de salida | Tipo | Descripción |
|---|---|---|
permission | string | "allow" para permitir la acción, "deny" para bloquearla. "ask" se acepta en el esquema, pero actualmente no se aplica para preToolUse. |
user_message | string (opcional) | Mensaje que se muestra al usuario cuando se deniega la acción |
agent_message | string (opcional) | Mensaje que se envía al agente cuando se deniega la acción |
updated_input | objeto (opcional) | Entrada de la herramienta modificada para usar en su lugar |
postToolUse
Se invoca tras ejecutar correctamente una herramienta. Útil para auditorías, analítica e inyectar contexto.
// Entrada{ "tool_name": "Shell", "tool_input": { "command": "npm test" }, "tool_output": "{\"exitCode\":0,\"stdout\":\"All tests passed\"}", "tool_use_id": "abc123", "cwd": "/project", "duration": 5432, "model": "claude-opus-4-7-thinking-max", "model_id": "claude-opus-4-7", "model_params": [ { "id": "thinking", "value": "true" }, { "id": "context", "value": "1m" }, { "id": "effort", "value": "max" } ]}// Salida{ "updated_mcp_tool_output": { "modified": "output" }, "additional_context": "Test coverage report attached."}| Campo de entrada | Tipo | Descripción |
|---|---|---|
duration | number | Tiempo de ejecución en milisegundos |
tool_output | string | Payload de resultado de la herramienta serializado como JSON (no texto sin procesar de la terminal) |
| Campo de salida | Tipo | Descripción |
|---|---|---|
updated_mcp_tool_output | objeto (opcional) | Solo para herramientas MCP: reemplaza la salida de la herramienta que ve el modelo |
additional_context | string (opcional) | Contexto adicional inyectado en la conversación después del resultado de la herramienta |
postToolUseFailure
Se llama cuando una herramienta falla, se agota el tiempo de espera o se rechaza. Útil para el seguimiento de errores y la lógica de recuperación.
// Entrada{ "tool_name": "Shell", "tool_input": { "command": "npm test" }, "tool_use_id": "abc123", "cwd": "/project", "error_message": "Command timed out after 30s", "failure_type": "timeout" | "error" | "permission_denied", "duration": 5000, "is_interrupt": false}// Salida{ // Actualmente no se admiten campos de salida}| Campo de entrada | Tipo | Descripción |
|---|---|---|
error_message | string | Descripción del error |
failure_type | string | Tipo de error: "error", "timeout" o "permission_denied" |
duration | number | Tiempo transcurrido en milisegundos hasta que se produjo el error |
is_interrupt | boolean | Indica si este error se debió a una interrupción o cancelación del usuario |
subagentStart
Se invoca antes de iniciar un subagente (herramienta Task). Puede permitir o denegar la creación de subagentes.
// Entrada{ "subagent_id": "abc-123", "subagent_type": "generalPurpose", "task": "Explore the authentication flow", "parent_conversation_id": "conv-456", "tool_call_id": "tc-789", "subagent_model": "claude-sonnet-4-20250514", "is_parallel_worker": false, "git_branch": "feature/auth"}// Salida{ "permission": "allow" | "deny", "user_message": "<message shown when denied>"}| Campo de entrada | Tipo | Descripción |
|---|---|---|
subagent_id | string | Identificador único de esta instancia de subagente |
subagent_type | string | Tipo de subagente: generalPurpose, explore, shell, etc. |
task | string | Descripción de la tarea asignada al subagente |
parent_conversation_id | string | ID de conversación de la sesión del agente principal |
tool_call_id | string | ID de la llamada a herramienta que activó el subagente |
subagent_model | string | Modelo que usará el subagente |
is_parallel_worker | boolean | Indica si este subagente se ejecuta como worker paralelo |
git_branch | string (optional) | Rama de Git en la que operará el subagente, si corresponde |
| Campo de salida | Tipo | Descripción |
|---|---|---|
permission | string | "allow" para continuar, "deny" para bloquear. "ask" no es compatible con subagentStart y se trata como "deny". |
user_message | string (optional) | Mensaje que se muestra al usuario cuando se deniega el subagente |
subagentStop
Se llama cuando un subagente finaliza, presenta errores o se cancela. Puede activar acciones de seguimiento.
// Entrada{ "subagent_type": "generalPurpose", "status": "completed" | "error" | "aborted", "task": "Explore the authentication flow", "description": "Exploring auth flow", "summary": "<subagent output summary>", "duration_ms": 45000, "message_count": 12, "tool_call_count": 8, "loop_count": 0, "modified_files": ["src/auth.ts"], "agent_transcript_path": "/path/to/subagent/transcript.txt"}// Salida{ "followup_message": "<auto-continue with this message>"}| Campo de entrada | Tipo | Descripción | |
|---|---|---|---|
subagent_type | string | Tipo de subagente: generalPurpose, explore, shell, etc. | |
status | string | "completed", "error" o "aborted" | |
task | string | Descripción de la tarea asignada al subagente | |
description | string | Breve descripción del propósito del subagente | |
summary | string | Resumen de la salida del subagente | |
duration_ms | number | Tiempo de ejecución en milisegundos | |
message_count | number | Número de mensajes intercambiados durante la sesión del subagente | |
tool_call_count | number | Número de llamadas a herramientas realizadas por el subagente | |
loop_count | number | Número de veces que un seguimiento de subagentStop ya se ha activado para este subagente (empieza en 0) | |
modified_files | string[] | Archivos modificados por el subagente | |
agent_transcript_path | string | null | Ruta al archivo de transcripción propio del subagente (independiente de la conversación principal) |
| Campo de salida | Tipo | Descripción |
|---|---|---|
followup_message | string (optional) | Continúa automáticamente con este mensaje. Solo se procesa cuando status es "completed". |
El campo followup_message permite flujos en bucle en los que la finalización de un subagente activa la siguiente iteración. Los mensajes de seguimiento están sujetos al mismo límite de bucle configurable que el hook stop (5 de forma predeterminada, configurable mediante loop_limit).
beforeShellExecution / beforeMCPExecution
Se ejecuta antes de que se ejecute cualquier comando de shell o herramienta MCP. Devuelve una decisión de permiso.
De forma predeterminada, los errores del hook (fallo, tiempo de espera, JSON no válido) permiten que la acción continúe (fail-open). Establece failClosed: true en la definición del hook para bloquear la acción en caso de error. Se recomienda para hooks de beforeMCPExecution críticos para la seguridad.
// entrada de beforeShellExecution{ "command": "<full terminal command>", "cwd": "<current working directory>", "sandbox": false}// entrada de beforeMCPExecution{ "tool_name": "<tool name>", "tool_input": "<json params>"}// Además, una de estas opciones:{ "url": "<server url>" }// O:{ "command": "<command string>" }// Salida{ "permission": "allow" | "deny" | "ask", "user_message": "<message shown in client>", "agent_message": "<message sent to agent>"}afterShellExecution
Se activa después de ejecutar un comando de shell; resulta útil para auditorías o para recopilar métricas de la salida del comando.
// Entrada{ "command": "<full terminal command>", "output": "<full terminal output>", "duration": 1234, "sandbox": false}| Campo | Tipo | Descripción |
|---|---|---|
command | string | El comando de terminal completo que se ejecutó |
output | string | La salida completa capturada de la terminal |
duration | number | Duración en milisegundos de la ejecución del comando de shell (no incluye el tiempo de espera de aprobación) |
sandbox | boolean | Indica si el comando se ejecutó en un entorno aislado |
afterMCPExecution
Se activa después de ejecutar una herramienta MCP; incluye los parámetros de entrada de la herramienta y el resultado completo en JSON.
// Entrada{ "tool_name": "<tool name>", "tool_input": "<json params>", "result_json": "<tool result json>", "duration": 1234}| Campo | Tipo | Descripción |
|---|---|---|
tool_name | string | Nombre de la herramienta MCP ejecutada |
tool_input | string | Cadena de parámetros JSON pasada a la herramienta |
result_json | string | Cadena JSON de la respuesta de la herramienta |
duration | number | Duración en milisegundos de la ejecución de la herramienta MCP (no incluye el tiempo de espera de aprobación) |
afterFileEdit
Se activa después de que el agente edite un archivo; resulta útil para formateadores o para contabilizar el código escrito por el agente.
// Entrada{ "file_path": "<absolute path>", "edits": [{ "old_string": "<search>", "new_string": "<replace>" }]}beforeReadFile
Se ejecuta antes de que el agente lea un archivo. Úsalo para controlar el acceso e impedir que se envíen archivos confidenciales al modelo.
De forma predeterminada, los errores del hook beforeReadFile (fallo, tiempo de espera o JSON no válido) se registran y se permite la lectura. Establece failClosed: true en la definición del hook para bloquear la lectura en caso de fallo.
// Entrada{ "file_path": "<absolute path>", "content": "<file contents>", "attachments": [ { "type": "file" | "rule", "file_path": "<absolute path>" } ]}// Salida{ "permission": "allow" | "deny", "user_message": "<message shown when denied>"}| Campo de entrada | Tipo | Descripción |
|---|---|---|
file_path | string | Ruta absoluta del archivo que se está leyendo |
content | string | Contenido completo del archivo |
attachments | array | Archivos adjuntos de contexto asociados a la instrucción. Cada entrada tiene un type ("file" o "rule") y un file_path. |
| Campo de salida | Tipo | Descripción |
|---|---|---|
permission | string | "allow" para continuar, "deny" para bloquear |
user_message | string (opcional) | Mensaje que se muestra al usuario cuando se deniega |
beforeTabFileRead
Se invoca antes de que Tab (completaciones en línea) lea un archivo. Activa la redacción o el control de acceso antes de que Tab acceda al contenido del archivo.
Diferencias clave respecto a beforeReadFile:
- Solo se activa con Tab, no con agente
- No incluye el campo
attachments(Tab no usa archivos adjuntos en las instrucciones) - Útil para aplicar políticas diferentes a las operaciones autónomas de Tab
// Entrada{ "file_path": "<absolute path>", "content": "<file contents>"}// Salida{ "permission": "allow" | "deny"}afterTabFileEdit
Se llama después de que Tab (completaciones en línea) edite un archivo. Es útil para formateadores o para auditar código escrito por Tab.
Diferencias clave con afterFileEdit:
- Solo lo activa Tab, no agente
- Incluye información detallada sobre la edición:
range,old_lineynew_linepara realizar un seguimiento preciso de los cambios - Útil para formatear o analizar en detalle las ediciones de Tab
// Entrada{ "file_path": "<absolute path>", "edits": [ { "old_string": "<search>", "new_string": "<replace>", "range": { "start_line_number": 10, "start_column": 5, "end_line_number": 10, "end_column": 20 }, "old_line": "<line before edit>", "new_line": "<line after edit>" } ]}// Salida{ // Actualmente no se admiten campos de salida}beforeSubmitPrompt
Se llama justo después de que el usuario pulsa Enviar, pero antes de la solicitud al backend. Puede impedir el envío.
// Entrada{ "prompt": "<user prompt text>", "attachments": [ { "type": "file" | "rule", "file_path": "<absolute path>" } ]}// Salida{ "continue": true | false, "user_message": "<message shown to user when blocked>"}| Campo de salida | Tipo | Descripción |
|---|---|---|
continue | boolean | Indica si se permite continuar con el envío de la instrucción |
user_message | string (opcional) | Mensaje que se muestra al usuario cuando se bloquea la instrucción |
afterAgentResponse
Se invoca después de que el agente haya completado un mensaje del asistente.
// Entrada{ "text": "<assistant final text>"}afterAgentThought
Se llama cuando el agente termina un bloque de razonamiento. Útil para observar su proceso de razonamiento.
// Entrada{ "text": "<fully aggregated thinking text>", "duration_ms": 5000}// Salida{ // Actualmente no se admiten campos de salida}| Campo | Tipo | Descripción |
|---|---|---|
text | string | Texto de razonamiento agregado completo del bloque finalizado |
duration_ms | number (optional) | Duración en milisegundos del bloque de razonamiento |
stop
Se ejecuta cuando finaliza el ciclo del agente. Opcionalmente, puede enviar automáticamente un mensaje de seguimiento del usuario para continuar iterando.
// Entrada{ "status": "completed" | "aborted" | "error", "loop_count": 0}// Salida{ "followup_message": "<message text>"}- El
followup_messageopcional es una cadena. Si se proporciona y no está vacío, Cursor lo enviará automáticamente como el siguiente mensaje del usuario. Esto permite flujos en bucle (p. ej., iterar hasta alcanzar un objetivo). - El campo
loop_countindica cuántas veces el hookstopya ha activado un mensaje de seguimiento automático para esta conversación (comienza en 0). El límite predeterminado es de 5 mensajes de seguimiento automáticos por script, configurable mediante la opciónloop_limit. Estableceloop_limitennullpara eliminar el límite. El mismo límite se aplica a los mensajes de seguimiento desubagentStop.
sessionStart
Se invoca cuando se crea una nueva conversación de composer. Este hook se ejecuta de forma fire-and-forget; el bucle del agente no espera ni exige una respuesta bloqueante. Úsalo para configurar variables de entorno específicas de la sesión o inyectar contexto adicional.
// Entrada{ "session_id": "<unique session identifier>", "is_background_agent": true | false, "composer_mode": "agent" | "ask" | "edit"}// Salida{ "env": { "<key>": "<value>" }, "additional_context": "<context to add to conversation>"}| Campo de entrada | Tipo | Descripción |
|---|---|---|
session_id | string | Identificador único de esta sesión (igual que conversation_id) |
is_background_agent | boolean | Indica si se trata de una sesión de agente en segundo plano o de una sesión interactiva |
composer_mode | string (opcional) | El modo en el que se inicia composer (p. ej., "agent", "ask", "edit") |
| Campo de salida | Tipo | Descripción |
|---|---|---|
env | objeto (opcional) | Variables de entorno que se deben establecer para esta sesión. Están disponibles para todas las ejecuciones posteriores de hooks |
additional_context | string (opcional) | Contexto adicional que se debe añadir al contexto inicial del sistema de la conversación |
El esquema también acepta los campos continue y user_message, pero los llamadores actuales no los exigen. La creación de la sesión no se bloquea aunque continue sea false.
sessionEnd
Se llama cuando finaliza una conversación de composer. Este hook fire-and-forget es útil para tareas de registro, analítica o limpieza. La respuesta se registra, pero no se utiliza.
// Entrada{ "session_id": "<identificador de sesión único>", "reason": "completed" | "aborted" | "error" | "window_close" | "user_close", "duration_ms": 45000, "is_background_agent": true | false, "final_status": "<cadena de estado>", "error_message": "<detalles del error si reason es 'error'>"}// Salida{ // Sin campos de salida: se envía y se olvida}| Campo de entrada | Tipo | Descripción |
|---|---|---|
session_id | string | Identificador único de la sesión que está finalizando |
reason | string | Cómo finalizó la sesión: "completed", "aborted", "error", "window_close" o "user_close" |
duration_ms | number | Duración total de la sesión en milisegundos |
is_background_agent | boolean | Indica si se trató de una sesión de un agente en segundo plano |
final_status | string | Estado final de la sesión |
error_message | string (optional) | Mensaje de error si el motivo es "error" |
preCompact
Se llama antes de que se produzca la compactación o resumido de la ventana de contexto. Es un hook de observación que no puede bloquear ni modificar el comportamiento de la compactación. Resulta útil para registrar cuándo se produce la compactación o notificar a los usuarios.
// Entrada{ "trigger": "auto" | "manual", "context_usage_percent": 85, "context_tokens": 120000, "context_window_size": 128000, "message_count": 45, "messages_to_compact": 30, "is_first_compaction": true | false}// Salida{ "user_message": "<message to show when compaction occurs>"}| Campo de entrada | Tipo | Descripción |
|---|---|---|
trigger | string | Qué desencadenó la compactación: "auto" o "manual" |
context_usage_percent | number | Uso actual de la ventana de contexto como porcentaje (0-100) |
context_tokens | number | Número actual de tokens de la ventana de contexto |
context_window_size | number | Tamaño máximo de la ventana de contexto en tokens |
message_count | number | Número de mensajes de la conversación |
messages_to_compact | number | Número de mensajes que se resumirán |
is_first_compaction | boolean | Indica si esta es la primera compactación de la conversación |
| Campo de salida | Tipo | Descripción |
|---|---|---|
user_message | string (optional) | Mensaje que se mostrará al usuario cuando se produzca la compactación |
workspaceOpen
Se activa una vez cuando Cursor abre un espacio de trabajo y de nuevo cada vez que cambia una carpeta del espacio de trabajo. Se omite cuando la ventana no tiene ninguna carpeta de espacio de trabajo. Se ejecuta en la aplicación de escritorio de Cursor y en la CLI.
// Entrada{ "hook_event_name": "workspaceOpen", "cursor_version": "string", "workspace_roots": ["<absolute path>"], "user_email": "string | null"}// Salida{ "pluginPaths": ["<absolute path>", "..."]}| Campo de salida | Tipo | Descripción |
|---|---|---|
pluginPaths | string[] (opcional) | Rutas absolutas a los directorios de plugins que se cargarán para el espacio de trabajo actual. |
Variables de entorno
Los scripts de hook reciben variables de entorno al ejecutarse:
| Variable | Descripción | Siempre presente |
|---|---|---|
CURSOR_PROJECT_DIR | Directorio raíz del espacio de trabajo | Sí |
CURSOR_VERSION | Cadena de versión de Cursor | Sí |
CURSOR_USER_EMAIL | Correo electrónico del usuario autenticado | Si ha iniciado sesión |
CURSOR_TRANSCRIPT_PATH | Ruta del archivo de transcripción de la conversación | Si las transcripciones están activadas |
CURSOR_CODE_REMOTE | Se establece en la cadena "true" al ejecutarse en un espacio de trabajo remoto | Para espacios de trabajo remotos |
CLAUDE_PROJECT_DIR | Alias del directorio del proyecto (compatibilidad con Claude) | Sí |
Las variables de entorno con alcance de sesión de los hooks sessionStart se փոխանցen a todas las ejecuciones posteriores de hooks dentro de esa sesión.
Solución de problemas
Cómo confirmar que los hooks están activos
Hay una pestaña Hooks en Personalizar y un canal de salida de Hooks para depurar los hooks configurados y ejecutados, y consultar errores.
Si los hooks no funcionan
- Cursor supervisa los archivos
hooks.jsony los recarga al guardarlos. Si los hooks siguen sin cargarse, reinicia Cursor. - Comprueba que las rutas relativas sean correctas para el código fuente de tu hook:
- Para los hooks de proyecto, las rutas son relativas a la raíz del proyecto (p. ej.,
.cursor/hooks/script.sh) - Para los hooks de usuario, las rutas son relativas a
~/.cursor/(p. ej.,./hooks/script.shohooks/script.sh)
- Para los hooks de proyecto, las rutas son relativas a la raíz del proyecto (p. ej.,
Bloqueo por código de salida
El código de salida 2 de los hooks de comando bloquea la acción (equivale a devolver permission: "deny"). Esto coincide con el comportamiento de Claude Code para garantizar la compatibilidad.
Hooks de Enterprise y distribución
La distribución en la nube y la gestión de hooks para todo el equipo están disponibles en Enterprise.