Lição 3 de 7 · 15 min · Verificado em 10 de Outubro de 2026
Hooks: verificações automáticas que o agente não salta
No fim desta lição vais conseguir:
- Explicar o que é um hook e em que momentos corre
- Criar um hook que impede o agente de editar uma pasta e testá-lo à mão antes de o ligar
- Ligar o mesmo hook ao Claude Code e ao Codex
Na loja de ferragens, o senhor Manuel colou um papel na gaveta do dinheiro: «Só o dono abre.» O empregado lê o papel e respeita-o. Num sábado de muito movimento, esquece-se. No dia seguinte, o senhor Manuel põe uma fechadura.
Com um agente é igual. No AGENTS.md (lição 1/07) escreveste «não mexas na pasta privado/». Quase sempre ele cumpre. Numa sessão longa, um dia, edita lá um ficheiro.
O papel é a regra no AGENTS.md. A fechadura é um hook.
O conceito
Um hook é um comando que a própria ferramenta corre, sozinha, em momentos fixos. Não é o modelo que decide se corre: é o programa. Os momentos mais usados têm o mesmo nome no Claude Code e no Codex:
- PreToolUse: antes de o agente usar uma ferramenta (editar um ficheiro, correr um comando).
- PostToolUse: depois de a usar.
- Stop: quando o agente acaba de responder.
O hook recebe uma descrição do que o agente vai fazer (em JSON, um formato de texto com campos e valores) e responde com um código de saída. Se terminar com 0, a acção segue. Se terminar com 2, a acção é bloqueada, e a mensagem que o hook escreveu é entregue ao agente, para ele saber porquê. Só os hooks que correm antes (PreToolUse) conseguem bloquear: um PostToolUse chega depois de a acção ter acontecido e serve para reagir, não para impedir.
Três usos comuns
- Proteger uma pasta. Um hook PreToolUse vê o caminho do ficheiro e bloqueia se for dentro de
privado/. É o exemplo completo desta lição. - Formatar depois de cada edição. Um hook PostToolUse corre um formatador (um programa que arruma o código sempre da mesma maneira) no ficheiro que acabou de mudar. O guia oficial do Claude Code traz um exemplo pronto.
- Testes antes de acabar. Um hook Stop corre
python3 -m pytest(lição 2/01). Se os testes falharem, devolve 2 com o erro e o agente continua a trabalhar.
Cuidado
Um hook mal feito bloqueia tudo. Se o script devolver sempre 2, o agente não consegue editar nenhum ficheiro. Um hook Stop que falha sempre não deixa o agente parar: o guia do Claude Code manda o script verificar o campo stop_hook_active para não entrar em ciclo. E um hook corre com as tuas permissões, no teu computador. Nunca copies hooks de outras pessoas sem os ler, e experimenta-os primeiro em experiencias.
Como se faz hoje: o hook mínimo
Isto é como está a 6 de Outubro de 2026; se o ecrã for diferente, procura o botão com o mesmo nome.
O script é o mesmo para as duas ferramentas. Grava-o em .claude/hooks/proteger.py:
# Trava: impede o agente de mexer na pasta privado/
import json
import sys
dados = json.load(sys.stdin)
entrada = dados.get("tool_input", {})
alvo = str(entrada.get("file_path", "")) + " " + str(entrada.get("command", ""))
alvo = alvo.replace("\\", "/")
if "privado/" in alvo:
print("Bloqueado: a pasta privado/ não se mexe.", file=sys.stderr)
sys.exit(2)
sys.exit(0)
Lê a descrição da acção, junta o caminho do ficheiro e o texto do comando, troca as barras do Windows e procura privado/. Se encontrar, escreve o motivo e sai com 2.
É um filtro de texto, não uma barreira: PRIVADO\notas.txt, em maiúsculas, passa com 0, e um comando que só fale de privado/ sem lhe tocar é bloqueado com 2. Chega para aprenderes o mecanismo. Para proteger uma pasta a sério, normaliza o caminho (minúsculas, os.path.realpath) e compara-o com o caminho completo da pasta protegida.
Testa-o à mão antes de o ligar, com um caso mau e um bom, dentro da pasta do projecto:
echo '{"tool_name":"Write","tool_input":{"file_path":"privado/notas.txt"}}' | python3 .claude/hooks/proteger.py; echo $?
echo '{"tool_name":"Write","tool_input":{"file_path":"publico/notas.txt"}}' | python3 .claude/hooks/proteger.py; echo $?
O primeiro tem de mostrar a mensagem e 2; o segundo, só 0. No PowerShell, troca echo $? por echo $LASTEXITCODE e python3 por python.
Claude Code. Liga o hook no ficheiro .claude/settings.json do projecto:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "python3 \"$CLAUDE_PROJECT_DIR\"/.claude/hooks/proteger.py"
}
]
}
]
}
}
O matcher escolhe as ferramentas vigiadas: aqui, editar e escrever ficheiros. Escreve /hooks na sessão para confirmar que o hook aparece.
Codex. Copia o script para .codex/hooks/proteger.py e cria .codex/hooks.json com o mesmo conteúdo, mudando só a linha do comando:
"command": "python3 \"$(git rev-parse --show-toplevel)/.codex/hooks/proteger.py\""
No Codex as edições chegam como apply_patch, com o texto da alteração em command; o script também procura aí, por isso serve. O Codex só carrega hooks de um projecto em que confias, e cada hook novo ou alterado tem de ser aprovado em /hooks.
Testámos este hook nas duas ferramentas: a edição em privado/ foi bloqueada com a mensagem e a de publico/ passou.
Dica
A documentação do Codex chama aos hooks «uma barreira útil, não uma fronteira completa». Este bloqueia edições, não comandos de terminal. As permissões (lições 1/03 e 1/06) continuam a ser a outra metade da protecção.
Dica
Junta uma linha ao AGENTS.md a explicar a regra. O agente percebe porque foi bloqueado e não perde tempo a tentar outra vez.
Exercício
Como sei que ficou bem o agente diz que a edição em privado/notas.txt foi bloqueada, com a mensagem do hook. O diff mostra só publico/notas.txt alterado. Se o agente pedir para correr um comando de terminal que escreva em privado/, recusa.
Se não deu
- Nada é bloqueado: confirma em
/hooksque o hook aparece. Vê se o JSON não tem uma vírgula a mais no fim de uma lista. Reinicia a sessão. No Codex, aprova o hook em/hooks. - Tudo é bloqueado: fecha a sessão antes de tirares o hook da configuração, repete o teste à mão com
publico/e só depois a voltas a abrir. Se der 2, o erro está no script. - «python3: command not found» (Windows): troca
python3porpythonna linha do comando. - «No such file»: o caminho do script está errado; confirma o nome da pasta
hooks.
Fontes:
Vídeos
Hooks do Claude Code na prática: o contrato de um hook, o mapa de eventos e hooks para proteger ficheiros sensíveis, dar contexto ao pedido e sinalizar o fim da tarefa, com testes automáticos.
Vídeo oficial da Anthropic, com cerca de três minutos: hooks para controlo determinista do Claude Code, como formatar depois de editar, bloquear operações perigosas e partilhar hooks com a equipa.
Testa o que aprendeste
Correcções a esta lição (1)
- : Depois de uma segunda revisão externa: o hook do exemplo é um filtro de texto (maiúsculas e caminhos equivalentes passam; um comando que só fale de `privado/` é bloqueado), com a nota de como normalizar caminhos; só os hooks PreToolUse bloqueiam, o PostToolUse chega depois; ao diagnosticar, fecha-se a sessão antes de tirar o hook.