> ## 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.

# Cascade Hooks

> Exécutez des commandes shell personnalisées à des moments clés du workflow de Cascade pour la journalisation, les contrôles de sécurité, la validation et la gouvernance Enterprise, avec des hooks pré- et post-exécution.

Les Cascade Hooks vous permettent d’exécuter des commandes shell personnalisées à des moments clés du workflow de Cascade. Cette puissante fonctionnalité d’extensibilité vous permet de consigner des opérations, d’appliquer des garde-fous, d’exécuter des contrôles de validation ou de vous intégrer à des systèmes externes.

<Note>
  Les Hooks sont conçus pour les utilisateurs avancés et les équipes Enterprise qui ont besoin d’un contrôle précis sur le comportement de Cascade. Ils nécessitent des connaissances de base en scripting shell.
</Note>

<div id="what-you-can-build">
  ## Ce que vous pouvez créer
</div>

Les hooks ouvrent un large éventail de fonctions d’automatisation et de gouvernance :

* **Journalisation et Analytics** : suivez chaque fichier lu, chaque modification de code, chaque commande exécutée, chaque invite utilisateur ou chaque réponse de Cascade pour la conformité et l’analyse de l’usage
* **Contrôles de sécurité** : empêchez Cascade d’accéder à des fichiers sensibles, d’exécuter des commandes dangereuses ou de traiter des invites qui enfreignent les politiques
* **Assurance qualité** : exécutez automatiquement des linters, des formateurs ou des tests après des modifications de code
* **Workflows personnalisés** : intégrez-vous aux outils de suivi d’incidents, aux systèmes de notification ou aux pipelines de déploiement
* **Standardisation d’équipe** : appliquez des normes de codage et des meilleures pratiques dans toute votre organisation

<div id="how-hooks-work">
  ## Fonctionnement des hooks
</div>

Les hooks sont des commandes de shell qui s’exécutent automatiquement lors d’actions Cascade spécifiques. Chaque hook :

1. **Reçoit un contexte** (des détails sur l’action en cours) au format JSON via l’entrée standard
2. **Exécute votre script** — Python, Bash, Node.js ou tout exécutable
3. **Renvoie un résultat** via le code de sortie et les flux de sortie

Pour les **pré-hooks** (exécutés avant une action), votre script peut **bloquer l’action** en se terminant avec le code de sortie `2`. Les pré-hooks sont donc idéaux pour appliquer des politiques de sécurité ou effectuer des validations.

<div id="configuration">
  ## Configuration
</div>

Les hooks sont configurés dans des fichiers JSON pouvant être placés à trois niveaux différents. Cascade charge et fusionne les hooks à partir de tous ces emplacements, offrant aux équipes la flexibilité nécessaire pour distribuer et gérer les configurations de hooks.

<div id="system-level">
  #### Niveau système
</div>

