MÓDULO 5.1

⚡ Hooks como interrupts do OS

SessionStart, PreToolUse, PostToolUse, Stop, PreCompact. O lifecycle do Claude Code que dá previsibilidade ao não-determinístico.

6
Tópicos
50
Minutos
Médio
Nível
Prático
Tipo
1

📚 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.
2

🚀 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.

3

🛡️ 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
4

📝 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.

5

🛑 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.

6

📦 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

Hooks = interrupts do OS — 10+ eventos no lifecycle do Claude Code
SessionStart — bootstrap de contexto, Silver Platters, conversões automáticas
PreToolUse — gate de segurança, exit 2 bloqueia, exit 0 libera
PostToolUse — audit trail, drift detection, webhooks assíncronos
Stop / StopFailure — Definition of Done imposto pelo sistema
PreCompact — contexto sticky que sobrevive à compactação

Próximo Módulo:

5.2 — n8n e Make como linguagens complementares