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

# Hooks de Cascade

> Exécutez des commandes shell personnalisées à des points clés du workflow de Cascade pour la journalisation, les contrôles de sécurité, la validation et la gouvernance Enterprise à l’aide de hooks pre et post.

Les Hooks de Cascade vous permettent d’exécuter des commandes shell personnalisées à des points clés du workflow de Cascade. Cette puissante fonctionnalité d’extensibilité vous permet de journaliser les opérations, d’appliquer des garde-fous, d’exécuter des vérifications de validation ou d’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 fin 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 mettre en place
</div>

Les Hooks offrent un large éventail de capacités d’automatisation et de gouvernance :

* **Journalisation et analyse** : suivez chaque fichier lu, chaque modification de code, chaque commande exécutée, chaque prompt utilisateur ou chaque réponse de Cascade à des fins de conformité et d’analyse de l’utilisation
* **Contrôles de sécurité** : empêchez Cascade d’accéder à des fichiers sensibles, d’exécuter des commandes dangereuses ou de traiter des prompts non conformes aux politiques
* **Assurance qualité** : exécutez automatiquement des linters, des outils de formatage ou des tests après des modifications de code
* **Workflows personnalisés** : intégrez des outils de suivi des problèmes, des systèmes de notification ou des pipelines de déploiement
* **Standardisation des équipes** : appliquez des normes de codage et des bonnes pratiques dans toute votre organisation

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

Les Hooks sont des commandes shell qui s’exécutent automatiquement lorsque certaines actions de Cascade se produisent. Chaque hook :

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

Pour les **pre-hooks** (exécutés avant une action), votre script peut **bloquer l’action** en se terminant avec le code de sortie `2`. Les pre-hooks sont donc idéaux pour mettre en œuvre des politiques de sécurité ou des contrôles de validation.

<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 depuis tous ces emplacements, offrant aux Teams la flexibilité nécessaire pour répartir et gérer les configurations de hooks.

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

Les hooks au niveau système sont idéaux pour appliquer des politiques à l’échelle de l’organisation sur des machines de développement partagées. Par exemple, vous pouvez les utiliser pour imposer des politiques de sécurité, des exigences de conformité ou des workflows obligatoires de révision du code. Les équipes Enterprise peuvent également configurer des hooks via le [tableau de bord cloud](#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 les préférences personnelles et les workflows optionnels.

* **Devin Desktop IDE**: `~/.codeium/windsurf/hooks.json`
* **JetBrains Plugin**: `~/.codeium/hooks.json`

<div id="workspace-level">
  #### Au niveau de l’espace de travail
</div>

Les hooks définis au niveau de l’espace de travail permettent aux équipes de versionner des politiques propres au projet avec 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 espace de travail

<Note>
  Les hooks 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 → espace de travail.
</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",
        "powershell": "python3 C:\\path\\to\\your\\script.py",
        "show_output": true
      }
    ],
    "post_write_code": [
      {
        "command": "python3 /path/to/another/script.py",
        "show_output": true
      }
    ]
  }
}
```

Dans cet exemple, `pre_read_code` spécifie à la fois une commande pour macOS/Linux et une commande PowerShell pour Windows. Le hook `post_write_code` ne spécifie que `command` ; il s’exécutera donc sur macOS/Linux et utilisera PowerShell par défaut sous Windows.

<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 sur **macOS/Linux** (via `bash -c`). Au moins l’un des paramètres `command` ou `powershell` doit être spécifié.            |
| `powershell`        | string  | Facultatif. La commande à exécuter sur **Windows** (via `powershell -Command`). S’il est omis sous Windows, `command` est utilisé en solution de repli. |
| `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 depuis lequel exécuter la commande. Par défaut, la racine de votre espace de travail est utilisée.                            |

<div id="cross-platform-behavior">
  #### Comportement multiplateforme
</div>

Les champs `command` et `powershell` permettent de définir, dans une même configuration, des commandes adaptées à chaque plateforme. C’est utile pour les équipes ayant un parc mixte macOS/Linux et Windows.

