Usa PostToolUse Hooks per avviare il lint automaticamente dopo ogni scrittura di Claude. Il codice di uscita 2 restituisce gli errori a Claude per la correzione automatica.
Claude Code scrive codice velocemente, ma non ricorda sempre di eseguire il lint. Gli chiedi di "controllare mentre scrive" e a volte lo fa, a volte no. Gli Hooks risolvono questo problema: spostano la responsabilità della verifica del codice da Claude al sistema.
Questo articolo si concentra su una cosa sola: usare i PostToolUse Hooks per avviare automaticamente le verifiche dopo che Claude ha scritto codice, assicurando che ogni modifica rispetti i tuoi standard.
La logica di un Hook di verifica del codice è semplice:
Write o Edit per scrivere un fileIl codice di uscita 2 è fondamentale: fa sì che Claude riceva l'errore e lo corregga automaticamente, formando un ciclo "scrivi→verifica→correggi".
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "bash -c 'file=$(echo \"$CLAUDE_TOOL_INPUT\" | jq -r .file_path 2>/dev/null); [[ \"$file\" == *.rb ]] && rubocop -A \"$file\" --no-color -q || true'"
}
]
}
]
}
}
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "bash -c 'file=$(echo \"$CLAUDE_TOOL_INPUT\" | jq -r .file_path 2>/dev/null); [[ \"$file\" =~ \\.(js|ts|jsx|tsx)$ ]] && npx eslint --fix \"$file\" || true'"
}
]
}
]
}
}
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "bash -c 'file=$(echo \"$CLAUDE_TOOL_INPUT\" | jq -r .file_path 2>/dev/null); [[ \"$file\" == *.py ]] && ruff check --fix \"$file\" && ruff format \"$file\" || true'"
}
]
}
]
}
}
Spostare la logica di verifica in uno script indipendente è più facile da mantenere che accumulare comandi nel JSON.
Crea .claude/hooks/lint.sh:
#!/bin/bash
set -e
input=$(cat)
file=$(echo "$input" | jq -r '.tool_input.file_path // empty')
[[ -z "$file" ]] && exit 0
[[ ! -f "$file" ]] && exit 0
ext="${file##*.}"
case "$ext" in
rb) rubocop -A "$file" --no-color -q ;;
js|ts|jsx|tsx) npx eslint --fix "$file" --quiet ;;
py) ruff check --fix "$file"; ruff format "$file" ;;
go) gofmt -w "$file"; golangci-lint run "$file" 2>&1 ;;
*) exit 0 ;;
esac
Riferisci lo script in settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [{ "type": "command", "command": "bash .claude/hooks/lint.sh" }]
}
]
}
}
Codice di uscita 2 + stderr è ciò che attiva la correzione automatica di Claude:
run_lint() {
local output exit_code
output=$(rubocop "$file" --no-color 2>&1)
exit_code=$?
if [[ $exit_code -ne 0 ]]; then
echo "$output" >&2
exit 2
fi
rubocop -A "$file" --no-color -q
}
skip_patterns=("vendor/" "node_modules/" "db/schema.rb" ".min.js" "_test.go")
for pattern in "${skip_patterns[@]}"; do
[[ "$file" == *"$pattern"* ]] && exit 0
done
Con questa configurazione, il flusso di lavoro diventa:
Writerubocop -A automaticamente — trova 3 problemiNon devi mai eseguire manualmente un comando di verifica.
Globale (~/.claude/settings.json): Quando usi le stesse regole in tutti i progetti.
Livello progetto (.claude/settings.json in git): Consigliato per i team. Chiunque apra il repository ottiene automaticamente la configurazione corretta.
I due coesistono; gli hooks di progetto si uniscono a quelli globali ed entrambi vengono eseguiti.
La verifica automatica del codice con gli Hooks si riduce a tre passi:
PostToolUse + matcher "Write|Edit" per intercettare le scritture di fileInizia con un linguaggio. Una volta funzionante, aggiungine altri. Fai commit degli script in .claude/hooks/ per condividerli con il team.