Obtenir AX Code · GratuitDocumentation

Cette page est traduite de la documentation anglaise. Les commandes, identifiants et exemples sont inchangés. Runtime 7.24.4 · SDK 2.6.7. Source anglaise

Hooks du cycle de vie

Statut : Actif
Portée : état actuel
Dernière revue : 2026-08-23 Responsable : runtime ax-code

Les hooks du cycle de vie permettent d’exécuter des commandes shell sur les événements de l’agent sans reconstruire le runtime. Ils complètent les règles de permission et le bac à sable d’isolation : les hooks sont des effets de bord déterministes (« toujours formater », « jamais de force-push »), tandis que les invites restent consultatives.

Événements

Événement Moment Peut bloquer ?
PreToolUse Avant l’exécution d’un outil Oui (blockOnFailure: true)
PostToolUse Après l’achèvement d’un outil (args : les arguments de l’outil). La sortie standard bornée ou le retour structuré est ajouté au résultat d’outil vu par le modèle ; voir plus bas Non
PostToolUseFailure Après qu’un outil a levé une erreur (args : { args, error }, texte d’erreur plafonné à 4,000 caractères). Émission sans attente ; l’erreur atteint encore le modèle inchangée Non
Stop Lorsqu’un tour de session s’achève (les paquets peuvent s’exécuter à l’arrêt via l’automatisation) Non
UserPromptSubmit Lorsqu’une invite utilisateur est soumise, avant la persistance du message Oui (blockOnFailure: true)
PreCompact Avant l’exécution du compactage de session (args : { auto, overflow }) Non
SubagentStop Lorsqu’un sous-agent task se termine (args : { agent, status }) Non
SessionStart Lorsqu’une session de premier niveau est créée (args : { sessionID, title, time }) Non
SessionEnd Lorsqu’une session est retirée ou archivée (args : { sessionID, reason }, reason vaut "remove" ou "archive") Non
PostCompact Après qu’un compactage de session s’est achevé avec succès (args : { sessionID, reason }, reason vaut "auto" ou "manual" ; non émis lorsque le compactage abandonne, par exemple en cas de débordement de contexte) Non
Interrupt Lorsqu’un utilisateur ou un opérateur annule explicitement un tour en cours (args : { sessionID } ; non émis à l’achèvement normal d’un tour ni lors du nettoyage interne) Non

Les quatre événements de cycle de vie de session (SessionStart, SessionEnd, PostCompact, Interrupt) et PostToolUseFailure sont seulement observateurs : ils s’émettent sans attente, ne bloquent jamais le chemin du cycle de vie, et leurs charges ne portent que des identifiants, des raisons et des horodatages — jamais le texte de conversation, les résumés ou la sortie d’outil. Les sessions de sous-agent n’émettent pas SessionStart (elles apparaissent déjà via SubagentStop). SubagentStop s’émet pour les enfants démarrés à la fois par task et par task_parallel.

Le retour PostToolUse atteint le modèle

Un hook PostToolUse peut renvoyer du texte au modèle. Il est ajouté au résultat d’outil dans un bloc <hook_feedback event="PostToolUse">, après la sortie propre de l’outil ; il ne remplace jamais la sortie et ne bloque jamais.

  • Entrées héritées (sans protocol) : sortie standard tronquée d’un hook qui s’est terminé avec le code 0.
  • Entrées protocol: "claude-code" : hookSpecificOutput.additionalContext, le reason d’un verdict {"decision": "block", "reason": "..."}, ou stderr lorsque le hook se termine avec le code 2. Les autres codes non nuls ne contribuent rien.

Le retour est plafonné à 4,000 caractères par hook et à 8,000 caractères par appel d’outil, afin qu’un hook bruyant ne puisse pas inonder le contexte. C’est ce qui rend le paquet format-after-edit utile : son rappel arrive désormais dans le tour suivant du modèle au lieu de rester seulement dans le journal.

Ces noms correspondent aux déclencheurs internes de plugins d’AX Code (tool.execute.before / tool.execute.after), plus les hooks d’invite, de compactage, de sous-agent et d’arrêt au niveau de la session. Les invites de continuation synthétiques (invites internes agentRouting: "preserve") n’émettent pas UserPromptSubmit.

Activer les paquets

Les hooks et plugins de projet exécutent du code contrôlé par le dépôt, donc .ax-code/hooks.json, .ax-code/plugin/ et les plugins configurés par le projet sont désactivés par défaut. Après les avoir examinés, activez-les hors du dépôt au démarrage d’AX Code :

AX_CODE_TRUST_PROJECT_CONFIG=1 ax-code

Puis créez .ax-code/hooks.json dans votre projet :

{
  "packs": ["format-after-edit", "block-force-push", "require-tests-on-stop", "protect-env-files", "log-bash-commands"]
}

Paquets officiels (≥5)