Les hooks au niveau système sont idéaux pour des politiques à l’échelle de l’organisation, appliquées sur des machines de développement partagées. Par exemple, vous pouvez les utiliser pour appliquer des politiques de sécurité, des exigences de conformité ou des workflows de revue de code obligatoires. Les équipes Enterprise peuvent également configurer des hooks via le [cloud dashboard](#cloud-dashboard-configuration) sans avoir à gérer de fichiers locaux.

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

<div id="user-level">
  #### Niveau utilisateur
</div>

Les hooks au niveau utilisateur sont parfaits pour des préférences personnelles et des workflows optionnels.

* **Emplacement** : `~/.codeium/windsurf/hooks.json`
* **Plugin JetBrains** : `~/.codeium/hooks.json`

<div id="workspace-level">
  #### Au niveau du workspace
</div>

Les hooks au niveau du workspace permettent aux équipes de versionner des politiques propres au projet aux côtés de leur code. Ils peuvent inclure des règles de validation personnalisées, des intégrations spécifiques au projet ou des workflows propres à l’équipe.

* **Emplacement** : `.windsurf/hooks.json` à la racine de votre workspace

<Note>
  Les hooks provenant des trois emplacements sont **fusionnés**. Si le même événement de hook est configuré à plusieurs emplacements, tous les hooks s’exécuteront dans l’ordre : système → utilisateur → workspace.
</Note>

<div id="basic-structure">
  ### Structure de base
</div>

Voici un exemple de la structure de base de la configuration des 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">
  ### Options de configuration
</div>

Chaque hook accepte les paramètres suivants :

| Paramètre           | Type    | Description                                                                                                                            |
| ------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `command`           | string  | La commande shell à exécuter. Peut être n’importe quel exécutable valide avec des arguments.                                           |
| `show_output`       | boolean | Indique s’il faut afficher la sortie stdout/stderr du hook dans l’interface Cascade visible par l’utilisateur. Utile pour le débogage. |
| `working_directory` | string  | Facultatif. Le répertoire à partir duquel exécuter la commande. Par défaut, la racine de votre workspace.                              |

<Note>
  **À propos du paramètre `working_directory` :**

  * Dans les workspaces comportant plusieurs dépôts, la valeur par défaut est la racine du dépôt actuellement en cours d’utilisation
  * Les chemins relatifs sont résolus à partir de l’emplacement par défaut (racine du workspace ou du dépôt)
  * Les chemins absolus sont pris en charge
  * L’utilisation de `~` pour développer le chemin vers le répertoire personnel n’est pas prise en charge
</Note>

<div id="hook-events">
  ## Événements de hooks
</div>

Cascade propose douze événements de hooks couvrant les actions les plus critiques du workflow de l’agent.

<div id="common-input-structure">
  ### Structure d’entrée commune
</div>

Tous les hooks reçoivent un objet JSON avec les champs communs suivants :

| Champ               | Type   | Description                                                                    |
| ------------------- | ------ | ------------------------------------------------------------------------------ |
| `agent_action_name` | string | Nom de l’événement du hook (p. ex. « pre\_read\_code », « post\_write\_code ») |
| `trajectory_id`     | string | Identifiant unique de l’ensemble de la conversation Cascade                    |
| `execution_id`      | string | Identifiant unique du tour de l’agent                                          |
| `timestamp`         | string | Horodatage ISO 8601 au moment du déclenchement du hook                         |
| `tool_info`         | object | Informations spécifiques à l’événement (varie selon le type de hook)           |

Dans les exemples suivants, les champs communs sont omis pour plus de concision. Il existe douze grands types d’événements de hook :

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

Déclenché **avant** que Cascade ne lise un fichier de code. L’action peut être bloquée si le hook se termine avec le code 2.

**Cas d’usage** : Restreindre l’accès aux fichiers, consigner les opérations de lecture, vérifier les autorisations

**JSON d’entrée** :

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

Ce `file_path` peut être un chemin de répertoire lorsque Cascade parcourt un répertoire de façon récursive.

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

Déclenché **après** que Cascade a lu un fichier de code avec succès.

**Cas d’usage** : consigner les lectures réussies, suivre les schémas d’accès aux fichiers

**JSON d’entrée** :

```json theme={null}
{
  "agent_action_name": "post_read_code",
  "tool_info": {
    "file_path": "/Users/votrenom/projet/fichier.py"
  }
}
```

Ce `file_path` peut être un chemin de répertoire lorsque Cascade lit un répertoire de façon récursive.

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

Déclenché **avant** que Cascade n’écrive ou ne modifie un fichier de code. Cela peut bloquer l’action si le hook se termine avec le code 2.

**Cas d’utilisation** : Empêcher les modifications de fichiers protégés, sauvegarder les fichiers avant les changements

**Input 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>

Déclenché **après** que Cascade a écrit ou modifié un fichier de code.

**Cas d’utilisation** : Exécuter des linters, des formateurs ou des tests ; consigner les modifications de code

**JSON d’entrée**:

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

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

Déclenché **avant** que Cascade n’exécute une commande dans le terminal. L’action peut être bloquée si le hook se termine avec le code 2.

**Cas d’usage** : Bloquer les commandes dangereuses, consigner toutes les exécutions de commandes, ajouter des contrôles de sécurité

**JSON d’entrée** :

```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>

Déclenché **après** l’exécution d’une commande de terminal par Cascade.

**Cas d’usage** : journaliser les résultats de la commande, déclencher des actions ultérieures

**JSON d’entrée** :

```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>

Déclenché **avant** que Cascade n’invoque un outil MCP (Model Context Protocol). L’action peut être bloquée si le hook se termine avec le code 2.

**Cas d’usage** : consigner l’utilisation de MCP, restreindre les outils MCP autorisés

**JSON d’entrée** :

```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": "Signalement de bug",
      "body": "Description du bug ici"
    },
    "mcp_tool_name": "create_issue"
  }
}
```

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

Déclenché **après** que Cascade a invoqué avec succès un outil MCP.

**Cas d’usage** : consigner les opérations MCP, suivre l’utilisation de l’API, afficher les résultats MCP

**JSON d’entrée** :

```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>

Déclenché **avant** que Cascade ne traite le texte de la requête d’un utilisateur. Cela peut bloquer l’action si le hook se termine avec le code 2.

**Cas d’utilisation** : Journaliser toutes les requêtes des utilisateurs à des fins d’audit, bloquer les requêtes potentiellement dangereuses ou non conformes aux règles

**JSON d’entrée** :

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

L'option de configuration `show_output` ne s'applique pas à ce hook.

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

Déclenché de manière asynchrone **après** que Cascade a terminé de répondre à la requête d’un utilisateur. Ce hook reçoit l’intégralité de la réponse générée par Cascade depuis la dernière saisie de l’utilisateur.

**Cas d’utilisation** : journaliser toutes les réponses de Cascade pour audit, analyser les schémas de réponse, envoyer les réponses à des systèmes externes pour examen de conformité

**JSON d’entrée** :

```json theme={null}
{
  "agent_action_name": "post_cascade_response",
  "tool_info": {
    "response": "### Planner Response\n\nI'll help you create that file.\n\n*Created file `/path/to/file.py`*\n\n### Planner Response\n\nThe file has been created successfully."
  }
}
```

Le champ `response` contient le contenu au format Markdown de la réponse de Cascade depuis la dernière saisie de l’utilisateur. Cela inclut les réponses du planificateur, les actions d’outils (lectures et écritures de fichiers, commandes), ainsi que toute autre étape effectuée par Cascade. Il inclut également des informations sur les [règles](/fr/windsurf/cascade/memories-and-rules) qui ont été déclenchées. Voir l’exemple [Suivi des règles déclenchées](#tracking-triggered-rules) pour savoir comment analyser l’utilisation des règles.

L’option de configuration `show_output` ne s’applique pas à ce hook.

<Warning>
  Le contenu de `response` est dérivé des données de trajectoire et peut contenir des informations sensibles provenant de votre base de code ou de vos conversations. Traitez ces données conformément aux politiques de sécurité et de confidentialité de votre organisation.
</Warning>

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

Déclenché de manière asynchrone **après** que Cascade a terminé une réponse à l’invite d’un utilisateur, similaire à `post_cascade_response`. Au lieu de fournir un résumé markdown intégré, ce hook écrit la transcription complète de la conversation (depuis le début de la conversation) dans un fichier JSONL local et fournit le chemin du fichier.

**Cas d’usage** : journalisation d’audit et de conformité pour Enterprise, suivi des contributions générées par l’IA, envoi des transcriptions vers des outils externes d’observabilité ou d’Analytics

**JSON d’entrée** :

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

Le `transcript_path` pointe vers un fichier [JSONL](https://jsonlines.org/) situé à `~/.windsurf/transcripts/{trajectory_id}.jsonl`. Chaque ligne est un objet JSON représentant une étape de la conversation, avec des champs `type` et `status`, ainsi que des données propres à cette étape. Par exemple :

```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 transcription inclut des données détaillées, détenues par le client, telles que le contenu des fichiers, les sorties de commande, les arguments des outils, les résultats de recherche, ainsi que les [règles](/fr/windsurf/cascade/memories-and-rules) qui ont été appliquées. Veuillez noter que la structure exacte de chaque étape peut changer dans de futures versions ; veillez donc à rendre tous les consommateurs de hooks résilients à ces évolutions.

Les fichiers de transcription sont écrits avec les autorisations `0600`. Windsurf limite automatiquement le répertoire de transcriptions à 100 fichiers, en supprimant les plus anciens selon leur date de modification.

L’option de configuration `show_output` ne s’applique pas à ce hook.

Ce tableau présente les différences clés entre les hooks `post_cascade_response` et `post_cascade_response_with_transcript` :

|                  | `post_cascade_response`                                     | `post_cascade_response_with_transcript`                                                       |
| ---------------- | ----------------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| **Data scope**   | Uniquement les étapes depuis la dernière entrée utilisateur | L’ensemble de la conversation depuis le début                                                 |
| **Format**       | Résumé en Markdown dans `tool_info.response`                | Fichier JSONL structuré à l’emplacement `tool_info.transcript_path`                           |
| **Detail level** | Résumé condensé, lisible par un humain                      | Données détaillées, lisibles par une machine (contenu de fichiers, sorties de commande, etc.) |
| **Delivery**     | En ligne via JSON sur stdin                                 | Fichier sur disque (`~/.windsurf/transcripts/`)                                               |

<Warning>
  Les fichiers de transcription contiendront des informations sensibles provenant de votre base de code, y compris le contenu des fichiers, les sorties de commande et l’historique des conversations. Traitez ces fichiers conformément aux politiques de sécurité et de confidentialité de votre organisation.
</Warning>

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

Déclenché **après** la création et la configuration d’un nouveau [git worktree](./worktrees). Le hook est exécuté dans le répertoire du nouveau **worktree**.

**Cas d’utilisation** : Copier les fichiers `.env` ou d’autres fichiers non suivis dans le worktree, installer les dépendances, exécuter des scripts de configuration

**Variables d’environnement** :

| Variable               | Description                                                                                                                                    |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `$ROOT_WORKSPACE_PATH` | Le chemin absolu vers le workspace d’origine. Utilisez-le pour accéder aux fichiers ou exécuter des commandes relativement au dépôt d’origine. |

**JSON d’entrée** :

```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">
  ## Codes de sortie
</div>

Vos scripts de hook communiquent leurs résultats via des codes de sortie :

| Code de sortie | Signification    | Effet                                                                                               |
| -------------- | ---------------- | --------------------------------------------------------------------------------------------------- |
| `0`            | Réussite         | L’action se poursuit normalement                                                                    |
| `2`            | Erreur bloquante | L’agent Cascade verra le message d’erreur sur stderr. Pour les pré-hooks, cela **bloque** l’action. |
| Tout autre     | Erreur           | L’action se poursuit normalement                                                                    |

<Warning>
  Seuls les **pré-hooks** (pre\_user\_prompt, pre\_read\_code, pre\_write\_code, pre\_run\_command, pre\_mcp\_tool\_use) peuvent bloquer des actions avec le code de sortie 2. Les post-hooks ne peuvent pas bloquer, puisque l’action a déjà eu lieu.
</Warning>

Gardez à l’esprit que l’utilisateur peut voir toute sortie standard et toute erreur standard générées par un hook dans l’interface Cascade si `show_output` est à true.

<div id="example-use-cases">
  ## Exemples d’utilisations
</div>

<div id="logging-all-cascade-actions">
  ### Journalisation de toutes les actions Cascade
</div>

Enregistrez chaque action effectuée par Cascade à des fins d’audit.

**Config** :

```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"Erreur lors de l'analyse du JSON : {e}", file=sys.stderr)
        sys.exit(1)

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

