Skip to main content

Configuration des hooks

Recherchez des informations sur la configuration des hooks à utiliser avec GitHub Copilot CLI et Agent de codage Copilot.

Cet article de référence décrit les types de hooks disponibles avec des exemples, notamment leurs formats d’entrée et de sortie, les meilleures pratiques de script et les modèles avancés pour la journalisation, l’application de la sécurité et les intégrations externes. Pour obtenir des informations générales sur la création de hooks, consultez Utilisation de hooks avec les agents de GitHub Copilot.

Types de crochets

Point d'ancrage pour le démarrage de session

Exécuté lorsqu’une nouvelle session d’agent commence ou lors de la reprise d’une session existante.

          **JSON d’entrée :**
JSON
{
  "timestamp": 1704614400000,
  "cwd": "/path/to/project",
  "source": "new",
  "initialPrompt": "Create a new feature"
}
          **Champs:**

* timestamp: horodatage Unix en millisecondes * cwd: répertoire de travail actuel * source: soit "new" (nouvelle session), (reprise de la session) "resume" ou "startup" * initialPrompt: invite initiale de l’utilisateur (le cas échéant)

          **Sortie:** Ignoré (aucune valeur de retour traitée)

          **Exemple de hook :**
JSON
{
  "type": "command",
  "bash": "./scripts/session-start.sh",
  "powershell": "./scripts/session-start.ps1",
  "cwd": "scripts",
  "timeoutSec": 30
}
          **Exemple de script (Bash) :**
Shell
#!/bin/bash
INPUT=$(cat)
SOURCE=$(echo "$INPUT" | jq -r '.source')
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')

echo "Session started from $SOURCE at $TIMESTAMP" >> session.log

Hook de fin de session

Exécuté lorsque la session de l’agent se termine ou est terminée.

          **JSON d’entrée :**
JSON
{
  "timestamp": 1704618000000,
  "cwd": "/path/to/project",
  "reason": "complete"
}
          **Champs:**

* timestamp: horodatage Unix en millisecondes * cwd: répertoire de travail actuel * reason: Un des "complete", , "error"``"abort", , "timeout"ou"user_exit"

          **Sortie:** Ignoré

          **Exemple de script :**
Shell
#!/bin/bash
INPUT=$(cat)
REASON=$(echo "$INPUT" | jq -r '.reason')

echo "Session ended: $REASON" >> session.log
# Cleanup temporary files
rm -rf /tmp/session-*

Hook déclenché à la soumission d’un prompt utilisateur

Exécuté lorsque l’utilisateur envoie une invite à l’agent.

          **JSON d’entrée :**
JSON
{
  "timestamp": 1704614500000,
  "cwd": "/path/to/project",
  "prompt": "Fix the authentication bug"
}
          **Champs:**

* timestamp: horodatage Unix en millisecondes * cwd: répertoire de travail actuel * prompt: texte exact envoyé par l’utilisateur

          **Sortie :** Ignorée (la modification de prompt n’est pas prise en charge actuellement dans les hooks client)

          **Exemple de script :**
Shell
#!/bin/bash
INPUT=$(cat)
PROMPT=$(echo "$INPUT" | jq -r '.prompt')
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')

# Log to a structured file
echo "$(date -d @$((TIMESTAMP/1000))): $PROMPT" >> prompts.log

Hook exécuté avant l’utilisation d’un outil

Exécuté avant que l’agent utilise un outil (par exemple, bash, edit, view). Il s’agit du hook le plus puissant, car il peut approuver ou refuser les exécutions d’outils.

          **JSON d’entrée :**
JSON
{
  "timestamp": 1704614600000,
  "cwd": "/path/to/project",
  "toolName": "bash",
  "toolArgs": "{\"command\":\"rm -rf dist\",\"description\":\"Clean build directory\"}"
}
          **Champs:**

* timestamp: horodatage Unix en millisecondes * cwd: répertoire de travail actuel * toolName: Nom de l’outil appelé (par exemple, « bash », « edit », « view », « create ») * toolArgs: chaîne JSON contenant les arguments de l’outil

          **Json de sortie (facultatif) :**
JSON
{
  "permissionDecision": "deny",
  "permissionDecisionReason": "Destructive operations require approval"
}
          **Champs de sortie :**

* permissionDecision: soit "allow", soit "deny", soit "ask" (uniquement "deny" est traité actuellement) * permissionDecisionReason: Explication lisible par l’homme de la décision

          **Exemple de hook pour bloquer les commandes dangereuses :**
Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')
TOOL_ARGS=$(echo "$INPUT" | jq -r '.toolArgs')

# Log the tool use
echo "$(date): Tool=$TOOL_NAME Args=$TOOL_ARGS" >> tool-usage.log

# Check for dangerous patterns
if echo "$TOOL_ARGS" | grep -qE "rm -rf /|format|DROP TABLE"; then
  echo '{"permissionDecision":"deny","permissionDecisionReason":"Dangerous command detected"}'
  exit 0
