"Quero formatação automática depois de cada edição." "Nunca deixe nada reescrever .env ou package-lock.json." "Bloqueie comandos perigosos como rm -rf." A forma de tornar reais essas regras de "isto precisa sempre acontecer" — sem depender dos caprichos da IA — são os hooks do Claude Code. Um hook é um comando de shell que roda automaticamente em pontos específicos do ciclo de vida do Claude Code, e os hooks também são um bloco de construção dos plugins.

Este artigo apresenta, com base na documentação oficial, o que são os hooks, a lista de eventos, como configurá-los, o contrato de entrada/saída, casos de uso e segurança. Três pontos antes de começar. ① Um hook é "lógica determinística que o harness (o próprio Claude Code) executa" — ele dispara com certeza, sem esperar que o modelo "decida" fazê-lo. ② Você escreve os hooks em settings.json como nome do evento → matcher → command. ③ Eventos como PreToolUse podem "bloquear" via código de saída 2 ou JSON — impedindo edições em arquivos protegidos ou comandos perigosos.

CLAUDE CODE · HOOKS

Dispara "com certeza" em pontos-chave do ciclo de vida

— o harness o executa de forma determinística, não o julgamento do modelo

SessionStart A sessão começa. A saída é injetada como contexto
UserPromptSubmit Quando um prompt é enviado [pode bloquear]
PreToolUse Logo antes de uma ferramenta rodar = o porteiro [pode bloquear]
PostToolUse Após uma ferramenta ter sucesso = formatação automática / auditoria
Stop Quando uma resposta termina = continuar até os testes passarem, etc. [pode bloquear]

Em cada ponto, seu comando de shell é executado. Os clássicos: PreToolUse para barrar ações perigosas logo na porta, PostToolUse para formatação automática.

1. O que são os hooks do Claude Code?

A definição oficial diz: "Hooks são comandos de shell definidos pelo usuário que são executados em pontos específicos do ciclo de vida do Claude Code. Eles oferecem controle determinístico sobre o comportamento do Claude Code, garantindo que certas ações sempre aconteçam, em vez de depender de o LLM escolher executá-las." Você os usa para impor regras de projeto, automatizar tarefas repetitivas e integrar o Claude Code às suas ferramentas existentes.

O cerne é o determinismo. Peça ao Claude para "rodar os testes" e se ele o fará depende do seu "julgamento". Mas com um hook, o harness sempre o executa — nenhum capricho entra em jogo. Além dos comandos (command), agora também há tipos de handler como HTTP, ferramentas MCP, prompts de LLM e verificação por subagente — mas, para começar, basta pensar nos hooks como "um mecanismo para sempre rodar um comando de shell em pontos-chave".

2. Os eventos de hook

Um evento representa "onde no ciclo de vida ele dispara". Comece pelos nove clássicos ("pode bloquear" = você pode interromper essa ação via código de saída 2 ou JSON).

EventoDispara quandoBloqueia
SessionStartUma sessão começa ou é retomada (a stdout é injetada como contexto)Não
UserPromptSubmitVocê envia um prompt, antes de o Claude processá-loSim
PreToolUseLogo antes de uma chamada de ferramenta (o porteiro principal)Sim
PostToolUseApós uma ferramenta ter sucesso (a ação em si não pode ser desfeita)Sim
NotificationEm uma notificação (aguardando entrada/permissão, etc.)Não
StopQuando o Claude termina de responder (bloquear = continuar trabalhando)Sim
SubagentStopQuando um subagente terminaSim
SessionEndQuando uma sessão é encerradaNão
PreCompactAntes da compactação do contextoSim

A documentação de 2026 adiciona muitos outros eventos — PermissionRequest, PostToolUseFailure, ConfigChange, FileChanged, WorktreeCreate, entre outros. Mas os nomes dos eventos podem ser adicionados ou alterados entre versões, então este artigo se ancora nos nove clássicos estáveis mais o contrato da próxima seção (consulte a documentação oficial para a lista atual completa).

3. Como configurar hooks