Ce script consigne chaque appel de hook dans un fichier journal, créant un historique d’audit de toutes les actions Cascade. Vous pouvez transformer les données d’entrée ou implémenter une logique personnalisée selon vos besoins.

<div id="restricting-file-access">
  ### Restriction de l’accès aux fichiers
</div>

Empêcher Cascade de lire des fichiers en dehors d’un répertoire spécifique.

**Configuration** :

```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():
    # Lire les données JSON depuis stdin
    input_data = sys.stdin.read()

    # Analyser le 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"Accès refusé : Cascade ne peut lire que les fichiers sous {ALLOWED_PREFIX}", file=sys.stderr)
                sys.exit(2)  # Le code de sortie 2 bloque l'action
            
            print(f"Accès autorisé : {file_path}", file=sys.stdout)

    except json.JSONDecodeError as e:
        print(f"Erreur lors de l'analyse du JSON : {e}", file=sys.stderr)
        sys.exit(1)

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

Lorsque Cascade tente de lire un fichier en dehors du répertoire autorisé, ce hook bloque l’opération et affiche un message d’erreur.

<div id="blocking-dangerous-commands">
  ### Blocage des commandes dangereuses
</div>

Empêchez Cascade d’exécuter des commandes potentiellement dangereuses.

**Configuration** :

```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"Commande bloquée : '{dangerous_cmd}' n'est pas autorisé pour des raisons de sécurité.", 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()
```

Ce hook analyse les commandes à la recherche de schémas dangereux et les bloque avant leur exécution.

<div id="blocking-policy-violating-prompts">
  ### Blocage des prompts non conformes aux politiques
</div>

Empêchez les utilisateurs de soumettre des prompts qui enfreignent les politiques de l'organisation.

**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():
    # Lire les données JSON depuis stdin
    input_data = sys.stdin.read()

    # Parser le 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)  # Le code de sortie 2 bloque le prompt

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

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

Ce hook analyse les prompts des utilisateurs avant leur traitement et bloque tous ceux qui contiennent des motifs interdits. Lorsqu'un prompt est bloqué, l'utilisateur voit s'afficher un message d'erreur dans l'interface de Cascade.

<div id="logging-cascade-responses">
  ### Journalisation des réponses de Cascade
</div>

Consignez toutes les réponses de Cascade pour les besoins d’audit de conformité ou d’Analytics.

**Configuration** :

```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():
    # Lire les données JSON depuis stdin
    input_data = sys.stdin.read()

    # Analyser le 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())

            # Enregistrer dans un fichier
            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"Erreur lors de l'analyse du JSON : {e}", file=sys.stderr)
        sys.exit(1)

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

