← Todos os Posts

Claude Code Hooks: Por que cada um dos meus 95 hooks existe

From the guide: Claude Code Comprehensive Guide

Construí 95 hooks para Claude Code. Cada um existe porque algo deu errado primeiro. O git-safety-guardian existe porque Claude fez force-push para a main. O recursion-guard existe porque um subagente gerou filhos infinitos. O blog-quality-gate existe porque publiquei um post com 7 frases em voz passiva e uma nota de rodapé solta.1

Claude Code hooks são comandos shell que executam em pontos específicos do ciclo de vida (início da sessão, antes/depois do uso de ferramentas, envio de prompt e conclusão da resposta), fornecendo guardrails determinísticos sobre o comportamento probabilístico do LLM. Os hooks recebem JSON via stdin e retornam decisões (bloquear, permitir ou modificar) via stdout. Eles aplicam políticas como bloquear force-pushes para main, impedir geração recursiva de agentes, injetar contexto por sessão e controlar a qualidade da saída que o LLM sozinho não pode garantir.

TL;DR

Claude Code hooks executam comandos shell em pontos específicos do ciclo de vida durante o desenvolvimento assistido por IA. Os hooks fornecem garantias determinísticas (bloqueando comandos git perigosos, injetando contexto, aplicando qualidade) sobre um sistema probabilístico (o LLM). Depois de construir 95 hooks em minha infraestrutura, descobri que os melhores hooks vêm de incidentes, não de planejamento. Este post cobre a arquitetura, as histórias de origem por trás dos meus hooks mais críticos e os padrões que aprendi em 9 meses de desenvolvimento de hooks.


A arquitetura

Claude Code expõe 26 eventos de ciclo de vida onde hooks podem interceptar, modificar ou bloquear o comportamento (na versão v2.1.116, abril de 2026).2 Meus hooks visam seis dos mais comuns:

Eventos de sessão

Evento Quando dispara Meus hooks
SessionStart Nova sessão começa session-start.sh: injeta data, valida venv, inicializa estado de recursão
SessionEnd Sessão termina Limpa arquivos temporários

Eventos de execução de ferramentas

Evento Quando dispara Meus hooks
PreToolUse Antes de qualquer ferramenta executar git-safety-guardian.sh, recursion-guard.sh, credentials-check.sh
PostToolUse Depois que a ferramenta completa post-deliberation.sh, log-bash.sh

Eventos de resposta

Evento Quando dispara Meus hooks
UserPromptSubmit Usuário envia um prompt Injetores de contexto (data, branch, informações do modelo)
Stop Claude termina de responder deliberation-pride-check.sh, reviewer-stop-gate.sh

Cada hook recebe JSON via stdin e se comunica através do stdout:

{"decision": "block", "reason": "Force push to main is prohibited"}

Ou permite silenciosamente saindo com código 0.3


Histórias de origem: os hooks que mais importam

Hook 1: git-safety-guardian.sh (PreToolUse:Bash)

O incidente: Durante uma sessão inicial do Claude Code, pedi ao agente para “limpar o histórico do git”. O agente executou git push --force origin main. O force push sobrescreveu três dias de commits em um branch compartilhado. Recuperei a partir de um backup local, mas o processo de recuperação de 4 horas me convenceu de que o julgamento probabilístico nunca deveria controlar operações destrutivas do git.

O hook:

#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

# Only check git commands
echo "$COMMAND" | grep -qE '\bgit\b' || exit 0

# Block force push to main/master
if echo "$COMMAND" | grep -qiE 'git\s+push\s+.*--force.*\b(main|master)\b'; then
    cat << EOF
{"decision": "block", "reason": "Force push to main/master blocked by safety hook"}
EOF
fi

A lição: O hook não tenta entender a intenção. Ele faz pattern-matching na string do comando. Simples, determinístico, impossível de contornar através de prompting inteligente. O agente ainda pode fazer force-push para branches de feature (às vezes legítimo), mas main/master estão permanentemente protegidos.4

