← Todos os Posts

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

Construí 95 hooks para o Claude Code. Cada um existe porque algo deu errado primeiro. O git-safety-guardian existe porque o Claude fez force-push na 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

TL;DR

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


A arquitetura

O Claude Code expõe eventos de ciclo de vida onde hooks podem interceptar, modificar ou bloquear comportamentos:2

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 Limpeza de 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 Após a ferramenta concluir 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

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

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

Ou permite silenciosamente ao sair 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 uma branch compartilhada. Recuperei a partir de um backup local, mas o processo de recuperação de 4 horas me convenceu de que 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 intenção. Ele faz correspondência de padrões na string do comando. Simples, determinístico, impossível de contornar com prompts criativos. O agente ainda pode fazer force-push em branches de feature (às vezes legítimo), mas main/master estão permanentemente protegidas.4

Interceptações ao longo do tempo: 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 criação, gerou seus próprios subagentes. A recursão consumiu tokens de API a 10x a taxa normal. Encerrei a sessão manualmente após perceber 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 decisão-chave de design: Agentes herdam um orçamento de criação do pai em vez de incrementar 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 (impedem cadeias profundas-mas-estreitas que são perfeitamente seguras).5

Bloqueios ao longo do tempo: 23 tentativas de criaçã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 frase de abertura. O post parecia polido no meu editor, mas falhou em verificações básicas de qualidade que qualquer revisor humano perceberia.

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 dos 95 hooks

A arquitetura orientada por configuração

Meus hooks evoluíram de valores fixos no código 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 limites para configs JSON significou que eu poderia ajustar comportamento sem editar scripts bash. Quando precisei de consenso de 85% para segurança mas 50% para documentação, a mudança de configuração levou 30 segundos. Uma mudança no código exigiria edição, testes e redeploy.6

O padrão de camadas no ciclo de vida

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

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

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

Camada 3: Validação (PostToolUse) — Verificar se ações concluídas atendem padrões. Verificação de consenso pós-deliberação, registro de saídas.

Camada 4: Qualidade (Stop) — Portão para a saída final. Pride check, quality gate, reviewer stop gate.

Cada camada é independente. Se um hook PreToolUse falhar silenciosamente, o hook Stop ainda detecta problemas de qualidade. Defesa em profundidade, aplicada ao comportamento de agentes 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 acionam o hook. PreToolUse:Task é uma 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 do usuário (~/.claude/settings.json) — aplica-se a todos os projetos. Meus 95 hooks ficam aqui.
  2. Nível do projeto (.claude/settings.json) — adiciona hooks específicos do projeto.
  3. Frontmatter de skill/subagente — escopo limitado ao ciclo de vida de um componente específico.8

O que eu faria diferente

Começar 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. Eventualmente, podei até ficar apenas com os hooks que produziam valor real (preveniam incidentes reais, detectavam problemas reais de qualidade).

Orientado por configuração desde o dia um. Passei duas semanas refatorando limites fixos no código para configs JSON. Essa refatoração teria sido gratuita se eu tivesse começado com configs.

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


Principais aprendizados

Para desenvolvedores começando com hooks: - Comece com três hooks: segurança do git (PreToolUse:Bash), injeção de contexto (UserPromptSubmit) e portão de qualidade (Stop); adicione mais apenas quando tiver incidentes que os justifiquem - Use o framework de timing de decisões: 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 tenha as mesmas proteções - Acompanhe métricas dos hooks (operações bloqueadas, incidentes interceptados) para justificar o custo de manutenção - Revise os logs dos hooks mensalmente para identificar novos padrões que valham a pena automatizar


Referências


  1. Infraestrutura de hooks do autor. 95 hooks em 6 eventos de ciclo de vida, desenvolvidos ao longo de 9 meses (2025-2026). 

  2. Anthropic, “Claude Code Documentation,” 2025. Eventos de ciclo de vida dos hooks. 

  3. Anthropic, “Claude Code Documentation,” 2025. Formato JSON de entrada/saída dos 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 limites e regras dos 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 dos hooks.