Ce hook enregistre chaque réponse de Cascade dans un fichier, créant une piste d’audit de l’ensemble du contenu généré par l’IA. Vous pouvez l’étendre pour envoyer des données vers des systèmes de logs externes, des bases de données ou des plateformes de conformité.

<div id="tracking-triggered-rules">
  ### Suivi des règles déclenchées
</div>

Identifiez quelles [règles](/fr/windsurf/cascade/memories-and-rules) ont été appliquées lors des interactions avec Cascade, à des fins d’observabilité et de mesure.

**Config** :

```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:
    """
    Analyse les règles déclenchées à partir de la réponse Cascade.
    Les règles apparaissent sous la forme : - (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()
```

**Types de règles :**

* `Always On` - Règles toujours actives
* `Model Decision` - Règles dont les descriptions ont été présentées au modèle d’IA pour une application conditionnelle
* `Manual` - Règles explicitement mentionnées avec @ dans la saisie utilisateur
* `Global` - Règles globales provenant de `global_rules.md`
* `Glob` - Règles déclenchées par l’accès à des fichiers correspondant à des motifs glob

<Note>
  Cela indique quelles règles ont été *présentées* au modèle d’IA ou *déclenchées* par l’accès aux fichiers, mais n’indique pas si le modèle d’IA a effectivement *suivi* une règle. Les règles déjà affichées récemment dans la conversation sont dédupliquées et peuvent ne pas réapparaître avant un certain temps.