fi

# Allow by default (or omit output to allow)
echo '{"permissionDecision":"allow"}'
          **Exemple de hook pour appliquer des autorisations de fichier :**
Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')

# Only allow editing specific directories
if [ "$TOOL_NAME" = "edit" ]; then
  PATH_ARG=$(echo "$INPUT" | jq -r '.toolArgs' | jq -r '.path')
  
  if [[ ! "$PATH_ARG" =~ ^(src/|test/) ]]; then
    echo '{"permissionDecision":"deny","permissionDecisionReason":"Can only edit files in src/ or test/ directories"}'
    exit 0
  fi
fi

# Allow all other tools

Hook exécuté après l’utilisation d’un outil

Exécuté après qu'un outil ait terminé son exécution, qu'elle se soit terminée par une réussite ou un échec.

          **Exemple d’entrée JSON :**
JSON
{
  "timestamp": 1704614700000,
  "cwd": "/path/to/project",
  "toolName": "bash",
  "toolArgs": "{\"command\":\"npm test\"}",
  "toolResult": {
    "resultType": "success",
    "textResultForLlm": "All tests passed (15/15)"
  }
}
          **Champs:**

* timestamp: horodatage Unix en millisecondes * cwd: répertoire de travail actuel * toolName: Nom de l’outil qui a été exécuté * toolArgs: chaîne JSON contenant les arguments de l’outil * toolResult: Objet de résultat contenant : * resultType: Soit "success", soit , "failure"ou "denied" * textResultForLlm: texte de résultat affiché à l’agent

          **Sortie:** Ignoré (la modification du résultat n’est pas prise en charge actuellement)

          **Exemple de script qui journalise les statistiques d’exécution des outils dans un fichier CSV :**

Ce script consigne les statistiques d’exécution de l’outil dans un fichier CSV et envoie une alerte par e-mail lorsqu’un outil échoue.

Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')
RESULT_TYPE=$(echo "$INPUT" | jq -r '.toolResult.resultType')

# Track statistics
echo "$(date),${TOOL_NAME},${RESULT_TYPE}" >> tool-stats.csv

# Alert on failures
if [ "$RESULT_TYPE" = "failure" ]; then
  RESULT_TEXT=$(echo "$INPUT" | jq -r '.toolResult.textResultForLlm')
  echo "FAILURE: $TOOL_NAME - $RESULT_TEXT" | mail -s "Agent Tool Failed" [email protected]
fi

Une erreur s'est produite au niveau du hook

Exécuté lorsqu’une erreur se produit pendant l’exécution de l’agent.

          **Exemple d’entrée JSON :**
JSON
{
  "timestamp": 1704614800000,
  "cwd": "/path/to/project",
  "error": {
    "message": "Network timeout",
    "name": "TimeoutError",
    "stack": "TimeoutError: Network timeout\n    at ..."
  }
}
          **Champs:**

* timestamp: horodatage Unix en millisecondes * cwd: répertoire de travail actuel * error: Objet d’erreur contenant : * message: Message d’erreur * name: type/nom d’erreur * stack: Trace de pile (le cas échéant)

          **Sortie:** Ignoré (la modification de gestion des erreurs n’est pas prise en charge actuellement)

          **Exemple de script qui extrait les détails d’erreur dans un fichier journal :**
Shell
#!/bin/bash
INPUT=$(cat)
ERROR_MSG=$(echo "$INPUT" | jq -r '.error.message')
ERROR_NAME=$(echo "$INPUT" | jq -r '.error.name')

echo "$(date): [$ERROR_NAME] $ERROR_MSG" >> errors.log

Bonnes pratiques de script

Lecture de l’entrée

Cet exemple de script lit l'entrée JSON depuis stdin dans une variable, puis utilise jq pour extraire les champs timestamp et cwd.

          **Bash:**
Shell
#!/bin/bash
# Read JSON from stdin
INPUT=$(cat)

# Parse with jq
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')
CWD=$(echo "$INPUT" | jq -r '.cwd')
          **PowerShell :**
PowerShell
# Read JSON from stdin
$input = [Console]::In.ReadToEnd() | ConvertFrom-Json

# Access properties
$timestamp = $input.timestamp
$cwd = $input.cwd

Sortie de JSON

Cet exemple de script montre comment générer un JSON valide à partir de votre script de hook. Utilisez jq -c Bash pour la sortie monoligne compacte ou ConvertTo-Json -Compress dans PowerShell.

          **Bash:**
Shell
#!/bin/bash
# Use jq to compact the JSON output to a single line
echo '{"permissionDecision":"deny","permissionDecisionReason":"Security policy violation"}' | jq -c

# Or construct with variables
REASON="Too dangerous"
jq -n --arg reason "$REASON" '{permissionDecision: "deny", permissionDecisionReason: $reason}'
          **PowerShell :**
PowerShell
# Use ConvertTo-Json to compact the JSON output to a single line
$output = @{
    permissionDecision = "deny"
    permissionDecisionReason = "Security policy violation"
}
$output | ConvertTo-Json -Compress