Você escreve os hooks sob a chave "hooks" em settings.json. A localização define o escopo: usuário (~/.claude/settings.json) / projeto (.claude/settings.json, compartilhável via git) / local (.claude/settings.local.json) / política gerenciada (organização) / o hooks/hooks.json de um plugin. O formato do JSON é assim.

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}

A estrutura é "hooks → nome do evento → um array de { matcher, hooks:[...] } → cada hook tem type + command." O matcher especifica o nome da ferramenta alvo: "*" (ou omitido) corresponde a todas, "Edit|Write" é uma lista separada por |, e outros caracteres são regex (p. ex. mcp__memory__.*). Diferencia maiúsculas de minúsculas. O comando /hooks lista os hooks configurados, mas é somente leitura — para adicionar ou alterar, edite settings.json diretamente. Desative todos com "disableAllHooks": true.

4. O contrato de entrada/saída

Um hook recebe JSON na entrada padrão (stdin) e retorna seu resultado via código de saída ou JSON na saída padrão.

Entrada (stdin): os campos comuns incluem session_id, transcript_path, cwd e hook_event_name. Eventos de ferramenta adicionam tool_name e tool_input (p. ex. {"command":"rm -rf /tmp/build"}); UserPromptSubmit adiciona prompt. Códigos de saída: 0 = sucesso (para alguns eventos, a stdout é adicionada ao contexto — embora código de saída 0 em PreToolUse não seja uma "aprovação"; o fluxo normal de permissão ainda se aplica), 2 = bloquear (a stderr é passada ao Claude como material para ajuste, e a saída JSON é ignorada).

# Exemplo: "deny" do PreToolUse via saída JSON estruturada (impressa na stdout)
{
  "hookSpecificOutput": {
    "hookEventName": "PreToolUse",
    "permissionDecision": "deny",
    "permissionDecisionReason": "Database writes are not allowed"
  }
}
# Campos comuns: continue (false = parar totalmente) / decision:"block"+reason /
#                additionalContext (anexado para o Claude) / updatedInput (reescrever args)

O princípio mais importante: "os hooks podem apertar restrições, mas não afrouxá-las". Retornar allow apenas pula o prompt; regras de deny em qualquer escopo (inclusive nas configurações gerenciadas) sempre têm precedência. Um deny de PreToolUse bloqueia até mesmo sob bypassPermissions / --dangerously-skip-permissions. Para o modelo de permissão mais amplo, veja modos de permissão e segurança.

5. Exemplos de uso

Os clássicos oficiais, acompanhados de sua configuração.

CASOS DE USO

As automações clássicas

Formatar automaticamente após edições
PostToolUse + Edit|Write roda prettier / um linter automaticamente.
Proteger arquivos críticos
PreToolUse bloqueia (exit 2) edições em .env, .git/, etc.
Bloquear comandos perigosos
PreToolUse detecta rm -rf etc. e retorna deny.
Reinjetar contexto
A stdout de SessionStart recarrega convenções e notas toda vez (mesmo após a compactação).
Notificações e log de auditoria
Notification para alertas de desktop; PostToolUse para registrar o histórico de comandos.
Testar antes de parar
Stop não deixa o Claude parar até os testes passarem (continuar trabalhando até ficar verde).

Observação: o Claude também pode alterar arquivos via Bash. Para capturar toda alteração, adicione um hook Stop que examine a árvore de trabalho uma vez por turno.

6. Segurança

Os hooks são poderosos, mas executam comandos de shell arbitrários automaticamente com os seus privilégios — não leve isso na brincadeira.

⚠️ O aviso oficial

"Os hooks executam comandos de shell arbitrários automaticamente. Você é o único responsável pela segurança dos hooks que configura. USE POR SUA CONTA E RISCO." Os hooks podem ler arquivos, modificar seu código-fonte, exfiltrar dados ou rodar qualquer comando — configure apenas aqueles em que você confia plenamente.

Snapshot na inicialização (um recurso de segurança fundamental): a configuração dos hooks é capturada no início da sessão, então alterações de configuração no meio da sessão não têm efeito. Isso impede que um prompt malicioso ou a saída de uma ferramenta reescreva a sua configuração de hook durante uma sessão. Aplique as alterações em uma nova sessão.