</Note>

<div id="running-code-formatters-after-edits">
  ### Exécuter des formatteurs de code après modification
</div>

Formatez automatiquement les fichiers après que Cascade les a modifiés.

**Configuration** :

```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

# Lire le JSON depuis stdin
input=$(cat)

# Extraire le chemin du fichier avec jq
file_path=$(echo "$input" | jq -r '.tool_info.file_path')

# Formater selon l'extension du fichier
if [[ "$file_path" == *.py ]]; then
    black "$file_path" 2>&1
    echo "Fichier Python formaté : $file_path"
elif [[ "$file_path" == *.js ]] || [[ "$file_path" == *.ts ]]; then
    prettier --write "$file_path" 2>&1
    echo "Fichier JS/TS formaté : $file_path"
elif [[ "$file_path" == *.go ]]; then
    gofmt -w "$file_path" 2>&1
    echo "Fichier Go formaté : $file_path"
fi

exit 0
```

Ce hook exécute automatiquement le formatteur adapté au type de fichier après chaque modification.

<div id="setting-up-worktrees">
  ### Mise en place des worktrees
</div>

Copiez les fichiers d'environnement et installez les dépendances lorsqu'un nouveau worktree est créé.

**Config** (dans `.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

# Copier les fichiers d'environnement depuis le workspace d'origine
if [ -f "$ROOT_WORKSPACE_PATH/.env" ]; then
    cp "$ROOT_WORKSPACE_PATH/.env" .env
    echo "Fichier .env copié"
fi

if [ -f "$ROOT_WORKSPACE_PATH/.env.local" ]; then
    cp "$ROOT_WORKSPACE_PATH/.env.local" .env.local
    echo "Fichier .env.local copié"
fi

# Installer les dépendances
if [ -f "package.json" ]; then
    npm install
    echo "Dépendances npm installées"
fi

exit 0
```

Ce hook garantit que, pour chaque worktree, la configuration d'environnement et les dépendances nécessaires sont automatiquement installées.

<div id="best-practices">
  ## Bonnes pratiques
</div>

<div id="security">
  ### Sécurité
</div>

<Warning>
  **Utilisez les hooks Cascade à vos risques et périls** : les hooks exécutent automatiquement des commandes shell avec l’ensemble des permissions de votre compte utilisateur. Vous êtes entièrement responsable du code que vous configurez. Des hooks mal conçus ou malveillants peuvent modifier des fichiers, supprimer des données, exposer des secrets ou compromettre votre système.
</Warning>

* **Validez toutes les entrées** : Ne faites jamais confiance au JSON d’entrée sans validation, en particulier pour les chemins de fichiers et les commandes.
* **Utilisez des chemins absolus** : Utilisez toujours des chemins absolus dans vos configurations de hooks pour éviter toute ambiguïté.
* **Protégez les données sensibles** : Évitez de journaliser des informations sensibles comme des clés d’API ou des identifiants.
* **Vérifiez les permissions** : Assurez-vous que vos scripts de hook disposent des permissions appropriées sur le système de fichiers.
* **Auditez avant le déploiement** : Passez en revue chaque commande et chaque script de hook avant de l’ajouter à votre configuration.
* **Testez en isolation** : Exécutez les hooks dans un environnement de test avant de les activer sur votre machine de développement principale.

<div id="performance-considerations">
  ### Considérations sur les performances
</div>

* **Gardez les hooks rapides** : Des hooks lents dégraderont la réactivité de Cascade. Visez des temps d'exécution inférieurs à 100 ms.
* **Utilisez des opérations asynchrones** : Pour des hooks non bloquants, envisagez de journaliser vers une file d'attente ou une base de données de façon asynchrone.
* **Filtrez dès le début** : Vérifiez le type d'action au démarrage de votre script pour éviter tout traitement inutile.

<div id="error-handling">
  ### Gestion des erreurs
</div>

* **Toujours valider le JSON** : Utilisez des blocs try-catch pour gérer proprement les entrées malformées.
* **Journalisez correctement les erreurs** : Écrivez-les sur `stderr` afin qu’elles soient visibles lorsque `show_output` est activé.
* **Échec sécurisé** : Si votre hook rencontre une erreur, déterminez s’il doit bloquer l’action ou la laisser se poursuivre.

<div id="testing-your-hooks">
  ### Tester vos hooks
</div>

1. **Commencez par la journalisation** : Implémentez d’abord un hook de journalisation simple pour comprendre le flux de données.
2. **Utilisez `show_output: true`** : Activez l’affichage de la sortie pendant le développement pour voir ce que font vos hooks.
3. **Testez le comportement de blocage** : Vérifiez que le code de sortie 2 bloque correctement les actions dans les pré-hooks.
4. **Couvrez tous les chemins d’exécution** : Testez les scénarios de réussite comme d’échec dans vos scripts.

<div id="enterprise-distribution">
  ## Distribution Enterprise
</div>

Les organisations Enterprise doivent appliquer des politiques de sécurité, des exigences de conformité et des normes de développement que les utilisateurs individuels ne peuvent pas contourner. Cascade Hooks prend en charge deux méthodes de distribution Enterprise :

1. **Cloud Dashboard** - Configurez les hooks via les paramètres d'équipe dans le tableau de bord Windsurf
2. **Fichiers au niveau du système** - Déployez les hooks via des outils MDM ou de gestion de configuration

Les deux méthodes peuvent être utilisées ensemble : les hooks provenant de toutes les sources sont combinés et exécutés dans l'ordre.

<div id="cloud-dashboard-configuration">
  ### Configuration du tableau de bord Cloud
</div>

Les administrateurs d'équipe peuvent configurer les Cascade Hooks directement depuis le tableau de bord Windsurf.

**Prérequis :**

* Offre Enterprise
* Autorisation `TEAM_SETTINGS_UPDATE`

**Pour configurer :**

1. Accédez à **Team Settings** dans le tableau de bord Windsurf
2. Recherchez la section **Cascade Hooks**
3. Saisissez votre configuration de hooks au format JSON
4. Enregistrez vos modifications

Les hooks configurés via le tableau de bord sont automatiquement distribués à tous les membres de l'équipe et chargés au démarrage de Windsurf. Les hooks configurés dans le cloud sont chargés en premier, suivis des hooks au niveau système, utilisateur et workspace.

<Note>
  Lorsque plusieurs configurations d'équipe sont fusionnées, les hooks sont combinés par action plutôt que remplacés. Cela signifie que les hooks de toutes les configurations d'équipe applicables s'exécuteront ensemble.
</Note>

<div id="system-level-file-deployment">
  ### Déploiement de fichiers au niveau du système
</div>

Pour les organisations qui préfèrent une configuration basée sur des fichiers ou qui ont besoin que les hooks fonctionnent hors ligne, déployez votre configuration obligatoire `hooks.json` aux emplacements spécifiques au système d’exploitation suivants :

**macOS :**

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

**Linux/WSL :**

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

**Windows :**

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

Placez vos scripts de hooks dans le répertoire système correspondant (par exemple, `/usr/local/share/windsurf-hooks/` sur les systèmes Unix).

Les hooks au niveau du système ont priorité sur les hooks utilisateur et de workspace et ne peuvent pas être désactivés par les utilisateurs finaux sans privilèges root.

<div id="mdm-and-configuration-management">
  #### MDM et gestion de configuration
</div>

Les équipes IT Enterprise peuvent déployer des hooks au niveau du système à l'aide d'outils standard :

**Mobile Device Management (MDM)**

* **Jamf Pro** (macOS) - Déployez via des profils de configuration ou des scripts
* **Microsoft Intune** (Windows/macOS) - Utilisez des scripts PowerShell ou un déploiement de stratégies
* **Workspace ONE**, **Google Endpoint Management**, et autres solutions MDM

**Gestion de configuration**

* **Ansible**, **Puppet**, **Chef**, **SaltStack** - Utilisez votre automatisation d’infrastructure existante
* **Scripts de déploiement personnalisés** - Scripts shell, PowerShell ou l’outil de votre choix

<div id="verification-and-auditing">
  #### Vérification et audit
</div>

Après le déploiement, vérifiez que les hooks sont correctement installés :

```bash theme={null}
# Vérifier la présence des hooks système
ls -la /etc/windsurf/hooks.json  # Linux
ls -la "/Library/Application Support/Windsurf/hooks.json"  # macOS

# Tester l'exécution des hooks (la sortie devrait apparaître dans Cascade)
# Demander à un développeur de déclencher l'action Cascade appropriée

# Vérifier que les utilisateurs ne peuvent pas modifier les hooks système
sudo chown root:root /etc/windsurf/hooks.json
sudo chmod 644 /etc/windsurf/hooks.json
```

<Note>
  **Important :** Les hooks système sont entièrement gérés par votre équipe informatique ou sécurité. Windsurf ne déploie ni ne gère de fichiers dans des emplacements système. Veillez à ce que vos équipes internes se chargent du déploiement, des mises à jour et de la conformité conformément aux politiques de votre organisation.
</Note>

<div id="workspace-hooks-for-team-projects">
  ### Hooks de workspace pour les projets d’équipe
</div>

Pour les conventions propres à un projet, les équipes peuvent utiliser des hooks au niveau du workspace dans le système de contrôle de version :

```bash theme={null}
# Ajouter à votre dépôt
.windsurf/
├── hooks.json
└── scripts/
    └── format-check.py

# Valider dans git
git add .windsurf/
git commit -m "Ajouter des hooks de workspace pour le formatage du code"
```

Cela permet aux équipes d’uniformiser les pratiques de développement. Conservez les politiques critiques en matière de sécurité au niveau du cloud ou du système et évitez de valider des informations sensibles dans le système de contrôle de version.

<div id="additional-resources">
  ## Ressources supplémentaires
</div>

* **Intégration MCP** : En savoir plus sur le [Model Context Protocol dans Windsurf](/fr/windsurf/cascade/mcp)
* **Workflows** : Découvrez comment combiner des hooks avec les [workflows Cascade](/fr/windsurf/cascade/workflows)
* **Analytics** : Suivez l’utilisation de Cascade avec les [Analytics d’équipe](/fr/windsurf/accounts/analytics)
