> ## Documentation Index
> Fetch the complete documentation index at: https://docs.windsurf.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Hooks de Cascade

> Ejecuta comandos de shell personalizados en puntos clave del flujo de trabajo de Cascade para registro, controles de seguridad, validación y gobernanza Enterprise mediante hooks de pre y pos-ejecución.

Los Hooks de Cascade te permiten ejecutar comandos de shell personalizados en puntos clave del flujo de trabajo de Cascade. Esta potente capacidad de extensibilidad te permite registrar operaciones, aplicar controles, ejecutar validaciones o integrarte con sistemas externos.

<Note>
  Los Hooks están diseñados para usuarios avanzados y equipos Enterprise que necesitan un control de grano fino sobre el comportamiento de Cascade. Requieren conocimientos básicos de scripting en shell.
</Note>

<div id="what-you-can-build">
  ## Qué puedes construir
</div>

Los hooks habilitan una amplia gama de capacidades de automatización y gobernanza:

* **Registro y Analytics**: Haz seguimiento de cada archivo leído, cambio de código, comando ejecutado, prompt de usuario o respuesta de Cascade para fines de cumplimiento y análisis de uso
* **Controles de seguridad**: Evita que Cascade acceda a archivos sensibles, ejecute comandos peligrosos o procese prompts que violen las políticas
* **Aseguramiento de la calidad**: Ejecuta linters, formatters o pruebas automáticamente después de modificaciones de código
* **Flujos de trabajo personalizados**: Integra con rastreadores de incidencias, sistemas de notificaciones o pipelines de despliegue
* **Estandarización del equipo**: Aplica estándares de codificación y mejores prácticas en toda tu organización

<div id="how-hooks-work">
  ## Cómo funcionan los hooks
</div>

Los hooks son comandos de shell que se ejecutan automáticamente cuando se producen acciones específicas de Cascade. Cada hook:

1. **Recibe contexto** (detalles sobre la acción que se está realizando) en formato JSON por la entrada estándar
2. **Ejecuta tu script**: Python, Bash, Node.js o cualquier ejecutable
3. **Devuelve un resultado** mediante el código de salida y los flujos de salida

En el caso de los **pre-hooks** (ejecutados antes de una acción), tu script puede **bloquear la acción** saliendo con el código de salida `2`. Esto hace que los pre-hooks sean ideales para implementar políticas de seguridad o comprobaciones de validación.

<div id="configuration">
  ## Configuración
</div>

Los hooks se configuran en archivos JSON que pueden ubicarse en tres niveles diferentes. Cascade carga y fusiona los hooks de todas las ubicaciones, lo que ofrece a los equipos flexibilidad para distribuir y administrar las configuraciones de hooks.

<div id="system-level">
  #### A nivel de sistema
</div>