Na prática: sempre valide e coloque entre aspas as entradas (extraia com jq; variáveis sem aspas podem virar argumentos extras ou sintaxe de shell), use caminhos absolutos e ${CLAUDE_PROJECT_DIR}, não mexa em arquivos sensíveis como .env ou .ssh, e nunca faça eval da saída de ferramentas. Os hooks rodam sem um terminal de controle (sem /dev/tty). Em organizações, os administradores podem restringir os hooks com allowManagedHooksOnly.

Resumo

Os hooks do Claude Code são comandos de shell definidos pelo usuário que rodam automaticamente em pontos-chave do ciclo de vida, tornando o "isto precisa sempre acontecer" real e determinístico sem depender do julgamento do modelo. Os eventos clássicos são nove: SessionStart / UserPromptSubmit / PreToolUse / PostToolUse / Notification / Stop / SubagentStop / SessionEnd / PreCompact (PreToolUse e outros podem bloquear — impedindo edições em arquivos protegidos ou comandos perigosos). Você os configura em settings.json sob "hooks" como evento → matcher → type + command.

A E/S é JSON na stdin, código de saída 0 (sucesso) / 2 (bloquear), ou JSON estruturado na stdout. O princípio: "você pode apertar, mas não afrouxar restrições" (deny sempre vence). Os casos de uso clássicos: formatação automática, proteger arquivos, bloquear comandos perigosos, reinjetar contexto, auditoria e testar antes de parar. Mas, como eles rodam código arbitrário, seja rigoroso em confiar apenas em hooks seguros e validar/colocar entre aspas as entradas, e entenda que a configuração é capturada na inicialização. Relacionados: plugins, MCP, erros do Claude Code.

FAQ

Q. Para que servem os hooks?
A. Eles automatizam de forma determinística o "isto precisa sempre acontecer". Coisas como "formatar após edições", "nunca deixar arquivos protegidos serem reescritos", "bloquear o perigoso rm -rf" e "passar nos testes antes de parar" são executadas com certeza pelo harness, sem depender do julgamento da IA. Um hook é um comando de shell que roda em pontos-chave do ciclo de vida, configurado em settings.json.

Q. Quais eventos (momentos) existem?
A. Os clássicos são nove: SessionStart (início), UserPromptSubmit (ao enviar), PreToolUse (logo antes de uma ferramenta), PostToolUse (após uma ferramenta), Notification, Stop (fim da resposta), SubagentStop, SessionEnd (encerramento), PreCompact (antes da compactação). Destes, PreToolUse, UserPromptSubmit, Stop, PreCompact e outros podem bloquear e interromper a ação. A versão de 2026 adiciona muitos outros eventos, mas os nomes podem mudar entre versões, então consulte a documentação oficial para a versão mais recente.

Q. Posso impedir edições em arquivos protegidos ou comandos perigosos?
A. Sim — com um hook PreToolUse. Um script inspeciona o caminho do arquivo ou o comando em tool_input, e se ele corresponder a .env, rm -rf, etc., retorna código de saída 2 (ou JSON com permissionDecision:"deny") para bloqueá-lo. Crucialmente, o deny sempre tem precedência e bloqueia até mesmo sob bypassPermissions. Os hooks só funcionam na direção de "apertar restrições".

Q. Alterei minha configuração, mas ela não está fazendo efeito.
A. Isso é intencional (um recurso de segurança). A configuração dos hooks é capturada como um snapshot no início da sessão, então alterações no meio da sessão não se aplicam. Isso impede que um prompt malicioso ou a saída de uma ferramenta reescreva silenciosamente a sua configuração de hook. Inicie uma nova sessão para aplicá-la. Note que /hooks é uma lista somente leitura; adicione ou altere hooks editando settings.json diretamente.

Q. Os hooks são seguros?
A. Não incondicionalmente. Os hooks executam comandos de shell arbitrários com os seus privilégios, e é por isso que a documentação diz "use por sua conta e risco". Configure apenas hooks em que você confia, valide e coloque entre aspas as entradas com jq, use caminhos absolutos e não mexa em .env / .ssh, e nunca faça eval da saída de ferramentas. Em organizações, os administradores podem restringir os hooks com allowManagedHooksOnly.