Paquet Événements Description
format-after-edit PostToolUse Rappelle à l’agent de formater après les modifications
block-force-push PreToolUse Bloque git push --force / -f
require-tests-on-stop Stop Rappelle de vérifier après les mutations
protect-env-files PreToolUse Avertit lorsque des outils touchent .env
log-bash-commands PreToolUse Journalise les commandes bash pour l’audit

Hooks personnalisés :

{
  "hooks": [
    {
      "event": "PreToolUse",
      "matcher": "bash",
      "command": "echo running bash",
      "blockOnFailure": false
    }
  ]
}

Protocole de liaison Claude Code (activation explicite)

Si vous avez déjà des hooks écrits pour Claude Code, une entrée peut adopter le protocole de liaison Claude Code avec "protocol": "claude-code" :

{
  "hooks": [
    {
      "event": "PreToolUse",
      "matcher": "bash",
      "command": "my-claude-code-hook.sh",
      "protocol": "claude-code"
    }
  ]
}

Pour les événements bloquants (PreToolUse, UserPromptSubmit), les entrées activées sont décodées avec la sémantique Claude Code à la place du contrôle blockOnFailure :

  • Code de sortie 2 bloque l’action ; le stderr du hook est présenté comme la raison. Une sortie standard mal formée bloque encore (sécurité par défaut).
  • Code de sortie 0 avec un JSON de sortie standard {"permissionDecision": "allow"|"deny"|"ask", "reason"?} : allow poursuit ; deny bloque avec reason ; ask met l’appel d’outil en pause sur une invite de permission interactive hook qui montre la raison (défaut "hook requested user confirmation"). L’invite est seulement interactive : aucune règle always, aucun octroi par joker ni aucune approbation automatique du mode autonome ne peut y répondre, et une exécution sans interface la rejette, ce que le modèle voit comme un rejet de permission ordinaire. Un hook ultérieur qui répond deny l’emporte sur un ask antérieur. UserPromptSubmit n’a pas d’appel d’outil auquel attacher une invite, donc ask bloque encore là. La forme imbriquée Claude Code {"hookSpecificOutput": {"permissionDecision": "...", "permissionDecisionReason": "..."}} est acceptée comme alias.
  • Tout autre code de sortie est une erreur non bloquante (journalisée, l’action continue).

Les événements seulement observateurs ignorent entièrement le décodeur — ils ne peuvent jamais bloquer. Les entrées sans le champ protocol se comportent exactement comme avant.

Variables d’environnement disponibles pour les commandes de hook :

  • HOOK_EVENT — PreToolUse, PostToolUse, PostToolUseFailure, Stop, UserPromptSubmit, PreCompact, SubagentStop, SessionStart, SessionEnd, PostCompact et Interrupt
  • HOOK_TOOL — identifiant d’outil
  • HOOK_SESSION_ID
  • HOOK_ARGS_JSON — arguments d’outil JSON
  • HOOK_ARGS_STDIN=1 — les arguments JSON complets sont toujours disponibles sur stdin ; HOOK_ARGS_JSON est vide pour les charges plus grandes que 32 KiB
  • HOOK_PACK — nom du paquet lorsque cela s’applique

Les processus enfants des hooks héritent d’une version assainie de l’environnement AX Code. AX Code conserve les variables ordinaires de plateforme et d’outillage, mais retire les noms qui ressemblent à des secrets, les URL porteuses d’identifiants, les assistants d’identifiants tels que SSH_AUTH_SOCK, et les variables d’injection de processus telles que NODE_OPTIONS. Les variables de protocole HOOK_* ci-dessus sont ajoutées après l’assainissement et sont toujours disponibles.

Les hooks hérités pleinement fiables qui exigent des identifiants ambiants peuvent rétablir le comportement précédent hors du dépôt :

AX_CODE_HOOKS_FULL_ENV=1 AX_CODE_TRUST_PROJECT_CONFIG=1 ax-code

Cette échappatoire expose chaque variable d’environnement à chaque hook activé. Un dépôt ne peut pas la demander via .ax-code/hooks.json ; ne l’utilisez qu’après avoir examiné tous les hooks et paquets.

Note de sécurité : l’assainissement de l’environnement réduit l’exposition des identifiants ambiants, mais n’isole pas les commandes de hook. Les hooks restent du code shell arbitraire qui peut lire les fichiers accessibles et utiliser le réseau de l’hôte. Traitez-les comme du code de confiance et examinez chaque hook et paquet activé.

Lien avec l'isolation

Les hooks ne remplacent pas le bac à sable. Utilisez :

  1. L’isolation de l’application pour des frontières portables d’écriture et de réseau
  2. L’isolation du système (le moteur par défaut "auto") pour un bac à sable bash appliqué par le noyau lorsqu’il est disponible
  3. Les hooks pour les effets de bord de politique et les blocages fermes comme le force-push

Voir Mode bac à sable et SECURITY.md.