Los hooks a nivel de sistema son ideales para definir políticas de toda la organización en máquinas de desarrollo compartidas. Por ejemplo, puedes usarlos para aplicar políticas de seguridad, requisitos de cumplimiento o flujos de trabajo obligatorios de revisión de código. Los equipos Enterprise también pueden configurar hooks desde el [panel de control en la nube](#cloud-dashboard-configuration) sin tener que gestionar archivos locales.

* **macOS**: `/Library/Application Support/Windsurf/hooks.json`
* **Linux/WSL**: `/etc/windsurf/hooks.json`
* **Windows**: `C:\ProgramData\Windsurf\hooks.json`

<div id="user-level">
  #### A nivel de usuario
</div>

Los hooks a nivel de usuario son ideales para preferencias personales y flujos de trabajo opcionales.

* **Windsurf IDE**: `~/.codeium/windsurf/hooks.json`
* **Plugin de JetBrains**: `~/.codeium/hooks.json`

<div id="workspace-level">
  #### A nivel de workspace
</div>

Los hooks a nivel de workspace permiten a los equipos llevar el control de versiones de políticas específicas del proyecto junto con su código. Pueden incluir reglas de validación personalizadas, integraciones específicas del proyecto o flujos de trabajo específicos del equipo.

* **Ubicación**: `.windsurf/hooks.json` en la raíz de tu workspace

<Note>
  Los hooks de las tres ubicaciones se **combinan**. Si el mismo evento de hook está configurado en varias ubicaciones, todos los hooks se ejecutarán en este orden: sistema → usuario → workspace.
</Note>

<div id="basic-structure">
  ### Estructura básica
</div>

Este es un ejemplo de la estructura básica de la configuración de hooks:

```json theme={null}
{
  "hooks": {
    "pre_read_code": [
      {
        "command": "python3 /path/to/your/script.py",
        "show_output": true
      }
    ],
    "post_write_code": [
      {
        "command": "python3 /path/to/another/script.py",
        "show_output": true
      }
    ]
  }
}
```

<div id="configuration-options">
  ### Opciones de configuración
</div>

Cada hook acepta los siguientes parámetros:

| Parámetro           | Tipo    | Descripción                                                                                                                  |
| ------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `command`           | string  | El comando de shell que se ejecutará. Puede ser cualquier ejecutable válido con argumentos.                                  |
| `show_output`       | boolean | Si se debe mostrar la salida stdout/stderr del hook en la interfaz de Cascade visible para el usuario. Útil para depuración. |
| `working_directory` | string  | Opcional. El directorio desde el cual ejecutar el comando. De forma predeterminada, es la raíz de tu workspace.              |

<Note>
  **Acerca del parámetro `working_directory`:**

  * En workspaces con múltiples repositorios, el valor predeterminado es la raíz del repositorio en el que se está trabajando actualmente
  * Las rutas relativas se resuelven desde la ubicación predeterminada (raíz del workspace o del repositorio)
  * Se admiten rutas absolutas
  * No se admite el uso de `~` para la expansión del directorio personal
</Note>

<div id="hook-events">
  ## Eventos de hooks
</div>

Cascade ofrece doce eventos de hooks que cubren las acciones más críticas en el flujo de trabajo del agente.

<div id="common-input-structure">
  ### Estructura común de entrada
</div>

Todos los hooks reciben un objeto JSON con los siguientes campos comunes:

| Campo               | Tipo   | Descripción                                                                 |
| ------------------- | ------ | --------------------------------------------------------------------------- |
| `agent_action_name` | string | Nombre del evento del hook (p. ej., "pre\_read\_code", "post\_write\_code") |
| `trajectory_id`     | string | Identificador único de la conversación global de Cascade                    |
| `execution_id`      | string | Identificador único del turno del agente                                    |
| `timestamp`         | string | Marca de tiempo en formato ISO 8601 cuando se activó el hook                |
| `tool_info`         | object | Información específica del evento (varía según el tipo de hook)             |

En los siguientes ejemplos, se omiten los campos comunes por brevedad. Hay doce tipos principales de eventos de hook:

<div id="pre_read_code">
  ### pre\_read\_code
</div>

Se activa **antes** de que Cascade lea un archivo de código. Puede bloquear la acción si el hook finaliza con el código 2.

**Casos de uso**: Restringir el acceso a archivos, registrar operaciones de lectura, verificar permisos

**JSON de entrada**:

```json theme={null}
{
  "agent_action_name": "pre_read_code",
  "tool_info": {
    "file_path": "/Users/yourname/project/file.py"
  }
}
```

Este `file_path` puede ser una ruta de directorio cuando Cascade lee un directorio de forma recursiva.

<div id="post_read_code">
  ### post\_read\_code
</div>

Se activa **después** de que Cascade lea correctamente un archivo de código.

**Casos de uso**: Registrar lecturas correctas, rastrear patrones de acceso a archivos

**JSON de entrada**:

```json theme={null}
{
  "agent_action_name": "post_read_code",
  "tool_info": {
    "file_path": "/Users/yourname/project/file.py"
  }
}
```

Este `file_path` puede ser una ruta de directorio cuando Cascade lee un directorio de manera recursiva.

<div id="pre_write_code">
  ### pre\_write\_code
</div>

Se activa **antes** de que Cascade escriba o modifique un archivo de código. Esto puede bloquear la acción si el hook termina con el código 2.

**Casos de uso**: Evitar modificaciones en archivos protegidos, hacer copias de seguridad de archivos antes de aplicar cambios

**Entrada JSON**:

```json theme={null}
{
  "agent_action_name": "pre_write_code",
  "tool_info": {
    "file_path": "/Users/yourname/project/file.py",
    "edits": [
      {
        "old_string": "def old_function():\n    pass",
        "new_string": "def new_function():\n    return True"
      }
    ]
  }
}
```

<div id="post_write_code">
  ### post\_write\_code
</div>

Se activa **después** de que Cascade escribe o modifica un archivo de código.

**Casos de uso**: Ejecutar linters, formateadores o pruebas; registrar cambios de código

**JSON de entrada**:

```json theme={null}
{
  "agent_action_name": "post_write_code",
  "tool_info": {
    "file_path": "/Users/yourname/project/file.py",
    "edits": [
      {
        "old_string": "import os",
        "new_string": "import os\nimport sys"
      }
    ]
  }
}
```

<div id="pre_run_command">
  ### pre\_run\_command
</div>

Se activa **antes** de que Cascade ejecute un comando en la terminal. Esto puede bloquear la acción si el hook termina con el código 2.

**Casos de uso**: Bloquear comandos peligrosos, registrar todas las ejecuciones de comandos, añadir comprobaciones de seguridad

**JSON de entrada**:

```json theme={null}
{
  "agent_action_name": "pre_run_command",
  "tool_info": {
    "command_line": "npm install package-name",
    "cwd": "/Users/yourname/project"
  }
}
```

<div id="post_run_command">
  ### post\_run\_command
</div>

Se activa **después** de que Cascade ejecuta un comando en la terminal.

**Casos de uso**: Registrar los resultados del comando, activar acciones posteriores

**JSON de entrada**:

```json theme={null}
{
  "agent_action_name": "post_run_command",
  "tool_info": {
    "command_line": "npm install package-name",
    "cwd": "/Users/yourname/project"
  }
}
```

<div id="pre_mcp_tool_use">
  ### pre\_mcp\_tool\_use
</div>

Se activa **antes** de que Cascade invoque una herramienta MCP (Model Context Protocol). Puede bloquear la acción si el hook finaliza con el código 2.

**Casos de uso**: Registrar el uso de MCP, restringir qué herramientas MCP pueden utilizarse

**JSON de entrada**:

```json theme={null}
{
  "agent_action_name": "pre_mcp_tool_use",
  "tool_info": {
    "mcp_server_name": "github",
    "mcp_tool_arguments": {
      "owner": "code-owner",
      "repo": "my-cool-repo",
      "title": "Informe de error",
      "body": "Descripción del error aquí"
    },
    "mcp_tool_name": "create_issue"
  }
}
```

<div id="post_mcp_tool_use">
  ### post\_mcp\_tool\_use
</div>

Se activa **después** de que Cascade invoque con éxito una herramienta MCP.

**Casos de uso**: Registrar operaciones de MCP, rastrear el uso de la API, ver resultados de MCP

**JSON de entrada**:

```json theme={null}
{
  "agent_action_name": "post_mcp_tool_use",
  "tool_info": {
    "mcp_result": "...",
    "mcp_server_name": "github",
    "mcp_tool_arguments": {
      "owner": "code-owner",
      "perPage": 1,
      "repo": "my-cool-repo",
      "sha": "main"
    },
    "mcp_tool_name": "list_commits"
  }
}
```

<div id="pre_user_prompt">
  ### pre\_user\_prompt
</div>

Se activa **antes** de que Cascade procese el texto del prompt de un usuario. Esto puede bloquear la acción si el hook finaliza con el código 2.

**Casos de uso**: Registrar todos los prompts de los usuarios para auditoría, bloquear prompts potencialmente dañinos o que infrinjan la política

**JSON de entrada**:

```json theme={null}
{
  "agent_action_name": "pre_user_prompt",
  "tool_info": {
    "user_prompt": "can you run the echo hello command"
  }
}
```

La opción de configuración `show_output` no se aplica a este hook.

<div id="post_cascade_response">
  ### post\_cascade\_response
</div>

Se activa de forma asíncrona **después** de que Cascade completa una respuesta al mensaje de un usuario. Este hook recibe la respuesta completa de Cascade desde la última entrada del usuario.

**Casos de uso**: Registrar todas las respuestas de Cascade para fines de auditoría, analizar patrones de respuesta, enviar respuestas a sistemas externos para revisión de cumplimiento normativo

**JSON de entrada**:

```json theme={null}
{
  "agent_action_name": "post_cascade_response",
  "tool_info": {
    "response": "### Respuesta del Planificador\n\nTe ayudaré a crear ese archivo.\n\n*Archivo creado `/path/to/file.py`*\n\n### Respuesta del Planificador\n\nEl archivo se ha creado exitosamente."
  }
}
```

El campo `response` contiene el contenido en formato Markdown de la respuesta de Cascade desde la última entrada del usuario. Esto incluye respuestas del planificador, acciones de herramientas (lecturas y escrituras de archivos, comandos) y cualquier otro paso que haya realizado Cascade. También incluye información sobre qué [reglas](/es/windsurf/cascade/memories-and-rules) se activaron. Consulta el ejemplo [Seguimiento de reglas activadas](#tracking-triggered-rules) para ver cómo analizar el uso de reglas.

La opción de configuración `show_output` no se aplica a este hook.

<Warning>
  El contenido de `response` se deriva de datos de trayectoria y puede contener información confidencial de tu base de código o de tus conversaciones. Maneja estos datos de acuerdo con las políticas de seguridad y privacidad de tu organización.
</Warning>

<div id="post_cascade_response_with_transcript">
  ### post\_cascade\_response\_with\_transcript
</div>

Se activa de forma asíncrona **después** de que Cascade completa una respuesta al prompt de un usuario, similar a `post_cascade_response`. En lugar de proporcionar un resumen en markdown integrado, este hook escribe la transcripción completa de la conversación (desde el inicio de la conversación) en un archivo JSONL local y proporciona la ruta del archivo.

**Casos de uso**: registro de auditoría y cumplimiento de Enterprise, seguimiento de contribuciones generadas por IA, envío de transcripciones a herramientas externas de observabilidad o de Analytics

**JSON de entrada**:

```json theme={null}
{
  "agent_action_name": "post_cascade_response_with_transcript",
  "tool_info": {
    "transcript_path": "/Users/yourname/.windsurf/transcripts/{trajectory_id}.jsonl"
  }
}
```

El `transcript_path` apunta a un archivo [JSONL](https://jsonlines.org/) en `~/.windsurf/transcripts/{trajectory_id}.jsonl`. Cada línea contiene un objeto JSON que representa un único paso en la conversación, con un campo `type` y otro `status`, además de datos específicos de ese paso. Por ejemplo:

```jsonl theme={null}
{"status":"done","type":"user_input","user_input":{"rules_applied":{"always_on":["my-rule.md"]},"user_response":"create a hello world file"}}
{"planner_response":{"response":"I'll create a hello world file for you."},"status":"done","type":"planner_response"}
{"code_action":{"new_content":"print('hello world')\n","path":"/path/to/file.py"},"status":"done","type":"code_action"}
{"planner_response":{"response":"I created the file for you."},"status":"done","type":"planner_response"}
```

La transcripción incluye datos detallados propiedad del cliente, como contenidos de archivos, salidas de comandos, argumentos de herramientas, resultados de búsqueda y [reglas](/es/windsurf/cascade/memories-and-rules) que se aplicaron. Ten en cuenta que la estructura exacta de cada paso puede cambiar en versiones futuras, por lo que debes implementar cualquier consumidor de hooks de forma resiliente.

Los archivos de transcripción se escriben con permisos `0600`. Windsurf limita automáticamente el directorio de transcripciones a 100 archivos, eliminando los más antiguos según la hora de modificación.

La opción de configuración `show_output` no se aplica a este hook.

Esta tabla muestra las diferencias clave entre los hooks `post_cascade_response` y `post_cascade_response_with_transcript`:

|                  | `post_cascade_response`                            | `post_cascade_response_with_transcript`                                                     |
| ---------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| **Data scope**   | Solo los pasos desde la última entrada del usuario | La conversación completa desde el principio                                                 |
| **Format**       | Resumen en Markdown en `tool_info.response`        | Archivo JSONL estructurado en `tool_info.transcript_path`                                   |
| **Detail level** | Resumen condensado y legible para humanos          | Datos detallados y legibles por máquina (contenidos de archivos, salidas de comandos, etc.) |
| **Delivery**     | En línea a través de JSON por stdin                | Archivo en disco (`~/.windsurf/transcripts/`)                                               |

<Warning>
  Los archivos de transcripción contendrán información sensible de tu base de código, incluidos contenidos de archivos, salidas de comandos e historial de conversación. Maneja estos archivos de acuerdo con las políticas de seguridad y privacidad de tu organización.
</Warning>

<div id="post_setup_worktree">
  ### post\_setup\_worktree
</div>

Se activa **después** de que se crea y configura un nuevo [git worktree](./worktrees). El hook se ejecuta dentro del nuevo directorio del **worktree**.

**Casos de uso**: Copiar archivos `.env` u otros archivos sin seguimiento al worktree, instalar dependencias, ejecutar scripts de configuración

**Variables de entorno**:

| Variable               | Descripción                                                                                                                  |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `$ROOT_WORKSPACE_PATH` | La ruta absoluta al workspace original. Úsala para acceder a archivos o ejecutar comandos relativos al repositorio original. |

**JSON de entrada**:

```json theme={null}
{
  "agent_action_name": "post_setup_worktree",
  "tool_info": {
    "worktree_path": "/Users/me/.windsurf/worktrees/my-repo/abmy-repo-c123",
    "root_workspace_path": "/Users/me/projects/my-repo"
  }
}
```

<div id="exit-codes">
  ## Códigos de salida
</div>

Tus scripts de hooks comunican resultados mediante códigos de salida:

| Código de salida | Significado      | Efecto                                                                                                    |
| ---------------- | ---------------- | --------------------------------------------------------------------------------------------------------- |
| `0`              | Éxito            | La acción continúa con normalidad                                                                         |
| `2`              | Error bloqueante | El agente de Cascade verá el mensaje de error desde stderr. En los pre-hooks, esto **bloquea** la acción. |
| Cualquier otro   | Error            | La acción continúa con normalidad                                                                         |

<Warning>
  Solo los **pre-hooks** (pre\_user\_prompt, pre\_read\_code, pre\_write\_code, pre\_run\_command, pre\_mcp\_tool\_use) pueden bloquear acciones usando el código de salida 2. Los post-hooks no pueden bloquear, ya que la acción ya se realizó.
</Warning>

Ten en cuenta que el usuario puede ver cualquier salida estándar y error estándar generados por los hooks en la interfaz de Cascade si `show_output` es true.

<div id="example-use-cases">
  ## Ejemplos de casos de uso
</div>

<div id="logging-all-cascade-actions">
  ### Registro de todas las acciones de Cascade
</div>

Realiza un seguimiento de cada acción que Cascade lleva a cabo con fines de auditoría.

**Configuración**:

```json theme={null}
{
  "hooks": {
    "post_read_code": [
      {
        "command": "python3 /Users/yourname/hooks/log_input.py",
        "show_output": true
      }
    ],
    "post_write_code": [
      {
        "command": "python3 /Users/yourname/hooks/log_input.py",
        "show_output": true
      }
    ],
    "post_run_command": [
      {
        "command": "python3 /Users/yourname/hooks/log_input.py",
        "show_output": true
      }
    ],
    "post_mcp_tool_use": [
      {
        "command": "python3 /Users/yourname/hooks/log_input.py",
        "show_output": true
      }
    ],
    "post_cascade_response": [
      {
        "command": "python3 /Users/yourname/hooks/log_input.py"
      }
    ]
  }
}
```

**Script** (`log_input.py`):

```python theme={null}
#!/usr/bin/env python3

import sys
import json

def main():
    # Read the JSON data from stdin
    input_data = sys.stdin.read()
    
    # Parse the JSON
    try:
        data = json.loads(input_data)
        
        # Write formatted JSON to file
        with open("/Users/yourname/hooks/input.txt", "a") as f:
            f.write('\n' + '='*80 + '\n')
            f.write(json.dumps(data, indent=2, separators=(',', ': ')))
            f.write('\n')
    
        print(json.dumps(data, indent=2))
    except json.JSONDecodeError as e:
        print(f"Error al analizar JSON: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
```

Este script anexa cada invocación del hook a un archivo de registro, creando un rastro de auditoría de todas las acciones de Cascade. Puedes transformar los datos de entrada o implementar lógica personalizada según lo consideres adecuado.

<div id="restricting-file-access">
  ### Restringir el acceso a archivos
</div>

Evita que Cascade lea archivos fuera de un directorio específico.

**Configuración**:

```json theme={null}
{
  "hooks": {
    "pre_read_code": [
      {
        "command": "python3 /Users/yourname/hooks/block_read_access.py",
        "show_output": true
      }
    ]
  }
}
```

**Script** (`block_read_access.py`):

```python theme={null}
#!/usr/bin/env python3

import sys
import json

ALLOWED_PREFIX = "/Users/yourname/my-project/"

def main():
    # Leer los datos JSON desde stdin
    input_data = sys.stdin.read()

    # Analizar el JSON
    try:
        data = json.loads(input_data)

        if data.get("agent_action_name") == "pre_read_code":
            tool_info = data.get("tool_info", {})
            file_path = tool_info.get("file_path", "")
            
            if not file_path.startswith(ALLOWED_PREFIX):
                print(f"Acceso denegado: Cascade solo tiene permitido leer archivos en {ALLOWED_PREFIX}", file=sys.stderr)
                sys.exit(2)  # El código de salida 2 bloquea la acción
            
            print(f"Acceso concedido: {file_path}", file=sys.stdout)

    except json.JSONDecodeError as e:
        print(f"Error al analizar JSON: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
```

Cuando Cascade intenta leer un archivo fuera del directorio permitido, este gancho bloquea la operación y muestra un mensaje de error.

<div id="blocking-dangerous-commands">
  ### Bloquear comandos peligrosos
</div>

Evita que Cascade ejecute comandos potencialmente peligrosos.

**Configuración**:

```json theme={null}
{
  "hooks": {
    "pre_run_command": [
      {
        "command": "python3 /Users/yourname/hooks/block_dangerous_commands.py",
        "show_output": true
      }
    ]
  }
}
```

**Script** (`block_dangerous_commands.py`):

```python theme={null}
#!/usr/bin/env python3

import sys
import json

DANGEROUS_COMMANDS = ["rm -rf", "sudo rm", "format", "del /f"]

def main():
    # Read the JSON data from stdin
    input_data = sys.stdin.read()

    # Parse the JSON
    try:
        data = json.loads(input_data)

        if data.get("agent_action_name") == "pre_run_command":
            tool_info = data.get("tool_info", {})
            command = tool_info.get("command_line", "")

            for dangerous_cmd in DANGEROUS_COMMANDS:
                if dangerous_cmd in command:
                    print(f"Comando bloqueado: '{dangerous_cmd}' no está permitido por razones de seguridad.", file=sys.stderr)
                    sys.exit(2)  # Exit code 2 blocks the command
            
            print(f"Command approved: {command}", file=sys.stdout)

    except json.JSONDecodeError as e:
        print(f"Error parsing JSON: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
```

Este hook escanea los comandos en busca de patrones peligrosos y los bloquea antes de su ejecución.

<div id="blocking-policy-violating-prompts">
  ### Bloquear prompts que infringen las políticas
</div>

Impide que los usuarios envíen prompts que violen las políticas de la organización.

**Config**:

```json theme={null}
{
  "hooks": {
    "pre_user_prompt": [
      {
        "command": "python3 /Users/yourname/hooks/block_bad_prompts.py"
      }
    ]
  }
}
```

**Script** (`block_bad_prompts.py`):

```python theme={null}
#!/usr/bin/env python3

import sys
import json

BLOCKED_PATTERNS = [
    "something dangerous",
    "bypass security",
    "ignore previous instructions"
]

def main():
    # Leer los datos JSON desde stdin
    input_data = sys.stdin.read()

    # Parsear el JSON
    try:
        data = json.loads(input_data)

        if data.get("agent_action_name") == "pre_user_prompt":
            tool_info = data.get("tool_info", {})
            user_prompt = tool_info.get("user_prompt", "").lower()

            for pattern in BLOCKED_PATTERNS:
                if pattern in user_prompt:
                    print(f"Prompt blocked: Contains prohibited content. The user cannot ask the agent to do bad things.", file=sys.stderr)
                    sys.exit(2)  # El código de salida 2 bloquea el prompt

    except json.JSONDecodeError as e:
        print(f"Error parsing JSON: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
```

Este hook examina los prompts del usuario antes de que se procesen y bloquea cualquiera que contenga patrones prohibidos. Cuando se bloquea un prompt, el usuario ve un mensaje de error en la interfaz de usuario de Cascade.

<div id="logging-cascade-responses">
  ### Registro de respuestas de Cascade
</div>

Registra todas las respuestas de Cascade para auditoría de cumplimiento o Analytics.

**Configuración**:

```json theme={null}
{
  "hooks": {
    "post_cascade_response": [
      {
        "command": "python3 /Users/yourname/hooks/log_cascade_response.py"
      }
    ]
  }
}
```

**Script** (`log_cascade_response.py`):

```python theme={null}
#!/usr/bin/env python3

import sys
import json
from datetime import datetime

def main():
    # Leer los datos JSON desde stdin
    input_data = sys.stdin.read()

    # Parsear el JSON
    try:
        data = json.loads(input_data)

        if data.get("agent_action_name") == "post_cascade_response":
            tool_info = data.get("tool_info", {})
            cascade_response = tool_info.get("response", "")
            trajectory_id = data.get("trajectory_id", "unknown")
            timestamp = data.get("timestamp", datetime.now().isoformat())

            # Registrar en archivo
            with open("/Users/yourname/hooks/cascade_responses.log", "a") as f:
                f.write(f"\n{'='*80}\n")
                f.write(f"Timestamp: {timestamp}\n")
                f.write(f"Trajectory ID: {trajectory_id}\n")
                f.write(f"Response:\n{cascade_response}\n")

            print(f"Logged Cascade response for trajectory {trajectory_id}")

    except json.JSONDecodeError as e:
        print(f"Error parsing JSON: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
```

Este hook registra cada respuesta de Cascade en un archivo, creando una pista de auditoría de todo el contenido generado por la IA. Puedes extenderlo para enviar datos a sistemas externos de logs, bases de datos o plataformas de cumplimiento normativo.

<div id="tracking-triggered-rules">
  ### Seguimiento de reglas activadas
</div>

Realiza un seguimiento de qué [reglas](/es/windsurf/cascade/memories-and-rules) se aplicaron durante las interacciones con Cascade para fines de observabilidad y métricas.

**Configuración**:

```json theme={null}
{
  "hooks": {
    "post_cascade_response": [
      {
        "command": "python3 /Users/yourname/hooks/track_rules.py"
      }
    ]
  }
}
```

**Script** (`track_rules.py`):

```python theme={null}
#!/usr/bin/env python3

import sys
import json
import re
from datetime import datetime

def extract_triggered_rules(response: str) -> dict:
    """
    Analiza las reglas activadas de la respuesta de Cascade.
    Las reglas aparecen como: - (Rule-Type) Triggered Rule: rule-filename.md
    """
    pattern = r"- \(([^)]+)\) Triggered Rule: (.+?)(?:\s*$)"
    rules = {}

    for match in re.finditer(pattern, response, re.MULTILINE):
        rule_type, rule_name = match.groups()
        if rule_type not in rules:
            rules[rule_type] = []
        rules[rule_type].append(rule_name)

    return rules

def main():
    input_data = sys.stdin.read()

    try:
        data = json.loads(input_data)

        if data.get("agent_action_name") == "post_cascade_response":
            response = data.get("tool_info", {}).get("response", "")
            trajectory_id = data.get("trajectory_id", "unknown")
            timestamp = data.get("timestamp", datetime.now().isoformat())

            rules = extract_triggered_rules(response)
            total_rules = sum(len(v) for v in rules.values())

            # Log to file
            with open("/Users/yourname/hooks/rules_usage.log", "a") as f:
                f.write(f"\n{'='*60}\n")
                f.write(f"Timestamp: {timestamp}\n")
                f.write(f"Trajectory: {trajectory_id}\n")
                f.write(f"Total rules triggered: {total_rules}\n")
                for rule_type, rule_list in rules.items():
                    if rule_list:
                        f.write(f"  {rule_type}: {', '.join(rule_list)}\n")

            print(f"Tracked {total_rules} triggered rules")

    except json.JSONDecodeError as e:
        print(f"Error parsing JSON: {e}", file=sys.stderr)
        sys.exit(1)

if __name__ == "__main__":
    main()
```

**Tipos de reglas:**

* `Always On` - Reglas que siempre se incluyen
* `Model Decision` - Reglas cuyas descripciones se mostraron al modelo de IA para su aplicación condicional
* `Manual` - Reglas mencionadas explícitamente con @ en la entrada del usuario
* `Global` - Reglas globales de `global_rules.md`
* `Glob` - Reglas activadas por acceso a archivos que coinciden con patrones de tipo glob

<Note>
  Esto registra qué reglas fueron *presentadas* al modelo de IA o *activadas* por el acceso a archivos, pero no indica si el modelo de IA realmente *siguió* una regla. Las reglas que ya se han mostrado recientemente en la conversación se deduplican y puede que no vuelvan a aparecer hasta más adelante.
</Note>

<div id="running-code-formatters-after-edits">
  ### Ejecutar formateadores de código después de las ediciones
</div>

Formatea automáticamente los archivos de código después de que Cascade los modifique.

**Configuración**:

```json theme={null}
{
  "hooks": {
    "post_write_code": [
      {
        "command": "bash /Users/yourname/hooks/format_code.sh",
        "show_output": false
      }
    ]
  }
}
```

**Script** (`format_code.sh`):

```bash theme={null}
#!/bin/bash

# Leer JSON desde stdin
input=$(cat)

# Extraer ruta de archivo usando jq
file_path=$(echo "$input" | jq -r '.tool_info.file_path')

# Formatear según extensión de archivo
if [[ "$file_path" == *.py ]]; then
    black "$file_path" 2>&1
    echo "Archivo Python formateado: $file_path"
elif [[ "$file_path" == *.js ]] || [[ "$file_path" == *.ts ]]; then
    prettier --write "$file_path" 2>&1
    echo "Archivo JS/TS formateado: $file_path"
elif [[ "$file_path" == *.go ]]; then
    gofmt -w "$file_path" 2>&1
    echo "Archivo Go formateado: $file_path"
fi

exit 0
```

Este hook ejecuta automáticamente el formateador correspondiente según el tipo de archivo tras cada edición.

<div id="setting-up-worktrees">
  ### Configurar worktrees
</div>

Copiar archivos de entorno e instalar dependencias al crear un nuevo worktree.

**Config** (en `.windsurf/hooks.json`):

```json theme={null}
{
  "hooks": {
    "post_setup_worktree": [
      {
        "command": "bash $ROOT_WORKSPACE_PATH/hooks/setup_worktree.sh",
        "show_output": true
      }
    ]
  }
}
```

**Script** (`hooks/setup_worktree.sh`):

```bash theme={null}
#!/bin/bash

# Copiar archivos de entorno desde el workspace original
if [ -f "$ROOT_WORKSPACE_PATH/.env" ]; then
    cp "$ROOT_WORKSPACE_PATH/.env" .env
    echo "Archivo .env copiado"
fi

if [ -f "$ROOT_WORKSPACE_PATH/.env.local" ]; then
    cp "$ROOT_WORKSPACE_PATH/.env.local" .env.local
    echo "Archivo .env.local copiado"
fi

# Instalar dependencias
if [ -f "package.json" ]; then
    npm install
    echo "Dependencias de npm instaladas"
fi

exit 0
```

Este hook garantiza que en cada worktree se instalen automáticamente la configuración de entorno y las dependencias necesarias.

<div id="best-practices">
  ## Prácticas recomendadas
</div>

<div id="security">
  ### Seguridad
</div>

<Warning>
  **Use Cascade Hooks at Your Own Risk**: Los hooks ejecutan comandos de shell automáticamente con todos los permisos de su cuenta de usuario. Usted es completamente responsable del código que configure. Los hooks mal diseñados o maliciosos pueden modificar archivos, eliminar datos, exponer credenciales o comprometer su sistema.
</Warning>

* **Valide todas las entradas**: Nunca confíe en el JSON de entrada sin validarlo, especialmente en lo referente a rutas de archivos y comandos.
* **Use rutas absolutas**: Utilice siempre rutas absolutas en la configuración de sus hooks para evitar ambigüedades.
* **Proteja los datos sensibles**: Evite registrar información sensible, como claves de API o credenciales.
* **Revise los permisos**: Asegúrese de que sus scripts de hooks tengan los permisos adecuados en el sistema de archivos.
* **Audite antes del despliegue**: Revise cada comando y script de hook antes de añadirlo a su configuración.
* **Pruebe en aislamiento**: Ejecute los hooks en un entorno de pruebas antes de habilitarlos en su máquina principal de desarrollo.

<div id="performance-considerations">
  ### Consideraciones de rendimiento
</div>

* **Mantén los hooks rápidos**: Los hooks lentos afectarán la capacidad de respuesta de Cascade. Procura tiempos de ejecución inferiores a 100 ms.
* **Usa operaciones asíncronas**: Para hooks no bloqueantes, considera enviar registros a una cola o base de datos de manera asíncrona.
* **Filtra cuanto antes**: Verifica el tipo de acción al inicio de tu script para evitar procesamiento innecesario.

<div id="error-handling">
  ### Manejo de errores
</div>

* **Valida siempre el JSON**: Usa bloques try-catch para manejar entradas malformadas de forma adecuada.
* **Registra los errores correctamente**: Escribe los errores en `stderr` para que sean visibles cuando `show_output` esté habilitado.
* **Falla de forma segura**: Si tu hook encuentra un error, considera si debe bloquear la acción o permitir que continúe.

<div id="testing-your-hooks">
  ### Pruebas de tus hooks
</div>

1. **Empieza con registros**: Implementa primero un hook simple de logging para comprender el flujo de datos.
2. **Usa `show_output: true`**: Habilita la salida durante el desarrollo para ver qué hacen tus hooks.
3. **Prueba el comportamiento de bloqueo**: Verifica que el código de salida 2 bloquee correctamente las acciones en los pre-hooks.
4. **Verifica todas las rutas de código**: Prueba tanto los casos de éxito como los de error en tus scripts.

<div id="enterprise-distribution">
  ## Distribución para Enterprise
</div>

Las organizaciones Enterprise deben aplicar políticas de seguridad, requisitos de cumplimiento y estándares de desarrollo que los usuarios individuales no puedan eludir. Cascade Hooks admite dos métodos de distribución para Enterprise:

1. **Cloud Dashboard** - Configura los hooks mediante Team Settings en el panel de Windsurf
2. **System-Level Files** - Implementa los hooks mediante MDM o herramientas de gestión de configuración

Ambos métodos pueden utilizarse juntos: los hooks de todas las fuentes se combinan y se ejecutan en orden.

<div id="cloud-dashboard-configuration">
  ### Configuración desde el panel en la nube
</div>

Los administradores de equipo pueden configurar Cascade Hooks directamente desde el panel de Windsurf.

**Requisitos:**

* Plan Enterprise
* Permiso `TEAM_SETTINGS_UPDATE`

**Para configurar:**

1. Accede a **Team Settings** en el panel de Windsurf
2. Busca la sección **Cascade Hooks**
3. Introduce tu configuración de hooks en formato JSON
4. Guarda los cambios

Los hooks configurados a través del panel se distribuyen automáticamente a todos los miembros del equipo y se cargan al iniciar Windsurf. Los hooks configurados en la nube se cargan primero, seguidos por los hooks a nivel de sistema, de usuario y de workspace.

<Note>
  Cuando se combinan múltiples configuraciones de equipo, los hooks se agrupan por acción en lugar de sobrescribirse. Esto significa que los hooks de todas las configuraciones de equipo aplicables se ejecutarán conjuntamente.
</Note>

<div id="system-level-file-deployment">
  ### Implementación de archivos a nivel del sistema
</div>

Para las organizaciones que prefieren la configuración basada en archivos o necesitan que los hooks funcionen sin conexión, implemente su configuración obligatoria `hooks.json` en estas ubicaciones específicas del sistema operativo:

**macOS:**

```
/Library/Application Support/Windsurf/hooks.json
```

**Linux/WSL:**

```
/etc/windsurf/hooks.json
```

**Windows:**

```
C:\ProgramData\Windsurf\hooks.json
```

Coloca tus scripts de hooks en un directorio de sistema correspondiente (p. ej., `/usr/local/share/windsurf-hooks/` en sistemas Unix).

Los hooks a nivel del sistema tienen prioridad sobre los hooks del usuario y del workspace, y no pueden deshabilitarse por los usuarios finales sin permisos de root.

<div id="mdm-and-configuration-management">
  #### MDM y gestión de la configuración
</div>

Los equipos de TI de Enterprise pueden desplegar hooks a nivel del sistema utilizando herramientas estándar:

**Mobile Device Management (MDM)**

* **Jamf Pro** (macOS) - Despliegue mediante perfiles de configuración o scripts
* **Microsoft Intune** (Windows/macOS) - Use scripts de PowerShell o despliegue de políticas
* **Workspace ONE**, **Google Endpoint Management** y otras soluciones MDM

**Gestión de configuración**

* **Ansible**, **Puppet**, **Chef**, **SaltStack** - Use su automatización de infraestructura existente
* **Scripts de despliegue personalizados** - Scripts de shell, PowerShell o sus herramientas preferidas

<div id="verification-and-auditing">
  #### Verificación y auditoría
</div>

Después del despliegue, verifica que los hooks estén correctamente instalados:

```bash theme={null}
# Verificar que los hooks del sistema estén presentes
ls -la /etc/windsurf/hooks.json  # Linux
ls -la "/Library/Application Support/Windsurf/hooks.json"  # macOS

# Probar la ejecución del hook (debería ver la salida del hook en Cascade)
# Pida a un desarrollador que active la acción correspondiente de Cascade

# Verificar que los usuarios no puedan modificar los hooks del sistema
sudo chown root:root /etc/windsurf/hooks.json
sudo chmod 644 /etc/windsurf/hooks.json
```

<Note>
  **Importante**: Los hooks a nivel de sistema son gestionados íntegramente por tu equipo de TI o de seguridad. Windsurf no despliega ni administra archivos en rutas del sistema. Asegúrate de que tus equipos internos se encarguen del despliegue, las actualizaciones y el cumplimiento conforme a las políticas de tu organización.
</Note>

<div id="workspace-hooks-for-team-projects">
  ### Hooks de workspace para proyectos en equipo
</div>

Para convenciones específicas del proyecto, los equipos pueden usar hooks a nivel de workspace en el control de versiones:

```bash theme={null}
# Add to your repository
.windsurf/
├── hooks.json
└── scripts/
    └── format-check.py

# Commit to git
git add .windsurf/
git commit -m "Agregar hooks de workspace para formateo de código"
```

Esto permite estandarizar las prácticas de desarrollo en los equipos. Mantén las políticas críticas de seguridad en la nube o a nivel del sistema y evita subir o registrar información sensible en el control de versiones.

<div id="additional-resources">
  ## Recursos adicionales
</div>

* **Integración con MCP**: Obtén más información sobre el [Model Context Protocol en Windsurf](/es/windsurf/cascade/mcp)
* **Workflows**: Descubre cómo combinar hooks con [Cascade Workflows](/es/windsurf/cascade/workflows)
* **Analytics**: Realiza un seguimiento del uso de Cascade con [Team Analytics](/es/windsurf/accounts/analytics)
