Hooks
Les hooks permettent d’observer, de contrôler et d’étendre la boucle de l’Agent à l’aide de scripts personnalisés. Définissez des hooks dans des fichiers hooks.json au niveau du projet ou de l’utilisateur, ou installez-les via des plugins depuis Personnaliser. Les hooks sont des processus qui communiquent via stdio à l’aide de JSON dans les deux sens. Ils s’exécutent avant ou après certaines étapes de la boucle de l’Agent et peuvent observer, bloquer ou modifier le comportement.
Les hooks permettent de :
- Exécuter des formateurs après les modifications
- Ajouter des analyses aux événements
- Analyser les données personnelles ou les secrets
- Bloquer les opérations risquées (par ex., les écritures SQL)
- Contrôler l’exécution des sous-agents (outil Task)
- Injecter du contexte au début d’une session
Vous cherchez des intégrations prêtes à l’emploi ? Voir Intégrations partenaires pour des solutions de sécurité, de gouvernance et de gestion des secrets proposées par nos partenaires de l’écosystème.
Cursor prend en charge le chargement de hooks depuis des outils tiers comme Claude Code. Voir Hooks tiers pour en savoir plus sur la compatibilité et la configuration.
Catégories de hooks
Les hooks se répartissent en trois catégories selon l’événement qui les déclenche :
Hooks d’agent (Cmd+K/Agent Chat) s’exécutent pendant une session d’agent :
sessionStart/sessionEnd- Gestion du cycle de vie de la sessionpreToolUse/postToolUse/postToolUseFailure- Hooks génériques d’utilisation d’outils (s’exécutent pour tous les outils)subagentStart/subagentStop- Cycle de vie des sous-agents (outil Task)beforeShellExecution/afterShellExecution- Contrôler les commandes shellbeforeMCPExecution/afterMCPExecution- Contrôler l’utilisation des outils MCPbeforeReadFile/afterFileEdit- Contrôler l’accès aux fichiers et les modificationsbeforeSubmitPrompt- Valider les prompts avant leur envoipreCompact- Surveiller la compaction de la fenêtre de contextestop- Gérer la fin de l’agentafterAgentResponse/afterAgentThought- Suivre les réponses de l’agent
Hooks Tab (complétions en ligne) s’exécutent lors d’opérations Tab autonomes :
beforeTabFileRead- Contrôler l’accès aux fichiers pour les complétions TabafterTabFileEdit- Post-traiter les modifications effectuées par Tab
Hooks du cycle de vie de l’application s’exécutent en dehors de toute session d’agent :
workspaceOpen- Se déclenche lorsque Cursor ouvre un espace de travail et à chaque changement de dossier dans l’espace de travail. Peut renvoyer des chemins de plugin supplémentaires à charger pour l’espace de travail actuel.
Ces différentes interfaces de hooks vous permettent d’appliquer des stratégies distinctes aux opérations Tab autonomes, aux opérations de l’Agent initiées par l’utilisateur et au démarrage de l’espace de travail.
Prise en charge des agents cloud
Les agents cloud exécutent les hooks basés sur des commandes de votre dépôt. Si des hooks sont définis dans .cursor/hooks.json à la racine de votre projet, les agents cloud les détectent et les exécutent au cours de leur travail.
Avec les forfaits Enterprise, les agents cloud exécutent également les hooks d'équipe et les hooks gérés par l'entreprise configurés via le tableau de bord web.
Les agents cloud démarrent parfois dans un environnement en lecture seule lors des premières interactions d'exploration. Les hooks ne s'exécutent pas durant ces interactions. Ils commencent à s'exécuter dès que l'agent dispose d'un environnement accessible en écriture.
Hooks pris en charge
Les hooks suivants sont exécutés dans les agents cloud :
| Hook | Pris en charge |
|---|---|
beforeShellExecution | Oui |
afterShellExecution | Oui |
beforeReadFile | Oui |
afterFileEdit | Oui |
preToolUse | Oui |
postToolUse | Oui |
postToolUseFailure | Oui |
subagentStart | Oui |
subagentStop | Oui |
beforeSubmitPrompt | Oui |
preCompact | Oui |
afterAgentResponse | Oui |
afterAgentThought | Oui |
stop | Oui |
Hooks non disponibles dans les agents cloud
Certains hooks ne s'appliquent pas aux agents cloud en raison de différences dans l'environnement d'exécution :
| Hook | Raison |
|---|---|
sessionStart | Différé, car les agents cloud peuvent démarrer dans un environnement en lecture seule. Les hooks n'y sont pas chargés : un sessionStart cloud se déclencherait donc trop tard (après la première écriture), et non au véritable début de la session. |
sessionEnd | Les agents cloud n'ont pas de limite de session liée à la durée de vie de l'Éditeur. sessionEnd est lié à la session de l'IDE, et non à un chat d'agent cloud. |
beforeMCPExecution / afterMCPExecution | Différés, car les agents cloud peuvent démarrer dans un environnement en lecture seule, où les hooks ne sont pas chargés et où le moment de déclenchement des hooks MCP n'est pas clairement défini. |
beforeTabFileRead / afterTabFileEdit | Les complétions Tab sont une fonctionnalité de l'IDE et ne s'exécutent pas dans les agents cloud. |
workspaceOpen | Il s'agit d'un hook de cycle de vie de l'IDE qui ne s'applique pas aux agents cloud. |
Sources de configuration
Les agents cloud chargent les hooks à partir des sources suivantes :
- Hooks de projet (
.cursor/hooks.jsondans votre dépôt) : chargés et exécutés lors du travail d’un agent cloud. - Hooks d’équipe (Enterprise) : distribués depuis le tableau de bord et exécutés dans les agents cloud.
- Hooks Enterprise (Enterprise) : hooks gérés à l’échelle du système et exécutés dans les agents cloud.
Les hooks au niveau utilisateur (~/.cursor/hooks.json) ne sont pas disponibles dans les agents cloud. Les VM d’agent cloud n’ont pas accès à la configuration de votre répertoire personnel local.
Limites des types d’exécution
Les agents cloud n’exécutent que des hooks basés sur des commandes. Les hooks basés sur des prompts nécessitent de relier l’authentification entre le hook et la boucle de l’agent, ce qui n’est pas possible dans l’environnement d’exécution cloud.
Démarrage rapide
Créez un fichier hooks.json au niveau du projet (<project>/.cursor/hooks.json) ou dans votre répertoire personnel (~/.cursor/hooks.json). Les hooks de projet s’appliquent uniquement à ce projet, tandis que les hooks du répertoire personnel s’appliquent globalement.
Pour créer des hooks utilisateur applicables globalement, créez ~/.cursor/hooks.json :
{ "version": 1, "hooks": { "afterFileEdit": [{ "command": "./hooks/format.sh" }] }}Créez votre script de hook dans ~/.cursor/hooks/format.sh :
#!/bin/bash# Lire l’entrée, effectuer une action, quitter avec le code 0cat > /dev/nullexit 0Rendez-le exécutable :
chmod +x ~/.cursor/hooks/format.shCursor surveille les fichiers de configuration des hooks et les recharge automatiquement. Votre hook s’exécute après chaque modification de fichier.
Types de hooks
Les hooks prennent en charge deux types d’exécution : par commande (par défaut) et par prompt (évaluée par le LLM).
Hooks basés sur des commandes
Les hooks de commande exécutent des scripts shell qui reçoivent des données JSON via stdin et renvoient des données JSON via stdout.
{ "hooks": { "beforeShellExecution": [ { "command": "./scripts/approve-network.sh", "timeout": 30, "matcher": "curl|wget|nc" } ] }}Comportement des codes de sortie :
- Code de sortie
0- Hook réussi, utiliser la sortie JSON - Code de sortie
2- Bloquer l’action (équivaut à renvoyerpermission: "deny") - Autres codes de sortie - Échec du hook, l’action se poursuit (ouvert par défaut en cas d’échec)
Hooks basés sur des prompts
Les hooks basés sur des prompts utilisent un LLM pour évaluer une condition en langage naturel. Ils permettent d’appliquer des politiques sans écrire de scripts personnalisés.
{ "hooks": { "beforeShellExecution": [ { "type": "prompt", "prompt": "Does this command look safe to execute? Only allow read-only operations.", "timeout": 10 } ] }}Fonctionnalités :
- Renvoie une réponse structurée
{ ok: boolean, reason?: string } - Utilise un modèle rapide pour une évaluation rapide
- L’espace réservé
$ARGUMENTSest automatiquement remplacé par le JSON d’entrée du hook - Si
$ARGUMENTSest absent, les données d’entrée du hook sont ajoutées automatiquement - Champ
modelfacultatif permettant de remplacer le modèle LLM par défaut
Exemples
Les exemples ci-dessous utilisent des chemins ./hooks/..., qui fonctionnent pour les hooks utilisateur (~/.cursor/hooks.json), les scripts étant exécutés depuis ~/.cursor/. Pour les hooks de projet (<project>/.cursor/hooks.json), utilisez plutôt des chemins .cursor/hooks/..., car les scripts sont exécutés depuis la racine du projet.
{ "version": 1, "hooks": { "sessionStart": [ { "command": "./hooks/session-init.sh" } ], "sessionEnd": [ { "command": "./hooks/audit.sh" } ], "beforeShellExecution": [ { "command": "./hooks/audit.sh" }, { "command": "./hooks/block-git.sh" } ], "beforeMCPExecution": [ { "command": "./hooks/audit.sh" } ], "afterShellExecution": [ { "command": "./hooks/audit.sh" } ], "afterMCPExecution": [ { "command": "./hooks/audit.sh" } ], "afterFileEdit": [ { "command": "./hooks/audit.sh" } ], "beforeSubmitPrompt": [ { "command": "./hooks/audit.sh" } ], "preCompact": [ { "command": "./hooks/audit.sh" } ], "stop": [ { "command": "./hooks/audit.sh" } ], "beforeTabFileRead": [ { "command": "./hooks/redact-secrets-tab.sh" } ], "afterTabFileEdit": [ { "command": "./hooks/format-tab.sh" } ] }}Hook d’automatisation stop en TypeScript
Choisissez TypeScript si vous avez besoin de JSON typé, d’E/S de fichiers persistantes et d’appels HTTP dans un même hook. Ce hook stop basé sur Bun enregistre sur disque le nombre d’échecs par conversation, transmet des données de télémétrie structurées à une API interne et peut automatiquement planifier une nouvelle tentative lorsque l’Agent échoue deux fois de suite.
{ "version": 1, "hooks": { "stop": [ { "command": "bun run .cursor/hooks/track-stop.ts --stop" } ] }}Définissez AGENT_TELEMETRY_URL sur l’endpoint interne qui doit recevoir les résumés d’exécution.
Hook de protection des manifestes Kubernetes en Python
Python est idéal lorsque vous avez besoin de bibliothèques d’analyse complètes. Ce hook utilise pyyaml pour inspecter les manifestes Kubernetes avant l’exécution de kubectl apply ; Bash aurait du mal à analyser de manière fiable des fichiers YAML comportant plusieurs documents.
{ "version": 1, "hooks": { "beforeShellExecution": [ { "command": "python3 .cursor/hooks/kube_guard.py" } ] }}Installez PyYAML (par exemple, pip install pyyaml) dans tous les environnements où vos scripts de hook s’exécutent afin que l’import du parseur fonctionne.
Intégrations partenaires
Nous collaborons avec des fournisseurs de l'écosystème qui ont intégré la prise en charge des hooks à Cursor. Ces intégrations couvrent l'analyse de sécurité, la gouvernance, la gestion des secrets et bien plus encore.
Gouvernance et visibilité des MCP
| Partenaire | Description |
|---|---|
| MintMCP | Créez un inventaire complet des serveurs MCP, surveillez l’utilisation des outils et analysez les réponses afin de détecter les données sensibles avant qu’elles n’atteignent le modèle d’IA. |
| Oasis Security | Appliquez la stratégie du moindre privilège aux actions des agents IA et conservez des pistes d’audit complètes dans l’ensemble des systèmes d’entreprise. |
| Runlayer | Encapsulez les outils MCP et intégrez-les à leur courtier MCP pour centraliser le contrôle et la visibilité des interactions entre agents et outils. |
Sécurité du code et bonnes pratiques
| Partenaire | Description |
|---|---|
| Corridor | Obtenez des retours en temps réel sur l’implémentation du code et les choix de conception en matière de sécurité, à mesure que le code est écrit. |
| Semgrep | Analysez automatiquement le code généré par l’IA afin d’y détecter des vulnérabilités, puis régénérez-le à l’aide de retours en temps réel jusqu’à la résolution des problèmes de sécurité. |
Sécurité des dépendances
| Partenaire | Description |
|---|---|
| Endor Labs | Interceptez les installations de paquets et analysez les dépendances malveillantes pour prévenir les attaques de la chaîne d’approvisionnement avant qu’elles n’atteignent votre base de code. |
Sécurité des agents
| Partenaire | Description |
|---|---|
| Snyk | Passez en revue en temps réel les actions des agents avec Evo Agent Guard, qui détecte et prévient les problèmes tels que les injections de prompt et les appels d’outils dangereux. |
Gestion des secrets
| Partenaire | Description |
|---|---|
| 1Password | Vérifiez que les fichiers d’environnement de 1Password Environments sont correctement montés avant l’exécution des commandes shell, afin d’accéder aux secrets au moment voulu sans écrire les identifiants sur le disque. |
Pour en savoir plus sur nos partenaires de hooks, consultez l’article de blog Hooks pour les équipes de sécurité et de plateforme.
Configuration
Définissez des hooks dans un fichier hooks.json. La configuration peut être définie à plusieurs niveaux. Tous les hooks correspondants de chaque source sont exécutés ; en cas de conflit entre les réponses, les sources prioritaires prévalent lors de la fusion :
~/.cursor/├── hooks.json└── hooks/ ├── audit.sh └── block-git.sh- Enterprise (géré par MDM, à l’échelle du système) :
- macOS :
/Library/Application Support/Cursor/hooks.json - Linux/WSL :
/etc/cursor/hooks.json - Windows :
C:\\ProgramData\\Cursor\\hooks.json
- macOS :
- Équipe (distribué via le Cloud, Enterprise uniquement) :
- Configuré dans le tableau de bord web et synchronisé automatiquement pour tous les membres de l’équipe
- Projet (spécifique au projet) :
<project-root>/.cursor/hooks.json- Les hooks de projet s’exécutent dans tout espace de travail approuvé et sont ajoutés au contrôle de version avec votre projet
- Utilisateur (spécifique à l’utilisateur) :
~/.cursor/hooks.json
Ordre de priorité (du plus élevé au plus faible) : Enterprise → Équipe → Projet → Utilisateur
L’objet hooks associe des noms de hooks à des tableaux de définitions de hooks. Chaque définition prend actuellement en charge une propriété command, qui peut être une chaîne de caractères shell, un chemin absolu ou un chemin relatif. Le répertoire de travail dépend de la source du hook :
- Hooks de projet (
.cursor/hooks.jsondans un dépôt) : s’exécutent depuis la racine du projet - Hooks utilisateur (
~/.cursor/hooks.json) : s’exécutent depuis~/.cursor/ - Hooks Enterprise (configuration à l’échelle du système) : s’exécutent depuis le répertoire de configuration Enterprise
- Hooks d’équipe (distribués via le Cloud) : s’exécutent depuis le répertoire des hooks gérés
Pour les hooks de projet, utilisez des chemins comme .cursor/hooks/script.sh (relatif à la racine du projet), et non ./hooks/script.sh (qui rechercherait <project>/hooks/script.sh).
Fichier de configuration
Cet exemple montre un fichier de hooks au niveau de l’utilisateur (~/.cursor/hooks.json). Pour les hooks au niveau du projet, remplacez les chemins tels que ./hooks/script.sh par .cursor/hooks/script.sh :
{ "version": 1, "hooks": { "sessionStart": [{ "command": "./session-init.sh" }], "sessionEnd": [{ "command": "./audit.sh" }], "preToolUse": [ { "command": "./hooks/validate-tool.sh", "matcher": "Shell|Read|Write" } ], "postToolUse": [{ "command": "./hooks/audit-tool.sh" }], "subagentStart": [{ "command": "./hooks/validate-subagent.sh" }], "subagentStop": [{ "command": "./hooks/audit-subagent.sh" }], "beforeShellExecution": [{ "command": "./script.sh" }], "afterShellExecution": [{ "command": "./script.sh" }], "afterMCPExecution": [{ "command": "./script.sh" }], "afterFileEdit": [{ "command": "./format.sh" }], "preCompact": [{ "command": "./audit.sh" }], "stop": [{ "command": "./audit.sh", "loop_limit": 10 }], "beforeTabFileRead": [{ "command": "./redact-secrets-tab.sh" }], "afterTabFileEdit": [{ "command": "./format-tab.sh" }], "workspaceOpen": [{ "command": "./register-workspace-plugins.sh" }] }}Les hooks d’agent (sessionStart, sessionEnd, preToolUse, postToolUse, postToolUseFailure, subagentStart, subagentStop, beforeShellExecution, afterShellExecution, beforeMCPExecution, afterMCPExecution, beforeReadFile, afterFileEdit, beforeSubmitPrompt, preCompact, stop, afterAgentResponse, afterAgentThought) s’appliquent aux opérations Cmd+K et Agent Chat. Les hooks Tab (beforeTabFileRead, afterTabFileEdit) s’appliquent spécifiquement aux complétions Tab en ligne. Le hook de cycle de vie de l’application (workspaceOpen) se déclenche à l’ouverture d’un espace de travail et lors de la modification des dossiers de l’espace de travail, indépendamment de toute session d’agent.
Options de configuration globales
| Option | Type | Par défaut | Description |
|---|---|---|---|
version | number | 1 | Version du schéma de configuration |
Options de configuration par script
| Option | Type | Par défaut | Description |
|---|---|---|---|
command | string | requis | Chemin du script ou commande |
type | "command" | "prompt" | "command" |
timeout | number | valeur par défaut de la plateforme | Délai d'exécution en secondes |
loop_limit | number | null | 5 |
failClosed | boolean | false | Lorsque true, les échecs du hook (plantage, expiration du délai, JSON non valide) bloquent l'action au lieu de l'autoriser. Utile pour les hooks critiques en matière de sécurité. |
matcher | object | - | Critères déterminant quand le hook s'exécute |
Configuration du matcher
Les matchers permettent de définir quand un hook s’exécute. Le champ auquel s’applique le matcher dépend du hook :
{ "hooks": { "preToolUse": [ { "command": "./validate-shell.sh", "matcher": "Shell" } ], "subagentStart": [ { "command": "./validate-explore.sh", "matcher": "explore|shell" } ], "beforeShellExecution": [ { "command": "./approve-network.sh", "matcher": "curl|wget|nc " } ] }}- subagentStart : Le matcher s’applique au type de sous-agent (p. ex.
explore,shell,generalPurpose). Utilisez-le pour n’exécuter des hooks que lorsqu’un type spécifique de sous-agent démarre. L’exemple ci-dessus exécutevalidate-explore.shuniquement pour les sous-agents explore ou shell. - beforeShellExecution : Le matcher s’applique à la chaîne de caractères de la commande shell. Utilisez-le pour n’exécuter des hooks que lorsque la commande correspond à un pattern (p. ex. appels réseau, suppressions de fichiers). L’exemple ci-dessus exécute
approve-network.shuniquement lorsque la commande contientcurl,wgetounc.
Matchers disponibles par hook :
- preToolUse / postToolUse / postToolUseFailure : Filtrez par type d’outil. Les valeurs incluent
Shell,Read,Write,Grep,Delete,Tasket les outils MCP au formatMCP:<tool_name>. - subagentStart / subagentStop : Filtrez par type de sous-agent (
generalPurpose,explore,shell, etc.). - beforeShellExecution / afterShellExecution : Filtrez par texte de commande shell ; le matcher s’applique à l’intégralité de la chaîne de commande.
- beforeReadFile : Filtrez par type d’outil (
TabRead,Read, etc.). - afterFileEdit : Filtrez par type d’outil (
TabWrite,Write, etc.). - beforeSubmitPrompt : Correspond à la valeur
UserPromptSubmit. - stop : Correspond à la valeur
Stop. - afterAgentResponse : Correspond à la valeur
AgentResponse. - afterAgentThought : Correspond à la valeur
AgentThought.
Distribution au sein de l’équipe
Les hooks peuvent être distribués aux membres de l’équipe via des hooks de projet (par contrôle de version), des outils MDM ou le système de distribution cloud de Cursor.
Hooks de projet (contrôle de version)
Les hooks de projet constituent le moyen le plus simple de partager des hooks avec votre équipe. Placez un fichier hooks.json dans <project-root>/.cursor/hooks.json et validez-le dans votre dépôt. Lorsque les membres de l’équipe ouvrent le projet dans un espace de travail approuvé, Cursor charge et exécute automatiquement les hooks de projet.
Les agents cloud chargent également ces hooks de projet lorsqu’ils travaillent sur votre dépôt dans le cloud.
Les hooks de projet :
- Sont stockés dans le contrôle de version avec votre code
- Sont automatiquement chargés pour tous les membres de l’équipe dans les espaces de travail approuvés
- Peuvent être spécifiques au projet (par exemple, imposer des normes de formatage pour une base de code donnée)
- Nécessitent que l’espace de travail soit approuvé pour pouvoir s’exécuter (pour des raisons de sécurité)
Distribution via MDM
Distribuez des hooks au sein de votre organisation à l’aide d’outils de gestion des appareils mobiles (MDM). Placez le fichier hooks.json et les scripts de hook dans les répertoires cibles de chaque machine.
Répertoire personnel de l’utilisateur (distribution par utilisateur) :
~/.cursor/hooks.json~/.cursor/hooks/(pour les scripts de hook)
Répertoires globaux (distribution à l’échelle du système) :
- macOS :
/Library/Application Support/Cursor/hooks.json - Linux/WSL :
/etc/cursor/hooks.json - Windows :
C:\\ProgramData\\Cursor\\hooks.json
Remarque : la distribution via MDM est entièrement gérée par votre organisation. Cursor ne déploie ni ne gère les fichiers via votre solution MDM. Veillez à ce que votre équipe informatique ou de sécurité interne gère la configuration, le déploiement et les mises à jour conformément aux stratégies de votre organisation.
Distribution cloud (Enterprise uniquement)
Les équipes Enterprise peuvent utiliser la distribution cloud native de Cursor pour synchroniser automatiquement les hooks sur les machines de tous les membres de l’équipe. Configurez les hooks dans le tableau de bord web. Cursor distribue automatiquement les hooks configurés sur toutes les machines clientes lorsque les membres de l’équipe se connectent.
La distribution cloud offre :
- Une synchronisation automatique pour tous les membres de l’équipe (toutes les trente minutes)
- Un ciblage par système d’exploitation pour les hooks spécifiques à une plateforme
- Une gestion centralisée via le tableau de bord
Les administrateurs Enterprise peuvent créer, modifier et gérer les hooks d’équipe depuis le tableau de bord, sans avoir besoin d’accéder aux machines individuelles.
Contacter le service commercial pour bénéficier de la distribution cloud de hooks Enterprise.
Référence
Schéma commun
Entrée (tous les hooks)
Tous les hooks reçoivent un ensemble de champs de base, en plus de leurs champs spécifiques :
{ "conversation_id": "string", "generation_id": "string", "model": "string", "model_id": "string", "model_params": [{ "id": "string", "value": "string" }], "hook_event_name": "string", "cursor_version": "string", "workspace_roots": ["<path>"], "user_email": "string | null", "transcript_path": "string | null"}| Champ | Type | Description | |
|---|---|---|---|
conversation_id | string | ID stable de la conversation sur plusieurs tours | |
generation_id | string | Génération actuelle, qui change à chaque message utilisateur | |
model | string | Slug de l'ancien modèle configuré pour le composer ayant déclenché le hook | |
model_id | string (optional) | ID structuré du modèle sélectionné, lorsqu'il est disponible | |
model_params | array (optional) | Paramètres du modèle sélectionné, tels que la réflexion, le contexte ou l'effort. Chaque élément possède un id et une value. | |
hook_event_name | string | Hook en cours d'exécution | |
cursor_version | string | Version de l'application Cursor (p. ex. "1.7.2") | |
workspace_roots | string[] | Liste des dossiers racine de l'espace de travail (généralement un seul, mais les espaces de travail à plusieurs racines peuvent en avoir plusieurs) | |
user_email | string | null | Adresse e-mail de l'utilisateur authentifié, si disponible |
transcript_path | string | null | Chemin vers le fichier de transcription de la conversation principale (null si les transcriptions sont désactivées) |
Les hooks de cycle de vie de l'application (workspaceOpen) se déclenchent en dehors de toute session d'agent ; la requête omet donc conversation_id, generation_id, model, session_id et transcript_path. Ils reçoivent néanmoins hook_event_name, cursor_version, workspace_roots et user_email.
Événements des hooks
preToolUse
Appelé avant toute exécution d’outil. Ce hook générique se déclenche pour tous les types d’outils (Shell, Read, Write, MCP, Task, etc.). Utilisez des matchers pour filtrer des outils spécifiques.
// Entrée{ "tool_name": "Shell", "tool_input": { "command": "npm install", "working_directory": "/project" }, "tool_use_id": "abc123", "cwd": "/project", "model": "claude-opus-4-7-thinking-max", "model_id": "claude-opus-4-7", "model_params": [ { "id": "thinking", "value": "true" }, { "id": "context", "value": "1m" }, { "id": "effort", "value": "max" } ], "agent_message": "Installing dependencies..."}// Sortie{ "permission": "allow" | "deny", "user_message": "<message shown in client when denied>", "agent_message": "<message sent to agent when denied>", "updated_input": { "command": "npm ci" }}| Champ de sortie | Type | Description |
|---|---|---|
permission | chaîne | "allow" pour autoriser la poursuite, "deny" pour bloquer. "ask" est accepté par le schéma, mais n'est pas appliqué pour preToolUse à ce jour. |
user_message | chaîne (facultatif) | Message affiché à l'utilisateur lorsque l'action est refusée |
agent_message | chaîne (facultatif) | Message renvoyé à l'agent lorsque l'action est refusée |
updated_input | objet (facultatif) | Entrée d'outil modifiée à utiliser à la place |
postToolUse
Appelé après l’exécution réussie d’un outil. Utile pour l’audit, l’analyse et l’ajout de contexte.
// Entrée{ "tool_name": "Shell", "tool_input": { "command": "npm test" }, "tool_output": "{\"exitCode\":0,\"stdout\":\"All tests passed\"}", "tool_use_id": "abc123", "cwd": "/project", "duration": 5432, "model": "claude-opus-4-7-thinking-max", "model_id": "claude-opus-4-7", "model_params": [ { "id": "thinking", "value": "true" }, { "id": "context", "value": "1m" }, { "id": "effort", "value": "max" } ]}// Sortie{ "updated_mcp_tool_output": { "modified": "output" }, "additional_context": "Test coverage report attached."}| Champ d’entrée | Type | Description |
|---|---|---|
duration | number | Durée d’exécution en millisecondes |
tool_output | string | Payload de résultat de l’outil sérialisé en chaîne JSON (et non texte brut du terminal) |
| Champ de sortie | Type | Description |
|---|---|---|
updated_mcp_tool_output | object (optional) | Réservé aux outils MCP : remplace la sortie de l’outil visible par le modèle |
additional_context | string (optional) | Contexte supplémentaire injecté dans la conversation après le résultat de l’outil |
postToolUseFailure
Appelé lorsqu’un outil échoue, expire ou est refusé. Utile pour le suivi des erreurs et la logique de reprise.
// Entrée{ "tool_name": "Shell", "tool_input": { "command": "npm test" }, "tool_use_id": "abc123", "cwd": "/project", "error_message": "Command timed out after 30s", "failure_type": "timeout" | "error" | "permission_denied", "duration": 5000, "is_interrupt": false}// Sortie{ // Aucun champ de sortie n’est actuellement pris en charge}| Champ d’entrée | Type | Description |
|---|---|---|
error_message | string | Description de l’erreur |
failure_type | string | Type d’erreur : "error", "timeout" ou "permission_denied" |
duration | number | Temps écoulé en millisecondes avant l’erreur |
is_interrupt | boolean | Indique si cette erreur a été causée par une interruption ou une annulation par l’utilisateur |
subagentStart
Appelé avant la création d’un sous-agent (outil Task). Peut autoriser ou refuser sa création.
// Entrée{ "subagent_id": "abc-123", "subagent_type": "generalPurpose", "task": "Explore the authentication flow", "parent_conversation_id": "conv-456", "tool_call_id": "tc-789", "subagent_model": "claude-sonnet-4-20250514", "is_parallel_worker": false, "git_branch": "feature/auth"}// Sortie{ "permission": "allow" | "deny", "user_message": "<message shown when denied>"}| Champ d’entrée | Type | Description |
|---|---|---|
subagent_id | string | Identifiant unique de cette instance de sous-agent |
subagent_type | string | Type de sous-agent : generalPurpose, explore, shell, etc. |
task | string | Description de la tâche confiée au sous-agent |
parent_conversation_id | string | ID de conversation de la session de l’agent parent |
tool_call_id | string | ID de l’appel d’outil ayant déclenché le sous-agent |
subagent_model | string | Modèle utilisé par le sous-agent |
is_parallel_worker | boolean | Indique si ce sous-agent s’exécute en tant que processus parallèle |
git_branch | string (facultatif) | Branche Git sur laquelle le sous-agent opérera, le cas échéant |
| Champ de sortie | Type | Description |
|---|---|---|
permission | string | "allow" pour autoriser, "deny" pour bloquer. "ask" n’est pas pris en charge pour subagentStart et est traité comme "deny". |
user_message | string (facultatif) | Message affiché à l’utilisateur lorsque le sous-agent est bloqué |
subagentStop
Appelé lorsqu’un sous-agent termine son exécution, rencontre une erreur ou est interrompu. Peut déclencher des actions de suivi.
// Entrée{ "subagent_type": "generalPurpose", "status": "completed" | "error" | "aborted", "task": "Explore the authentication flow", "description": "Exploring auth flow", "summary": "<subagent output summary>", "duration_ms": 45000, "message_count": 12, "tool_call_count": 8, "loop_count": 0, "modified_files": ["src/auth.ts"], "agent_transcript_path": "/path/to/subagent/transcript.txt"}// Sortie{ "followup_message": "<auto-continue with this message>"}| Champ d’entrée | Type | Description | |
|---|---|---|---|
subagent_type | string | Type de sous-agent : generalPurpose, explore, shell, etc. | |
status | string | "completed", "error" ou "aborted" | |
task | string | Description de la tâche confiée au sous-agent | |
description | string | Brève description du rôle du sous-agent | |
summary | string | Résumé de la sortie du sous-agent | |
duration_ms | number | Temps d’exécution en millisecondes | |
message_count | number | Nombre de messages échangés durant la session du sous-agent | |
tool_call_count | number | Nombre d’appels d’outils effectués par le sous-agent | |
loop_count | number | Nombre de fois qu’un message de suivi subagentStop a déjà été déclenché pour ce sous-agent (à partir de 0) | |
modified_files | string[] | Fichiers modifiés par le sous-agent | |
agent_transcript_path | string | null | Chemin vers le fichier de transcription propre au sous-agent (distinct de la conversation parente) |
| Champ de sortie | Type | Description |
|---|---|---|
followup_message | string (facultatif) | Continuer automatiquement avec ce message. Utilisé uniquement lorsque status vaut "completed". |
Le champ followup_message permet des flux en boucle où la finalisation d’un sous-agent déclenche l’itération suivante. Les messages de suivi sont soumis à la même limite de boucle configurable que le hook stop (5 par défaut, configurable via loop_limit).
beforeShellExecution / beforeMCPExecution
Appelé avant l’exécution d’une commande shell ou d’un outil MCP. Renvoyez une décision d’autorisation.
Par défaut, en cas d’échec du hook (plantage, délai d’expiration, JSON non valide), l’action est autorisée (échec ouvert). Définissez failClosed: true dans la définition du hook pour bloquer l’action en cas d’échec. Cette option est recommandée pour les hooks beforeMCPExecution critiques pour la sécurité.
// entrée de beforeShellExecution{ "command": "<full terminal command>", "cwd": "<current working directory>", "sandbox": false}// entrée de beforeMCPExecution{ "tool_name": "<tool name>", "tool_input": "<json params>"}// Plus l’un des champs suivants :{ "url": "<server url>" }// Ou :{ "command": "<command string>" }// Sortie{ "permission": "allow" | "deny" | "ask", "user_message": "<message shown in client>", "agent_message": "<message sent to agent>"}afterShellExecution
Se déclenche après l’exécution d’une commande shell ; utile pour l’audit ou la collecte de métriques à partir de la sortie de la commande.
// Entrée{ "command": "<full terminal command>", "output": "<full terminal output>", "duration": 1234, "sandbox": false}| Champ | Type | Description |
|---|---|---|
command | string | Commande complète exécutée dans le terminal |
output | string | Sortie complète capturée dans le terminal |
duration | number | Durée d'exécution de la commande shell en millisecondes (hors temps d'attente d'approbation) |
sandbox | boolean | Indique si la commande a été exécutée dans un environnement sandboxé |
afterMCPExecution
Se déclenche après l’exécution d’un outil MCP ; inclut les paramètres d’entrée de l’outil et le résultat JSON complet.
// Entrée{ "tool_name": "<tool name>", "tool_input": "<json params>", "result_json": "<tool result json>", "duration": 1234}| Champ | Type | Description |
|---|---|---|
tool_name | string | Nom de l’outil MCP exécuté |
tool_input | string | Chaîne de paramètres JSON transmise à l’outil |
result_json | string | Chaîne JSON de la réponse de l’outil |
duration | number | Durée d’exécution de l’outil MCP, en millisecondes (hors délai d’attente d’approbation) |
afterFileEdit
Se déclenche après qu’un Agent a modifié un fichier ; utile pour les outils de formatage ou pour comptabiliser le code écrit par l’Agent.
// Entrée{ "file_path": "<absolute path>", "edits": [{ "old_string": "<search>", "new_string": "<replace>" }]}beforeReadFile
Appelé avant que l’Agent ne lise un fichier. Permet de contrôler l’accès afin d’empêcher l’envoi de fichiers sensibles au modèle.
Par défaut, les échecs du hook beforeReadFile (plantage, délai d’expiration, JSON non valide) sont consignés et la lecture est autorisée. Définissez failClosed: true dans la définition du hook pour bloquer la lecture en cas d’échec.
// Entrée{ "file_path": "<absolute path>", "content": "<file contents>", "attachments": [ { "type": "file" | "rule", "file_path": "<absolute path>" } ]}// Sortie{ "permission": "allow" | "deny", "user_message": "<message shown when denied>"}| Champ d’entrée | Type | Description |
|---|---|---|
file_path | string | Chemin absolu du fichier en cours de lecture |
content | string | Contenu complet du fichier |
attachments | array | Pièces jointes de contexte associées au prompt. Chaque entrée comporte un type ("file" ou "rule") et un file_path. |
| Champ de sortie | Type | Description |
|---|---|---|
permission | string | "allow" pour autoriser, "deny" pour bloquer |
user_message | string (facultatif) | Message affiché à l’utilisateur en cas de refus |
beforeTabFileRead
Appelé avant que Tab (complétions en ligne) ne lise un fichier. Activez la rédaction ou le contrôle d’accès avant que Tab n’accède au contenu du fichier.
Principales différences avec beforeReadFile :
- Déclenché uniquement par Tab, et non par l’Agent
- N’inclut pas le champ
attachments(Tab n’utilise pas de pièces jointes dans les prompts) - Utile pour appliquer des stratégies différentes aux opérations autonomes de Tab
// Entrée{ "file_path": "<absolute path>", "content": "<file contents>"}// Sortie{ "permission": "allow" | "deny"}afterTabFileEdit
Appelé après qu’une complétion Tab (en ligne) a modifié un fichier. Utile pour les outils de formatage ou l’audit du code écrit par Tab.
Différences clés par rapport à afterFileEdit :
- Déclenché uniquement par Tab, et non par un Agent
- Inclut des informations détaillées sur la modification :
range,old_lineetnew_line, pour un suivi précis des modifications - Utile pour le formatage ou l’analyse détaillée des modifications de Tab
// Entrée{ "file_path": "<absolute path>", "edits": [ { "old_string": "<search>", "new_string": "<replace>", "range": { "start_line_number": 10, "start_column": 5, "end_line_number": 10, "end_column": 20 }, "old_line": "<line before edit>", "new_line": "<line after edit>" } ]}// Sortie{ // Aucun champ de sortie n’est actuellement pris en charge}beforeSubmitPrompt
Appelé juste après que l’utilisateur a envoyé sa requête, mais avant la requête au backend. Peut empêcher l’envoi.
// Entrée{ "prompt": "<texte de l'invite utilisateur>", "attachments": [ { "type": "file" | "rule", "file_path": "<chemin absolu>" } ]}// Sortie{ "continue": true | false, "user_message": "<message affiché à l'utilisateur lorsqu'il est bloqué>"}| Champ de sortie | Type | Description |
|---|---|---|
continue | boolean | Indique si l'envoi du prompt est autorisé à se poursuivre |
user_message | string (optional) | Message affiché à l'utilisateur lorsque le prompt est bloqué |
afterAgentResponse
Appelé une fois que l’agent a terminé un message de l’assistant.
// Entrée{ "text": "<assistant final text>"}afterAgentThought
Appelé lorsque l’agent a terminé un bloc de réflexion. Utile pour observer le raisonnement de l’agent.
// Entrée{ "text": "<fully aggregated thinking text>", "duration_ms": 5000}// Sortie{ // Aucun champ de sortie n’est actuellement pris en charge}| Champ | Type | Description |
|---|---|---|
text | string | Texte de réflexion agrégé du bloc terminé |
duration_ms | number (optional) | Durée du bloc de réflexion, en millisecondes |
stop
Appelé à la fin de la boucle de l’agent. Peut éventuellement envoyer automatiquement un message de suivi de l’utilisateur pour poursuivre l’itération.
// Entrée{ "status": "completed" | "aborted" | "error", "loop_count": 0}// Sortie{ "followup_message": "<message text>"}- Le paramètre facultatif
followup_messageest une chaîne de caractères. Lorsqu’il est renseigné et non vide, Cursor l’envoie automatiquement comme prochain message utilisateur. Cela permet des flux en boucle (p. ex., itérer jusqu’à ce qu’un objectif soit atteint). - Le champ
loop_countindique le nombre de fois où le hook stop a déjà déclenché un message de suivi automatique pour cette conversation (commence à 0). La limite par défaut est de 5 messages de suivi automatiques par script, configurable via l’optionloop_limit. Définissezloop_limitsurnullpour supprimer cette limite. La même limite s’applique aux messages de suivisubagentStop.
sessionStart
Appelé lorsqu’une nouvelle conversation dans composer est créée. Ce hook s’exécute en mode fire-and-forget ; la boucle de l’Agent n’attend pas de réponse bloquante et ne l’impose pas. Utilisez-le pour configurer des variables d’environnement propres à la session ou injecter du contexte supplémentaire.
// Entrée{ "session_id": "<unique session identifier>", "is_background_agent": true | false, "composer_mode": "agent" | "ask" | "edit"}// Sortie{ "env": { "<key>": "<value>" }, "additional_context": "<context to add to conversation>"}| Champ d’entrée | Type | Description |
|---|---|---|
session_id | string | Identifiant unique de cette session (identique à conversation_id) |
is_background_agent | boolean | Indique s’il s’agit d’une session d’Agent en arrière-plan ou d’une session interactive |
composer_mode | string (facultatif) | Mode dans lequel composer démarre (p. ex., "agent", "ask", "edit") |
| Champ de sortie | Type | Description |
|---|---|---|
env | object (facultatif) | Variables d’environnement à définir pour cette session. Disponibles pour toutes les exécutions de hooks ultérieures |
additional_context | string (facultatif) | Contexte supplémentaire à ajouter au contexte système initial de la conversation |
Le schéma accepte également les champs continue et user_message, mais les appelants actuels ne les imposent pas. La création de la session n’est pas bloquée, même lorsque continue est défini sur false.
sessionEnd
Appelé à la fin d’une conversation composer. Ce hook fire-and-forget est utile pour les tâches de journalisation, d’analyse ou de nettoyage. La réponse est journalisée, mais n’est pas utilisée.
// Entrée{ "session_id": "<identifiant de session unique>", "reason": "completed" | "aborted" | "error" | "window_close" | "user_close", "duration_ms": 45000, "is_background_agent": true | false, "final_status": "<chaîne d'état>", "error_message": "<détails de l'erreur si reason est 'error'>"}// Sortie{ // Aucun champ de sortie ; exécution sans attente de réponse}| Champ d’entrée | Type | Description |
|---|---|---|
session_id | string | Identifiant unique de la session qui se termine |
reason | string | Manière dont la session s’est terminée : "completed", "aborted", "error", "window_close" ou "user_close" |
duration_ms | number | Durée totale de la session en millisecondes |
is_background_agent | boolean | Indique s’il s’agissait d’une session d’agent en arrière-plan |
final_status | string | Statut final de la session |
error_message | string (optional) | Message d’erreur si la raison est "error" |
preCompact
Appelé avant la compaction ou la synthèse de la fenêtre de contexte. Ce hook d’observation ne peut ni bloquer ni modifier le comportement de compaction. Utile pour consigner les opérations de compaction ou en informer les utilisateurs.
// Entrée{ "trigger": "auto" | "manual", "context_usage_percent": 85, "context_tokens": 120000, "context_window_size": 128000, "message_count": 45, "messages_to_compact": 30, "is_first_compaction": true | false}// Sortie{ "user_message": "<message to show when compaction occurs>"}| Champ d’entrée | Type | Description |
|---|---|---|
trigger | string | Élément ayant déclenché la compaction : "auto" ou "manual" |
context_usage_percent | number | Utilisation actuelle de la fenêtre de contexte, en pourcentage (0-100) |
context_tokens | number | Nombre actuel de tokens dans la fenêtre de contexte |
context_window_size | number | Taille maximale de la fenêtre de contexte en tokens |
message_count | number | Nombre de messages dans la conversation |
messages_to_compact | number | Nombre de messages qui seront résumés |
is_first_compaction | boolean | Indique s’il s’agit de la première compaction de cette conversation |
| Champ de sortie | Type | Description |
|---|---|---|
user_message | string (optional) | Message à afficher à l’utilisateur lors d’une compaction |
workspaceOpen
Se déclenche à l’ouverture d’un espace de travail par Cursor, puis à chaque modification d’un dossier de l’espace de travail. Ignoré lorsque la fenêtre ne contient aucun dossier d’espace de travail. S’exécute dans l’application de bureau Cursor et la CLI.
// Entrée{ "hook_event_name": "workspaceOpen", "cursor_version": "string", "workspace_roots": ["<absolute path>"], "user_email": "string | null"}// Sortie{ "pluginPaths": ["<absolute path>", "..."]}| Champ de sortie | Type | Description |
|---|---|---|
pluginPaths | string[] (facultatif) | Chemins absolus des répertoires de plugins à charger pour l’espace de travail actuel. |
Variables d’environnement
Les scripts de hook reçoivent des variables d’environnement lors de leur exécution :
| Variable | Description | Toujours présente |
|---|---|---|
CURSOR_PROJECT_DIR | Répertoire racine de l’espace de travail | Oui |
CURSOR_VERSION | Chaîne de version de Cursor | Oui |
CURSOR_USER_EMAIL | Adresse e-mail de l’utilisateur authentifié | Si connecté |
CURSOR_TRANSCRIPT_PATH | Chemin du fichier de transcription de la conversation | Si les transcriptions sont activées |
CURSOR_CODE_REMOTE | Défini sur la chaîne "true" lors de l’exécution dans un espace de travail distant | Pour les espaces de travail distants |
CLAUDE_PROJECT_DIR | Alias du répertoire du projet (compatibilité avec Claude) | Oui |
Les variables d’environnement définies par les hooks sessionStart et limitées à la session sont transmises à toutes les exécutions de hook suivantes au cours de cette session.
Dépannage
Comment vérifier que les hooks sont actifs
Un onglet Hooks est disponible dans Personnaliser, ainsi qu’un canal de sortie Hooks permettant de déboguer les hooks configurés et exécutés et d’afficher les erreurs.
Si les hooks ne fonctionnent pas
- Cursor surveille les fichiers
hooks.jsonet les recharge à l’enregistrement. Si les hooks ne se chargent toujours pas, redémarrez Cursor. - Vérifiez que les chemins relatifs sont corrects pour la source de votre hook :
- Pour les hooks de projet, les chemins sont relatifs à la racine du projet (par ex.,
.cursor/hooks/script.sh) - Pour les hooks utilisateur, les chemins sont relatifs à
~/.cursor/(par ex.,./hooks/script.shouhooks/script.sh)
- Pour les hooks de projet, les chemins sont relatifs à la racine du projet (par ex.,
Blocage par code de sortie
Le code de sortie 2 des hooks de commande bloque l’action (ce qui équivaut à renvoyer permission: "deny"). Ce comportement est conforme à celui de Claude Code, par souci de compatibilité.
Hooks Enterprise et distribution
La distribution Cloud et la gestion des hooks à l’échelle de l’équipe sont disponibles avec Enterprise.