Hook
Hook PreToolUse qui bloque les commandes shell dangereuses
Hook Claude Code prêt à l'emploi : un script PreToolUse refuse rm -rf, git push --force ou git reset --hard avant leur exécution.
Faits vérifiés le source officiellejournal des changements
Où le placer.claude/settings.json + .claude/hooks/bloquer-commandes.sh
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/bloquer-commandes.sh"
}
]
}
]
}
}#!/bin/bash
# bloquer-commandes.sh — hook PreToolUse pour l'outil Bash de Claude Code.
#
# Claude Code envoie sur l'entrée standard un objet JSON décrivant l'appel
# d'outil ; la commande shell se trouve dans .tool_input.command.
# Code de sortie 2 = l'appel est bloqué et le message écrit sur stderr
# est transmis à Claude. Code de sortie 0 = le circuit normal des
# permissions s'applique.
#
# Prérequis : jq. Rendre le script exécutable :
# chmod +x .claude/hooks/bloquer-commandes.sh
#
# Ce filtre est un garde-fou, pas une barrière infaillible : une commande
# peut être formulée autrement. Combinez-le avec des règles "deny" dans
# settings.json.
INPUT=$(cat)
COMMANDE=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
# Motifs refusés (expressions régulières étendues). Complétez la liste.
MOTIFS_INTERDITS=(
'rm[[:space:]]+-[a-zA-Z]*r[a-zA-Z]*f' # rm -rf, rm -fr, rm -Rf…
'rm[[:space:]]+-[a-zA-Z]*f[a-zA-Z]*r'
'git[[:space:]]+push.*(--force|-f([[:space:]]|$))'
'git[[:space:]]+reset[[:space:]]+--hard'
'git[[:space:]]+clean[[:space:]]+-[a-zA-Z]*f'
'chmod[[:space:]]+-R[[:space:]]+777'
'mkfs\.'
'dd[[:space:]]+if='
'curl[^|]*\|[[:space:]]*(ba|z)?sh' # curl … | sh
)
for motif in "${MOTIFS_INTERDITS[@]}"; do
if echo "$COMMANDE" | grep -Eq -- "$motif"; then
echo "Commande bloquée par le hook de sécurité du projet (motif : $motif). Proposez une alternative non destructive ou demandez à l'utilisateur de l'exécuter lui-même." >&2
exit 2
fi
done
exit 0Une consigne écrite dans CLAUDE.md reste une consigne : Claude la suit la plupart du temps, sans garantie. Un hook, lui, est une commande que Claude Code exécute systématiquement à un moment précis. Ce modèle utilise l'événement PreToolUse, déclenché avant chaque appel d'outil, pour inspecter les commandes shell et refuser celles qui détruisent des données ou réécrivent l'historique Git.
Comment ça fonctionne
Le fichier est livré en deux parties :
- l'extrait de
settings.jsondéclare le hook sur l'événementPreToolUseavec le filtre"matcher": "Bash", afin qu'il ne s'exécute que pour l'outil shell ; - le script
bloquer-commandes.shreçoit sur son entrée standard un objet JSON décrivant l'appel. Il en extrait la commande (.tool_input.command) avecjq, la compare à une liste de motifs et, en cas de correspondance, écrit une explication sur la sortie d'erreur puis quitte avec le code 2.
Le code de sortie 2 bloque l'appel d'outil, et le message d'erreur est transmis à Claude, qui peut proposer une alternative. Le code 0 laisse le circuit normal des permissions s'appliquer. Attention : un code 1 n'est pas bloquant pour Claude Code, il est traité comme une erreur non bloquante et la commande s'exécute quand même.
Installation
- Copiez le script dans
.claude/hooks/bloquer-commandes.shet rendez-le exécutable (chmod +x). - Fusionnez l'extrait dans
.claude/settings.json: si le fichier contient déjà une cléhooks, ajoutez l'entréePreToolUseau lieu de remplacer l'objet. - Vérifiez que
jqest installé. - Lancez
/hooksdans Claude Code pour vérifier que le hook est bien pris en compte, puis demandez à Claude de supprimer un dossier de test pour observer le refus.
La commande utilise "$CLAUDE_PROJECT_DIR", variable qui pointe vers la racine du projet : le script est trouvé même si Claude a changé de répertoire.
Comment l'adapter
- Complétez la liste
MOTIFS_INTERDITSavec les commandes sensibles de votre contexte (déploiement, suppression de base de données…). - Pour un blocage plus riche, la documentation décrit aussi une sortie JSON avec
permissionDecisionà"deny","ask"ou"allow".
Pièges fréquents
- Se croire protégé à 100 % : une expression régulière se contourne (variables, scripts intermédiaires). Doublez ce hook par des règles
denydanssettings.json. - Oublier le droit d'exécution : sans
chmod +x, le hook échoue sans bloquer. - Bloquer trop large : un motif trop générique interrompt des commandes légitimes et pousse à désactiver le hook.
La leçon Les hooks présente les autres événements disponibles et leurs usages.