Salvamentos acumulados: 8 tentativas de force-push interceptadas em 9 meses.

Hook 2: recursion-guard.sh (PreToolUse:Task)

O incidente: Enquanto construía o sistema de deliberação, executei uma sessão que gerou 3 subagentes de exploração. Cada subagente, sem limites de geração, gerou seus próprios subagentes. A recursão consumiu tokens API a 10x a taxa normal. Matei a sessão manualmente após notar a queima acelerada de tokens.

O hook:

#!/bin/bash
CONFIG_FILE="${HOME}/.claude/configs/recursion-limits.json"
STATE_FILE="${HOME}/.claude/state/recursion-depth.json"

MAX_DEPTH=2
MAX_CHILDREN=5
DELIB_SPAWN_BUDGET=2
DELIB_MAX_AGENTS=12

# Validate integers safely (((VAR++)) crashes with set -e when VAR=0)
is_positive_int() {
    [[ "$1" =~ ^[0-9]+$ ]] && [[ "$1" -gt 0 ]]
}

A principal decisão de design: Os agentes herdam um orçamento de geração de seu pai em vez de incrementar a profundidade. Um agente raiz com budget=12 pode distribuir esse orçamento em qualquer formato de árvore. Limites baseados em profundidade são rígidos demais (eles impedem cadeias profundas-mas-estreitas que são perfeitamente seguras).5

Bloqueios acumulados: 23 tentativas de geração descontrolada.

Hook 3: blog-quality-gate.sh (Stop)

O incidente: Publiquei um post de blog com 7 frases em voz passiva, uma nota de rodapé referenciada no texto mas ausente da seção de referências, e “was implemented by the team” como a frase de abertura. O post parecia polido no meu editor, mas falhou em verificações básicas de qualidade que qualquer revisor humano pegaria.

O hook: Executa meu linter de blog com 12 módulos em qualquer arquivo de conteúdo de blog modificado. Verifica voz passiva, notas de rodapé soltas, meta descriptions ausentes, blocos de código sem tag e integridade de citações. Cada achado é específico: “Linha 47: voz passiva detectada em ‘was implemented by the team.’ Sugestão: ‘the team implemented.’”

O paralelo com feedback humano: O hook critica o trabalho, não o operador. Ele diz “linha 47 tem voz passiva”, não “você escreve mal”. O mesmo princípio que torna o feedback humano construtivo torna o feedback automatizado útil.


O padrão por trás de 95 hooks

A arquitetura orientada por configuração

Meus hooks evoluíram de valores hardcoded para comportamento orientado por configuração:

~/.claude/configs/
├── recursion-limits.json     # Depth, spawn budgets, timeouts
├── deliberation-config.json  # Consensus thresholds per task type
├── consensus-profiles.json   # security=85%, docs=50%
├── circuit-breaker.json      # Failure mode configurations
└── file-scope-rules.json     # Path-scoped hook application

Mover limiares para configs JSON significou que eu poderia ajustar o comportamento sem editar scripts bash. Quando precisei de consenso relacionado à segurança em 85%, mas documentação em 50%, a mudança de configuração levou 30 segundos. Uma mudança de código teria exigido edição, teste e redeploy.6

O padrão de camadas de ciclo de vida

Meus 95 hooks formam uma rede de segurança com quatro camadas:

Camada 1: Prevenção (PreToolUse): Impede coisas ruins antes que aconteçam. git-safety-guardian, credentials-check, recursion-guard.

Camada 2: Contexto (UserPromptSubmit, SessionStart): Injeta informações que o agente precisa. Data, branch, contexto do projeto, entradas de memória, princípios de filosofia.

Camada 3: Validação (PostToolUse): Verifica se as ações concluídas atendem aos padrões. Verificação de consenso post-deliberation, logging de saída.

Camada 4: Qualidade (Stop): Controla a saída final. Pride check, quality gate, reviewer stop gate. Esta camada implementa monitoramento metacognitivo onde o agente avalia a qualidade do próprio raciocínio, não apenas sua saída.

