📚 O catálogo de hooks
Em sistemas operacionais, interrupts são sinais que o kernel intercepta antes de deixar o hardware agir livremente. Hooks do Claude Code são exatamente isso: pontos de interrupção no lifecycle do agente onde você injeta lógica determinística num sistema intrinsecamente não-determinístico.
📋 Catálogo completo de hooks
- •SessionStart — dispara ao iniciar qualquer sessão Claude Code.
- •PreToolUse — antes de cada chamada de ferramenta. Pode bloquear com exit code 2.
- •PostToolUse — após tool executar. Ideal para log e auditoria.
- •PostToolUseFailure — quando tool falha. Alertas e rollback.
- •UserPromptSubmit — quando usuário envia prompt. Enriquecimento automático.
- •Stop / StopFailure — quando Claude acha que terminou. Gate de qualidade.
- •SubagentStop — quando subagente termina. Coordenação multi-agente.
- •PreCompact — antes de compactar contexto. Preservar dados críticos.
- •Notification — Claude envia notificação ao usuário.
💡 Exit codes que controlam tudo
- Exit 0 — sucesso, continua normalmente.
- Exit 1 — erro no hook, Claude ignora e continua.
- Exit 2 — bloqueia a ação. PreToolUse com exit 2 impede a tool de rodar.
🚀 SessionStart — injetar contexto
Toda sessão começa "em branco". O SessionStart resolve isso: carrega Silver Platters, converte arquivos, define variáveis de contexto. É o equivalente ao script de inicialização do sistema — roda uma vez, no começo, de forma invisível.
💻 Exemplo real: bootstrap de contexto
#!/bin/bash
# .claude/hooks/session-start.sh
# Carrega Silver Platters
cat /workspace/context/company-brief.md >> /tmp/session-context.md
cat /workspace/context/active-projects.md >> /tmp/session-context.md
# Converte planilhas para MD se existirem
find /workspace/data -name "*.xlsx" -newer /tmp/.last-convert \
| xargs -I{} python3 convert-xlsx.py {}
# Injeta data atual
echo "## Sessão iniciada em: $(date '+%Y-%m-%d %H:%M')" >> /tmp/session-context.md
touch /tmp/.last-convert
exit 0
💡 Caso de uso: Marco (CFO)
Marco configura SessionStart para carregar o brief financeiro semanal, estado atual do pipeline e alertas pendentes. Toda sessão com o CFO Bot começa com 3 páginas de contexto rico — sem Marco precisar lembrar de copiar nada.
🛡️ PreToolUse — gate antes de agir
Antes de cada tool call, o Claude passa pelo PreToolUse. É a última linha de defesa antes de uma ação irreversível. Você pode inspecionar qual tool vai rodar, com quais argumentos, e decidir: passa, bloqueia ou redireciona.
💻 Exemplo: bloqueio de paths proibidos
#!/bin/bash
# .claude/hooks/pre-tool-use.sh
# Recebe JSON via stdin com tool_name e tool_input
TOOL=$(cat /dev/stdin | jq -r '.tool_name')
INPUT=$(cat /dev/stdin | jq -r '.tool_input // ""')
# Bloqueia acesso a dados financeiros via Bash
if [[ "$TOOL" == "Bash" ]]; then
if echo "$INPUT" | grep -q "/financials/\|/billing/"; then
echo "BLOQUEADO: acesso a dados financeiros requer aprovação" >&2
exit 2
fi
fi
# Bloqueia git push --force
if [[ "$TOOL" == "Bash" ]] && echo "$INPUT" | grep -q "push --force\|push -f"; then
echo "BLOQUEADO: force push não permitido" >&2
exit 2
fi
exit 0
✓ Bons usos do PreToolUse
- ✓Validar paths de acesso
- ✓Bloquear comandos destrutivos
- ✓Log de auditoria preventivo
- ✓Rate limiting por ferramenta
✗ Anti-padrões
- ✗Hook que leva >2s (bloqueia UI)
- ✗Exit 2 em todo erro (para tudo)
- ✗Lógica complexa sem teste
- ✗Depender de serviço externo frágil
📝 PostToolUse — log e auditoria
Depois que a tool executa, o PostToolUse recebe o resultado. É onde você constrói o audit trail, detecta drift, dispara webhooks e valida outputs antes do Claude continuar. Pense nele como o kernel registrando syscalls.
💻 Exemplo: audit trail estruturado
#!/bin/bash
# .claude/hooks/post-tool-use.sh
PAYLOAD=$(cat /dev/stdin)
TOOL=$(echo "$PAYLOAD" | jq -r '.tool_name')
INPUT=$(echo "$PAYLOAD" | jq -r '.tool_input // ""')
OUTPUT=$(echo "$PAYLOAD" | jq -r '.tool_output // ""')
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# Log estruturado JSONL
echo "{\"ts\":\"$TIMESTAMP\",\"tool\":\"$TOOL\",\"input\":$INPUT,\"status\":\"ok\"}" \
>> /var/log/agent-audit.jsonl
# Webhook para Slack se foi Write em produção
if [[ "$TOOL" == "Write" ]] && echo "$INPUT" | grep -q "/prod/"; then
curl -s -X POST "$SLACK_WEBHOOK" \
-d "{\"text\":\"⚠️ Agente escreveu em /prod/ — ts: $TIMESTAMP\"}" &
fi
exit 0
💡 Drift detection com PostToolUse
Sally (CMO) usa PostToolUse para detectar quando o agente edita arquivos fora do escopo `/marketing/`. Se o output incluir path de outra área, o hook registra um alerta de "escopo drift" no Slack — sem parar o agente, só sinalizando.
🛑 Stop e StopFailure — validação humana
Claude decide quando "terminou". Mas o critério de "pronto" do agente raramente é o critério da operação. O hook Stop com exit code 2 força o agente a continuar — é como o Definition of Done imposto pelo sistema, não pela esperança.
💻 Stop hook com checklist de qualidade
#!/bin/bash
# .claude/hooks/stop.sh
# Valida se o trabalho atende critérios antes de parar
TRANSCRIPT=$(cat /dev/stdin | jq -r '.transcript // ""')
# Verifica se testes foram rodados
if ! echo "$TRANSCRIPT" | grep -q "npm test\|pytest\|cargo test"; then
echo "REQUER: rode os testes antes de finalizar" >&2
exit 2
fi
# Verifica se há arquivos staged mas não commitados
if git diff --cached --quiet 2>/dev/null; then
: # ok, nada staged
else
echo "REQUER: commit as mudanças staged antes de finalizar" >&2
exit 2
fi
exit 0
📊 StopFailure — quando o agente falha
StopFailure dispara quando Claude para por erro (não por conclusão). É onde você captura a mensagem de falha, envia alerta, e opcionalmente dispara um agente de recuperação. Sana (ops) usa isso para garantir que nenhuma falha fique silenciosa.
📦 PreCompact — hook avançado de contexto
Quando o contexto fica grande, Claude compacta a janela. PreCompact roda antes disso acontecer: você injeta o que NÃO pode ser comprimido — decisões críticas, estado atual, identidade do projeto. É o que garante continuidade em sessões longas.
💻 PreCompact: injeta sticky context
#!/bin/bash
# .claude/hooks/pre-compact.sh
# Injeta contexto que não pode ser perdido na compactação
echo "=== CONTEXTO STICKY — NÃO COMPRIMIR ==="
echo "Projeto: $(cat .claude/project-name 2>/dev/null || echo 'N/A')"
echo "Estado: $(cat /tmp/agent-state.json 2>/dev/null || echo '{}')"
echo "Decisões desta sessão:"
cat /tmp/session-decisions.md 2>/dev/null || echo "(nenhuma)"
echo "Regras ativas:"
cat .claude/CLAUDE.md | head -20
echo "=== FIM CONTEXTO STICKY ==="
exit 0
⚠️ Anti-padrão: loop infinito de compactação
Se PreCompact injetar contexto grande demais, Claude compacta → fica cheio → compacta de novo. Evite: injete só o essencial (máx. 500 tokens). Arquivos completos ficam em disco, não no contexto sticky.
📋 Resumo do Módulo
Próximo Módulo:
5.2 — n8n e Make como linguagens complementares