| Plateforme  | `command` défini | `powershell` défini | Résultat                                       |
| ----------- | :--------------: | :-----------------: | ---------------------------------------------- |
| macOS/Linux |         ✓        |       (ignoré)      | Exécute `command` via `bash -c`                |
| macOS/Linux |         ✗        |          ✓          | Le hook est ignoré sans avertissement          |
| Windows     |         ✓        |          ✗          | Utilise `command` via `powershell -Command`    |
| Windows     |         ✗        |          ✓          | Exécute `powershell` via `powershell -Command` |
| Windows     |         ✓        |          ✓          | Exécute `powershell` via `powershell -Command` |
| Toutes      |         ✗        |          ✗          | Erreur de validation                           |

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

  * Dans les espaces de travail multi-repo, la valeur par défaut est la racine du repo en cours de traitement
  * Les chemins relatifs sont résolus depuis l’emplacement par défaut (espace de travail ou racine du repo)
  * Les chemins absolus sont pris en charge
  * L’utilisation de `~` pour développer le home directory n’est pas prise en charge
</Note>

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

Cascade propose douze événements de hook qui couvrent les principales actions du workflow des agents.

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

Tous les hooks reçoivent un objet JSON contenant 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 d’un tour d’agent                                                                                                                                                                                                                                                                                                                           |
| `timestamp`         | string | Horodatage ISO 8601 indiquant quand le hook a été déclenché                                                                                                                                                                                                                                                                                                    |
| `model_name`        | string | Nom lisible du modèle associé à cette invocation du hook (p. ex. : "Claude Sonnet 4", "GPT 4.1"). Il s’agit du même libellé affiché dans le sélecteur de modèles Cascade. Cette valeur peut évoluer au fil du temps à mesure que Devin Desktop met à jour les noms d’affichage des modèles. Défini sur "Unknown" lorsque le modèle ne peut pas être déterminé. |
| `tool_info`         | object | Informations spécifiques à l’événement (varient selon le type de hook)                                                                                                                                                                                                                                                                                         |

Dans les exemples suivants, les champs communs sont omis par souci de concision. Il existe douze principaux 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. Cela peut bloquer l’action si le hook renvoie le code 2.

**Cas d’utilisation** : restreindre l’accès aux fichiers, journaliser 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 correspondre au chemin d’un répertoire lorsque Cascade lit 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 avec succès un fichier de code.

**Cas d’utilisation** : consigner les lectures réussies, suivre les modes d’accès aux fichiers

**JSON d’entrée** :

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

Ce `file_path` peut être le chemin d’un 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 un code de sortie 2.

**Cas d’usage** : empêcher les modifications de fichiers protégés, sauvegarder les fichiers avant toute modification

**JSON d’entrée** :

```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 outils de formatage 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/yourname/project/file.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. Cela peut bloquer l’action si le hook se termine avec le code 2.

**Cas d’usage** : bloquer les commandes dangereuses, journaliser toutes les exécutions de commandes, ajouter des vérifications 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** que Cascade exécute une commande dans le terminal.

**Cas d’utilisation** : Consigner les résultats des commandes, déclencher des actions de suivi

**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). Cela peut bloquer l’action si le hook se termine avec le code de sortie 2.

**Cas d’utilisation** : consigner l’utilisation des outils 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": "Bug report",
      "body": "Description of the bug here"
    },
    "mcp_tool_name": "create_issue"
  }
}
```

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

Déclenché **après** l’invocation réussie d’un outil MCP par Cascade.

**Cas d’usage** : consigner les opérations MCP, suivre l’utilisation de l’API, consulter 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 du prompt d’un utilisateur. Cela peut bloquer l’action si le hook se termine avec le code 2.

**Cas d’usage** : consigner tous les prompts des utilisateurs à des fins d’audit, bloquer les prompts potentiellement dangereux ou contraires aux politiques

**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 fini de répondre au prompt d’un utilisateur. Ce hook reçoit l’intégralité de la réponse de Cascade depuis la dernière saisie de l’utilisateur.

