Saltar para o conteúdo
← Inforjota
Cursos Inforjota English

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 /hooks que 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 python3 por python na linha do comando.
  • «No such file»: o caminho do script está errado; confirma o nome da pasta hooks.

Fontes:

Vídeos

Hooks no Claude Code na prática: 5 hooks com teste automatizado
OpsRoom · IA & Agentes de Código · 11 min · PT-BR · legendas · Ver no YouTube
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.
Hooks in Claude Code
Claude · 3 min · EN · legendas · Ver no YouTube
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

1. Queres que os testes corram sempre antes de o agente dizer «acabei», mesmo nos dias em que ele se esquece. Onde pões isso?
2. Acabaste de escrever um hook novo. Qual é o primeiro teste?
3. Ligaste um hook PreToolUse e agora o agente não consegue editar nenhum ficheiro, nem os de publico/. O que fazes?

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.