Cada camada é independente. Se um hook PreToolUse falhar silenciosamente, o hook Stop ainda captura problemas de qualidade. Defesa em profundidade, aplicada ao comportamento do agente de IA.


Configuração

Os hooks ficam em .claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "command": "~/.claude/hooks/git-safety-guardian.sh",
        "timeout": 5000
      }
    ],
    "PreToolUse:Task": [
      {
        "command": "~/.claude/hooks/recursion-guard.sh"
      }
    ]
  }
}

O campo matcher filtra quais ferramentas disparam o hook. PreToolUse:Task é abreviação para um matcher que dispara apenas em invocações da ferramenta Task. Hooks assíncronos (async: true) executam em segundo plano sem bloquear.7

Hierarquia de escopo

  1. Nível de usuário (~/.claude/settings.json): aplica-se a todos os projetos. Meus 95 hooks ficam aqui.
  2. Nível de projeto (.claude/settings.json): adiciona hooks específicos do projeto.
  3. Frontmatter de Skill/Subagent: com escopo no ciclo de vida de um componente específico.8

O que eu faria diferente

Comece com 3 hooks, não 25. Meu primeiro mês produziu 25 hooks, muitos dos quais adicionavam contexto que o agente já tinha. A sobrecarga de carregar 25 hooks em cada chamada de ferramenta era mensurável. Acabei removendo até ficar com os hooks que produziam valor real (impediram incidentes reais, pegaram problemas de qualidade reais).

Orientado por configuração desde o primeiro dia. Gastei duas semanas refatorando limiares hardcoded em configs JSON. Essa refatoração teria sido gratuita se eu tivesse começado com configs.

Infraestrutura de teste cedo. Os primeiros 20 hooks não tinham testes. Quando adicionei o test harness (48 testes de integração bash), encontrei 3 hooks que falhavam silenciosamente em casos extremos. Os testes deveriam ter sido entregues junto com o hook #1.


Principais conclusões

Para desenvolvedores começando com hooks: - Comece com três hooks: segurança do git (PreToolUse:Bash), injeção de contexto (UserPromptSubmit) e quality gate (Stop); adicione mais apenas quando tiver incidentes que justifiquem - Use o framework de timing de decisão: a arquitetura de hooks é irreversível (95 hooks dependem dela), então invista no modelo de ciclo de vida antes de escrever hooks

Para equipes padronizando hooks: - Padronize hooks no nível do usuário para que cada membro da equipe receba os mesmos trilhos de segurança - Rastreie métricas de hooks (operações bloqueadas, incidentes interceptados) para justificar o custo de manutenção - Revise logs de hooks mensalmente para identificar novos padrões que valham a pena automatizar


FAQ

O que são Claude Code hooks?

Hooks são shell scripts que executam em pontos específicos do ciclo de vida durante sessões do Claude Code. Eles disparam deterministicamente em momentos específicos: antes de uma ferramenta rodar (PreToolUse), depois que ela completa (PostToolUse), quando você envia um prompt (UserPromptSubmit), quando uma sessão começa (SessionStart) e quando Claude termina de responder (Stop). Os hooks recebem JSON via stdin com contexto completo (nome da ferramenta, input, ID da sessão) e podem bloquear operações, injetar contexto ou aplicar quality gates. Eles fornecem garantias determinísticas sobre um LLM probabilístico.

Quantos hooks o Claude Code pode executar e há custo de desempenho?

Não há limite rígido na quantidade de hooks. Eu rodo 95 hooks em 6 dos 26 eventos de ciclo de vida disponíveis (na versão v2.1.116, abril de 2026), com aproximadamente 200ms de sobrecarga total por evento. O limite prático é a latência: cada hook adiciona tempo de execução antes ou depois de chamadas de ferramenta. A otimização principal é usar dispatchers (um por evento, executando hooks sequencialmente a partir de stdin em cache) em vez de hooks independentes que cada um lê stdin separadamente. Escritas concorrentes de hooks independentes causaram corrupção de JSON na minha configuração inicial; os dispatchers eliminaram esse modo de falha completamente.