**Cas d’utilisation** : Journaliser toutes les réponses de Cascade à des fins d’audit, analyser les tendances des réponses, envoyer les réponses à des systèmes externes pour un contrôle 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 planner, les actions des outils (lecture et écriture de fichiers, commandes) ainsi que toutes les autres étapes effectuées par Cascade. Il inclut également des informations sur les [règles](/fr/desktop/cascade/memories) qui ont été déclenchées. Consultez 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 issu 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é de répondre au prompt d’un utilisateur, comme `post_cascade_response`. Au lieu de fournir un résumé Markdown inline, ce hook écrit la transcription intégrale de la conversation (depuis le début de la conversation) dans un fichier JSONL local et fournit le chemin vers ce fichier.

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

**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 un champ `type`, un champ `status` et 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 comprend des données détaillées propres au client, telles que le contenu des fichiers, les sorties de commandes, les arguments des outils, les résultats de recherche et les [règles](/fr/desktop/cascade/memories) appliquées. Notez que la structure exacte de chaque étape peut évoluer dans les futures versions. Concevez donc tout consommateur de hook pour qu’il soit robuste face à ces changements.

Les fichiers de transcription sont écrits avec les permissions `0600`. Devin Desktop limite automatiquement le répertoire des 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 principales différences entre les hooks `post_cascade_response` et `post_cascade_response_with_transcript` :

|                           | `post_cascade_response`                                          | `post_cascade_response_with_transcript`                                                     |
| ------------------------- | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
| **Périmètre des données** | Uniquement les étapes depuis la dernière saisie de l’utilisateur | L’intégralité de la conversation depuis le début                                            |
| **Format**                | Résumé Markdown dans `tool_info.response`                        | Fichier JSONL structuré dans `tool_info.transcript_path`                                    |
| **Niveau de détail**      | Résumé condensé, lisible par un humain                           | Données détaillées, lisibles par machine (contenu des fichiers, sorties de commandes, etc.) |
| **Mode de transmission**  | Inline via JSON sur stdin                                        | Fichier sur disque (`~/.windsurf/transcripts/`)                                             |

<Warning>
  Les fichiers de transcription contiendront des informations sensibles de votre base de code, notamment le contenu des fichiers, les sorties de commandes et l’historique des conversations. Manipulez 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’usage** : copier des fichiers `.env` ou d’autres fichiers non suivis dans le worktree, installer des dépendances, exécuter des scripts d’installation

**Variables d’environnement** :

| Variable               | Description                                                                                                                                            |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `$ROOT_WORKSPACE_PATH` | Le chemin absolu vers l’espace de travail d’origine. Utilisez-le pour accéder à des fichiers ou exécuter des commandes par rapport 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 au moyen de codes de sortie :

| Code de sortie     | Signification    | Effet                                                                                                        |
| ------------------ | ---------------- | ------------------------------------------------------------------------------------------------------------ |
| `0`                | Succès           | L’action se poursuit normalement                                                                             |
| `2`                | Erreur bloquante | L’agent Cascade verra le message d’erreur provenant de stderr. Pour les pré-hooks, cela **bloque** l’action. |
| Toute autre valeur | 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 à l’aide du code de sortie 2. Les post-hooks ne peuvent pas bloquer une action, puisqu’elle 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` a la valeur true.

<div id="example-use-cases">
  ## Exemples de cas d’usage
</div>

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

Suivez chaque action de Cascade à des fins d’audit.

**Configuration**:

```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():
    # Lire les données JSON depuis stdin
    input_data = sys.stdin.read()
    
    # Analyser le JSON
    try:
        data = json.loads(input_data)
        
        # Écrire le JSON formaté dans le fichier
        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 parsing JSON: {e}", file=sys.stderr)
        sys.exit(1)

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

Ce script ajoute chaque appel de hook à un fichier journal, créant une piste d’audit de toutes les actions de Cascade. Vous pouvez transformer les données d’entrée ou exécuter une logique personnalisée selon vos besoins.

<div id="restricting-file-access">
  ### Restreindre l'accès aux fichiers
