Hooks: Automação Determinística
Hooks são comandos de shell que o Claude Code executa automaticamente em pontos definidos do seu ciclo de vida. Enquanto as permissões decidem se uma ação é permitida, os hooks permitem que você execute uma lógica determinística em torno dela — formatação, validação, registro de logs, barreiras. É assim que você torna o comportamento garantido em vez de "por favor, lembre-se de".
- Quando recorrer a um hook em vez de uma instrução ou uma permissão
- Como um hook é configurado: evento, matcher e o payload JSON no stdin
- As duas formas pelas quais um hook bloqueia uma ação — código de saída 2 vs JSON no stdout
- As boas práticas e os erros comuns que separam hooks rápidos e seguros dos lentos e silenciosos
Quando recorrer a um hook
Recorra a um hook quando quiser que um comportamento seja garantido, não apenas solicitado. Cada tarefa comum mapeia para um evento do ciclo de vida:
- Formatar / fazer lint automaticamente após cada edição de arquivo (
PostToolUse). - Bloquear uma ação que viola uma regra antes que ela seja executada (
PreToolUse). - Notificar ou registrar em log quando uma sessão termina ou uma tarefa é concluída (
Stop). - Injetar contexto no início da sessão.
Como funcionam
Você registra hooks em settings.json, associando um evento (e, muitas vezes, um matcher de ferramenta). Quando o evento dispara, o Claude executa seu comando, passando um payload JSON no stdin (o nome da ferramenta, suas entradas, a sessão). O código de saída e a saída do seu comando decidem o que acontece em seguida.
- Registre o hook em settings.json sob o evento do ciclo de vida que lhe interessa — por exemplo, PostToolUse.
- Adicione um matcher de ferramenta para que o hook dispare apenas em ferramentas relevantes, ex.: matcher "Edit|Write" para edições de arquivo.
- Quando o evento dispara, o Claude executa seu comando e canaliza um payload JSON no stdin — o nome da ferramenta, suas entradas, a sessão.
- O código de saída e a saída do seu comando determinam o resultado: deixar a ação prosseguir, executar sua lógica ou bloqueá-la.
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" }
]
}
]
}
}
O hook acima lê o caminho do arquivo editado a partir do JSON de stdin (.tool_input.file_path) e o formata. Não presuma que uma variável de ambiente contém o caminho — leia-o do stdin. Placeholders de caminho úteis como ${CLAUDE_PROJECT_DIR} estão disponíveis para localizar scripts.
Como um hook bloqueia
Duas formas, dependendo do evento:
- Código de saída 2 — o hook faz a ação falhar e o que quer que ele tenha escrito no stderr se torna a mensagem que o Claude vê. Simples e funciona para hooks de comando.
- JSON no stdout (saída 0) — retorne uma decisão estruturada. Para
PreToolUse, isso é umapermissionDecisiondedeny; paraPostToolUse/Stop/etc. é{"decision": "block", "reason": "…"}.
O script abaixo é um hook PreToolUse na ferramenta Bash. Leia-o de cima para baixo: ele extrai o comando do stdin e, se ele parecer destrutivo, escreve uma razão no stderr e sai com código 2 para bloquear.
#!/usr/bin/env bash
# PreToolUse hook on the Bash tool: refuse to delete things.
command=$(jq -r '.tool_input.command' < /dev/stdin)
if [[ "$command" == rm\ * || "$command" == *"rm -rf"* ]]; then
echo "Blocked: destructive 'rm' is not allowed by policy." >&2
exit 2
fi
exit 0
O modelo mental
Um hook PreToolUse roda antes da ação e pode bloqueá-la; um hook PostToolUse roda depois que ela tem sucesso e reage ao resultado.
Boas práticas
- Mantenha os hooks rápidos e idempotentes — eles rodam muito.
- Falhe de forma ruidosa em problemas reais, mas não bloqueie por questões cosméticas.
- Trate a saída do hook como feedback para o Claude — uma mensagem clara o ajuda a se autocorrigir.
- Hooks rodam com os privilégios do seu shell — revise qualquer hook que você não escreveu (Revisando Código de Terceiros).
Erros comuns
- Ler o caminho do arquivo a partir de uma variável de ambiente. O caminho vive no JSON de stdin (
.tool_input.file_path), não em$CLAUDE_FILE_PATH. Encaminhe o stdin através dojq. - Bloqueios silenciosos. Se um hook
PreToolUsesai com código 2 sem nada no stderr, o Claude é bloqueado, mas não sabe por quê e não consegue se adaptar. Sempre escreva uma razão clara. - Hooks lentos. Um hook
PostToolUseroda após cada edição correspondente. Um linter de 3 segundos faz toda a sessão parecer lenta — mantenha os hooks rápidos e, idealmente, atue apenas sobre o que mudou. - Matchers excessivamente amplos.
matcher: ".*"dispara em cada ferramenta. Restrinja com um nome exato, uma listaEdit|Write, ou o campoifpor handler (ex.:"if": "Bash(git push *)"). - Confiar em hooks que você não escreveu. Um hook executa shell arbitrário com os seus privilégios. Revise primeiro qualquer hook vindo de um plugin ou template — veja Revisando Código de Terceiros.
- Um hook executa shell arbitrário com os seus privilégios — nunca configure um hook de um plugin ou template sem lê-lo primeiro.
Modelos prontos para copiar e colar estão em Receitas de Hooks e settings.json.
Formatar automaticamente arquivos editados (PostToolUse em Edit|Write)
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{ "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" }
]
}
]
}
}Teste seus conhecimentos
0/3- Hooks tornam o comportamento garantido, não solicitado — eles executam lógica determinística em torno de ações que as permissões apenas permitem ou negam.
- Registre um hook em settings.json contra um evento mais um matcher; o Claude canaliza um payload JSON no stdin e lê seu código de saída e sua saída.
- Leia o caminho do arquivo do stdin (.tool_input.file_path) — não de uma variável de ambiente.
- Bloqueie com o código de saída 2 (o stderr se torna a mensagem) ou com JSON estruturado no stdout (saída 0); sempre inclua uma razão clara.
- Mantenha os hooks rápidos, idempotentes e estreitamente associados — e revise qualquer hook que você não escreveu, já que ele roda com os privilégios do seu shell.
Próximos passos
- settings.json · Permissões
- Skills — expertise vs automação
- Fortalecendo Execuções Autônomas