Em quais eventos os Claude Code hooks disparam?

Claude Code expõe 26 eventos de ciclo de vida para hooks na versão v2.1.116 (abril de 2026). Os seis mais comuns que meus hooks visam são: SessionStart (nova sessão começa), SessionEnd (sessão termina), PreToolUse (antes de qualquer ferramenta executar), PostToolUse (depois que a ferramenta completa), UserPromptSubmit (usuário envia um prompt) e Stop (Claude termina de responder). Outros incluem SubagentStart, PermissionRequest, PermissionDenied, TaskCreated, CwdChanged, FileChanged, PreCompact e mais. PreToolUse e PostToolUse podem ser escopados ainda mais com matchers como PreToolUse:Bash ou PreToolUse:Task para disparar apenas em tipos específicos de ferramenta. Cada evento recebe JSON via stdin com contexto relevante.

Os Claude Code hooks podem bloquear chamadas de ferramentas?

Sim. Um hook que produz {"decision": "block", "reason": "explanation"} para stdout impede que a chamada da ferramenta seja executada. Esse é o mecanismo central para hooks de segurança: meu git-safety-guardian bloqueia force pushes para main, meu credentials-check bloqueia leituras de arquivos .env e meu recursion-guard bloqueia geração excessiva de agentes. O bloqueio é determinístico e não pode ser contornado através de prompting. Hooks que saem silenciosamente com código 0 permitem que a operação prossiga.

Qual é a diferença entre hooks PreToolUse e PostToolUse?

PreToolUse dispara antes de uma ferramenta executar e pode bloquear a operação inteiramente. Use-o para safety gates: bloquear comandos perigosos, verificar credenciais, aplicar orçamentos de geração. PostToolUse dispara depois que uma ferramenta completa e pode fornecer feedback ou disparar ações de acompanhamento. Use-o para validação: verificar qualidade da saída, registrar atividade, verificar consenso. Juntos eles formam a primeira e terceira camadas de uma rede de segurança de quatro camadas: prevenção (PreToolUse), injeção de contexto (UserPromptSubmit), validação (PostToolUse) e quality gating (Stop).

Referências


  1. Infraestrutura de hooks do autor. 95 hooks em 6 dos 26 eventos de ciclo de vida disponíveis (v2.1.116, abril de 2026), desenvolvidos ao longo de 9 meses (2025-2026). 

  2. Anthropic, “Claude Code Hooks Reference,” 2026. 26 tipos de eventos de ciclo de vida na versão v2.1.116 (abril de 2026). 

  3. Anthropic, “Claude Code Documentation,” 2025. Formato JSON de entrada/saída de hooks. 

  4. git-safety-guardian.sh do autor. 8 tentativas de force-push interceptadas rastreadas em ~/.claude/state/

  5. recursion-guard.sh do autor. Modelo de herança de orçamento documentado em ~/.claude/configs/recursion-limits.json

  6. Arquitetura orientada por configuração do autor. 14 arquivos de configuração JSON codificando todos os limiares e regras de hooks. 

  7. Anthropic, “Claude Code Documentation,” 2025. Configuração de hooks e execução assíncrona. 

  8. Anthropic, “Claude Code Documentation,” 2025. Hierarquia de escopo de hooks. 

Artigos relacionados

Criando Skills Personalizadas para o Claude Code: Um Tutorial Completo

Construa uma skill de revisao de codigo do zero. Estrutura de diretorios, campos frontmatter, matching LLM, orcamentos d…

12 min de leitura

Gerenciamento da janela de contexto: o que 50 sessões me ensinaram sobre desenvolvimento com IA

Medi o consumo de tokens em 50 sessões do Claude Code. O esgotamento do contexto degrada a qualidade antes de você perce…

5 min de leitura

Tutorial de Hooks do Claude Code: 5 hooks de produção do zero

Construa 5 hooks práticos do Claude Code do zero: auto-formatação, portões de segurança, execução de testes, alertas de …

9 min de leitura