</div>

Empêchez Cascade de lire des fichiers en dehors d'un répertoire donné.

**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"Access denied: Cascade is only allowed to read files under {ALLOWED_PREFIX}", file=sys.stderr)
                sys.exit(2)  # Le code de sortie 2 bloque l'action
            
            print(f"Access granted: {file_path}", file=sys.stdout)

    except json.JSONDecodeError as e:
        print(f"Error parsing 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():
    # 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_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"Command blocked: '{dangerous_cmd}' is not allowed for safety reasons.", file=sys.stderr)
                    sys.exit(2)  # Le code de sortie 2 bloque la commande
            
            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 pour y détecter des motifs dangereux et les bloque avant leur exécution.

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

Empêchez les utilisateurs de soumettre des prompts contraires aux politiques de l'organisation.

**Configuration**:

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

    # Analyser 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 examine les prompts de l’utilisateur avant leur traitement et bloque ceux qui contiennent des patterns interdits. Lorsqu’un prompt est bloqué, l’utilisateur voit un message d’erreur dans l’interface Cascade.

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

Consignez toutes les réponses de Cascade à des fins d’audit de conformité ou d’analyse.

**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()

    # Parser 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())

            # Journaliser dans le 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"Error parsing 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 ainsi une trace d’audit de l’ensemble du contenu généré par l’IA. Vous pouvez l’étendre pour envoyer ces données vers des systèmes externes de journalisation, des bases de données ou des plateformes de conformité.

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

Suivez les [règles](/fr/desktop/cascade/memories) appliquées lors des interactions avec Cascade à des fins d’observabilité et de suivi des métriques.

**Configuration**:

```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:
    """
    Parse triggered rules from the Cascade response.
    Rules appear as: - (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())

            # Écrire dans le fichier journal
            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 incluses
* `Model Decision` - Règles dont la description a été présentée au modèle pour une application conditionnelle
* `Manual` - Règles explicitement mentionnées avec @ dans la saisie de l’utilisateur
* `Global` - Règles globales issues de `global_rules.md`
* `Glob` - Règles déclenchées par un accès à des fichiers correspondant à des motifs glob

<Note>
  Cela indique quelles règles ont été *présentées* au modèle ou *déclenchées* par un accès aux fichiers, mais pas si le modèle a réellement *respecté* une règle. Les règles déjà montrées récemment dans la conversation sont dédupliquées et peuvent ne réapparaître que plus tard.
</Note>

<div id="running-code-formatters-after-edits">
  ### Exécuter le formatage du code après les modifications
</div>

Formatez automatiquement les fichiers de code après leur modification par Cascade.

**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 "Formatted Python file: $file_path"
elif [[ "$file_path" == *.js ]] || [[ "$file_path" == *.ts ]]; then
    prettier --write "$file_path" 2>&1
    echo "Formatted JS/TS file: $file_path"
elif [[ "$file_path" == *.go ]]; then
    gofmt -w "$file_path" 2>&1
    echo "Formatted Go file: $file_path"
fi

exit 0
```

Ce hook lance automatiquement le formateur adapté au type de fichier après chaque modification.

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

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

**Configuration** (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 "Copied .env file"
fi

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

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

exit 0
```

Ce hook garantit que chaque worktree dispose automatiquement de la configuration d’environnement nécessaire et des dépendances requises.

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

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

<Warning>
  **Utilisez Cascade Hooks à vos propres risques** : les hooks exécutent automatiquement des commandes shell avec l’ensemble des autorisations 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 identifiants ou compromettre votre système.
</Warning>

* **Validez toutes les entrées** : ne faites jamais confiance au JSON d’entrée sans l’avoir validé, en particulier pour les chemins de fichiers et les commandes.
* **Utilisez des chemins absolus** : utilisez toujours des chemins absolus dans vos configurations de hook afin d’éviter toute ambiguïté.
* **Protégez les données sensibles** : évitez de journaliser des informations sensibles comme des clés API ou des identifiants.
* **Vérifiez les autorisations** : assurez-vous que vos scripts de hook disposent des autorisations du système de fichiers appropriées.
* **Auditez avant le déploiement** : examinez chaque commande et script de hook avant de les 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 relatives aux performances
</div>

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

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

* **Validez toujours le JSON** : utilisez des blocs try-catch pour gérer proprement les entrées mal formées.
* **Consignez correctement les erreurs** : écrivez les erreurs dans `stderr` afin qu’elles soient visibles lorsque `show_output` est activé.
* **Prévoyez un échec sans risque** : 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** : commencez par mettre en place un hook de journalisation simple pour mieux 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 hooks de pré-exécution.
4. **Vérifiez tous les chemins d’exécution du code** : testez à la fois les scénarios de réussite et d’échec dans vos scripts.

<div id="enterprise-distribution">
  ## Déploiement Enterprise
</div>

Les organisations Enterprise doivent imposer 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 déploiement Enterprise :

1. **Cloud Dashboard** - Configurez les hooks via Team Settings dans le tableau de bord Devin Desktop
2. **System-Level Files** - Déployez les hooks via MDM ou des outils de gestion de configuration

Les deux méthodes peuvent être utilisées ensemble — les hooks 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 admins de la Team peuvent configurer les Cascade Hooks directement depuis le tableau de bord Devin Desktop.

**Prérequis :**

* plan Enterprise
* autorisation `TEAM_SETTINGS_UPDATE`

**Pour configurer :**

1. Accédez à **Team Settings** dans le tableau de bord Devin Desktop
2. Repérez la section **Cascade Hooks**
3. Saisissez la configuration des 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 la Team et chargés au démarrage de Devin Desktop. Les hooks configurés dans le Cloud sont chargés en premier, suivis des hooks au niveau système, utilisateur et espace de travail.

<Note>
  Lorsque plusieurs configurations de Team sont fusionnées, les hooks sont combinés par action au lieu d’être remplacés. Cela signifie que les hooks de toutes les configurations de Team applicables s’exécutent ensemble.
</Note>

<div id="system-level-file-deployment">
  ### Déploiement des fichiers au niveau 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` dans les emplacements propres à chaque système d’exploitation :

**macOS :**

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

**Linux/WSL :**

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

**Windows :**

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

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

Les hooks au niveau système ont priorité sur les hooks utilisateur et d’espace de travail, 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 la configuration
</div>

Les équipes informatiques Enterprise peuvent déployer des hooks au niveau système à l’aide d’outils standards :

**Gestion des appareils mobiles (MDM)**

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

**Gestion de la configuration**

* **Ansible**, **Puppet**, **Chef**, **SaltStack** - Utilisez vos outils existants d’automatisation de l’infrastructure
* **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 que les hooks système sont présents
ls -la /etc/windsurf/hooks.json  # Linux
ls -la "/Library/Application Support/Windsurf/hooks.json"  # macOS

# Tester l'exécution du hook (la sortie du hook doit 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 de sécurité. Devin Desktop ne déploie ni ne gère de fichiers dans des emplacements système. Assurez-vous que vos équipes internes prennent en charge le déploiement, les mises à jour et la conformité, conformément aux politiques de votre organisation.
</Note>

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

Pour les conventions propres à un projet, les Teams peuvent utiliser des hooks au niveau de l’espace de travail dans le système de contrôle de version :

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

# Committer dans git
git add .windsurf/
git commit -m "Add workspace hooks for code formatting"
```

Cela permet aux équipes de standardiser les pratiques de développement. Conservez les politiques de sécurité critiques au niveau du cloud ou du système, et évitez d’ajouter des informations sensibles au contrôle de version.

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

* **Intégration MCP** : En savoir plus sur le [Model Context Protocol dans Devin Desktop](/fr/desktop/cascade/mcp)
* **Workflows** : Découvrez comment combiner des Hooks avec les [Cascade Workflows](/fr/desktop/cascade/workflows)
* **Analyse** : Suivez l’utilisation de Cascade avec [Team Analytics](/fr/desktop/accounts/analytics)