Gestion des erreurs

Cet exemple de script montre comment gérer les erreurs dans les scripts de hook.

          **Bash:**
Shell
#!/bin/bash
set -e  # Exit on error

INPUT=$(cat)
# ... process input ...

# Exit with 0 for success
exit 0
          **PowerShell :**
PowerShell
$ErrorActionPreference = "Stop"

try {
    $input = [Console]::In.ReadToEnd() | ConvertFrom-Json
    # ... process input ...
    exit 0
} catch {
    Write-Error $_.Exception.Message
    exit 1
}

Gestion des délais d’expiration

Les hooks ont un délai d’expiration par défaut de 30 secondes. Pour les opérations plus longues, augmentez timeoutSec:

JSON
{
  "type": "command",
  "bash": "./scripts/slow-validation.sh",
  "timeoutSec": 120
}

Modèles avancés

Crochets multiples du même type

Vous pouvez définir plusieurs hooks pour le même événement. Ils s’exécutent dans l’ordre :

JSON
{
  "version": 1,
  "hooks": {
    "preToolUse": [
      {
        "type": "command",
        "bash": "./scripts/security-check.sh",
        "comment": "Security validation - runs first"
      },
      {
        "type": "command", 
        "bash": "./scripts/audit-log.sh",
        "comment": "Audit logging - runs second"
      },
      {
        "type": "command",
        "bash": "./scripts/metrics.sh",
        "comment": "Metrics collection - runs third"
      }
    ]
  }
}

Logique conditionnelle dans les scripts

          **Exemple : Bloquer uniquement des outils spécifiques**
Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')

# Only validate bash commands
if [ "$TOOL_NAME" != "bash" ]; then
  exit 0  # Allow all non-bash tools
fi

# Check bash command for dangerous patterns
COMMAND=$(echo "$INPUT" | jq -r '.toolArgs' | jq -r '.command')
if echo "$COMMAND" | grep -qE "rm -rf|sudo|mkfs"; then
  echo '{"permissionDecision":"deny","permissionDecisionReason":"Dangerous system command"}'
fi

Journalisation structurée

          **Exemple : format lignes JSON**
Shell
#!/bin/bash
INPUT=$(cat)
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')
RESULT_TYPE=$(echo "$INPUT" | jq -r '.toolResult.resultType')

# Output structured log entry
jq -n \
  --arg ts "$TIMESTAMP" \
  --arg tool "$TOOL_NAME" \
  --arg result "$RESULT_TYPE" \
  '{timestamp: $ts, tool: $tool, result: $result}' >> logs/audit.jsonl

Intégration avec des systèmes externes

          **Exemple : Envoyer des alertes à Slack**
Shell
#!/bin/bash
INPUT=$(cat)
ERROR_MSG=$(echo "$INPUT" | jq -r '.error.message')

WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"

curl -X POST "$WEBHOOK_URL" \
  -H 'Content-Type: application/json' \
  -d "{\"text\":\"Agent Error: $ERROR_MSG\"}"

Exemples de cas d’utilisation

Piste d’audit de conformité

Journaliser toutes les actions de l’agent pour les exigences de conformité en utilisant des scripts de journal :

JSON
{
  "version": 1,
  "hooks": {
    "sessionStart": [{"type": "command", "bash": "./audit/log-session-start.sh"}],
    "userPromptSubmitted": [{"type": "command", "bash": "./audit/log-prompt.sh"}],
    "preToolUse": [{"type": "command", "bash": "./audit/log-tool-use.sh"}],
    "postToolUse": [{"type": "command", "bash": "./audit/log-tool-result.sh"}],
    "sessionEnd": [{"type": "command", "bash": "./audit/log-session-end.sh"}]
  }
}

Suivi des coûts

Suivez l’utilisation des outils pour l’allocation des coûts :

Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')
TIMESTAMP=$(echo "$INPUT" | jq -r '.timestamp')
USER=${USER:-unknown}

echo "$TIMESTAMP,$USER,$TOOL_NAME" >> /var/log/copilot/usage.csv

Application de la qualité du code

Empêcher les commits qui enfreignent les standards de code :

Shell
#!/bin/bash
INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.toolName')

if [ "$TOOL_NAME" = "edit" ] || [ "$TOOL_NAME" = "create" ]; then
  # Run linter before allowing edits
  npm run lint-staged
  if [ $? -ne 0 ]; then
    echo '{"permissionDecision":"deny","permissionDecisionReason":"Code does not pass linting"}'
  fi
fi

Système de notification

Envoyer des notifications sur des événements importants :

Shell
#!/bin/bash
INPUT=$(cat)
PROMPT=$(echo "$INPUT" | jq -r '.prompt')

# Notify on production-related prompts
if echo "$PROMPT" | grep -iq "production"; then
  echo "ALERT: Production-related prompt: $PROMPT" | mail -s "Agent Alert" [email protected]
fi