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.
Version bêta : les Cascade Hooks sont actuellement en bêta et font l’objet d’un développement actif. Les fonctionnalités et les API peuvent évoluer. Veuillez contacter le support Windsurf pour tout commentaire ou rapport de bug.
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.
Les hooks ouvrent un large éventail de fonctions d’automatisation et de gouvernance :
- Journalisation et Analytics : suivez chaque fichier lu, chaque modification de code ou chaque commande exécutée par Cascade pour la conformité et l’analyse de l’usage
- Contrôles de sécurité : empêchez Cascade d’accéder à des fichiers sensibles ou d’exécuter des commandes dangereuses
- 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
Les hooks sont des commandes de shell qui s’exécutent automatiquement lors d’actions Cascade spécifiques. Chaque hook :
- Reçoit un contexte (des détails sur l’action en cours) au format JSON via l’entrée standard
- Exécute votre script — Python, Bash, Node.js ou tout exécutable
- 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.
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.
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.
- macOS :
/Library/Application Support/Windsurf/hooks.json
- Linux/WSL :
/etc/windsurf/hooks.json
- Windows :
C:\ProgramData\Windsurf\hooks.json
Les hooks au niveau utilisateur sont parfaits pour des préférences personnelles et des workflows optionnels.
- Emplacement :
~/.codeium/windsurf/hooks.json
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
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.
Voici un exemple de la structure de base de la configuration des hooks :
{
"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
}
]
}
}
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. |
Cascade propose huit événements de hooks couvrant les actions les plus critiques du workflow de l’agent.
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 huit grands types d’événements de hook :
pre_read_code
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 :
{
"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.
post_read_code
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 :
{
"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.
pre_write_code
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:
{
"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"
}
]
}
}
post_write_code
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:
{
"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"
}
]
}
}
pre_run_command
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 :
{
"agent_action_name": "pre_run_command",
"tool_info": {
"command_line": "npm install package-name",
"cwd": "/Users/yourname/project"
}
}
post_run_command
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 :
{
"agent_action_name": "post_run_command",
"tool_info": {
"command_line": "npm install package-name",
"cwd": "/Users/yourname/project"
}
}
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 :
{
"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"
}
}
post_mcp_tool_use
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 :
{
"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"
}
}
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 |
Seuls les pré-hooks (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.
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.
Journalisation de toutes les actions Cascade
Enregistrez chaque action effectuée par Cascade à des fins d’audit.
Config (~/.codeium/windsurf/hooks.json):
{
"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
}
]
}
}
Script (log_input.py) :
#!/usr/bin/env python3
import sys
import json
def main():
# Lire les données JSON depuis stdin
input_data = sys.stdin.read()
# Parser 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"Erreur lors du parsing 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 une piste d’audit de toutes les actions Cascade. Vous pouvez transformer les données d’entrée ou exécuter une logique personnalisée selon vos besoins.
Restriction de l’accès aux fichiers
Empêcher Cascade de lire des fichiers en dehors d’un répertoire spécifique.
Configuration (~/.codeium/windsurf/hooks.json) :
{
"hooks": {
"pre_read_code": [
{
"command": "python3 /Users/yourname/hooks/block_read_access.py",
"show_output": true
}
]
}
}
Script (block_read_access.py) :
#!/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.
Blocage des commandes dangereuses
Empêchez Cascade d’exécuter des commandes potentiellement dangereuses.
Configuration (~/.codeium/windsurf/hooks.json) :
{
"hooks": {
"pre_run_command": [
{
"command": "python3 /Users/yourname/hooks/block_dangerous_commands.py",
"show_output": true
}
]
}
}
Script (block_dangerous_commands.py) :
#!/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"Commande bloquée : '{dangerous_cmd}' n'est pas autorisé pour des raisons de sécurité.", file=sys.stderr)
sys.exit(2) # Le code de sortie 2 bloque la commande
print(f"Commande approuvée : {command}", 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()
Ce hook analyse les commandes pour détecter des motifs dangereux et les bloque avant leur exécution.
Formatez automatiquement les fichiers après que Cascade les a modifiés.
Configuration (~/.codeium/windsurf/hooks.json):
{
"hooks": {
"post_write_code": [
{
"command": "bash /Users/yourname/hooks/format_code.sh",
"show_output": false
}
]
}
}
Script (format_code.sh) :
#!/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.
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.
- 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.
- 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.
- 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.
- Commencez par la journalisation : Implémentez d’abord un hook de journalisation simple pour comprendre le flux de données.
- Utilisez
show_output: true : Activez l’affichage de la sortie pendant le développement pour voir ce que font vos hooks.
- Testez le comportement de blocage : Vérifiez que le code de sortie 2 bloque correctement les actions dans les pré-hooks.
- Couvrez tous les chemins d’exécution : Testez les scénarios de réussite comme d’échec dans vos scripts.
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 cela via une configuration au niveau du système, qui a priorité et ne peut pas être désactivée par les utilisateurs finaux sans privilèges root.
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 :
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 équipes IT Enterprise peuvent déployer des hooks au niveau du système à l’aide d’outils et de workflows 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
Après le déploiement, vérifiez que les hooks sont correctement installés et ne peuvent pas être contournés :
# 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
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.
Hooks de workspace pour les projets d’équipe
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 :
# 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. Veillez à maintenir les politiques critiques en matière de sécurité au niveau du système et à ne jamais valider d’informations sensibles dans le système de contrôle de version.
Ressources supplémentaires