Introdução

Os hooks do Claude Code são comandos de shell definidos pelo usuário que executam em vários pontos do ciclo de vida do Claude Code. Os hooks fornecem controle determinístico sobre o comportamento do Claude Code, garantindo que certas ações sempre aconteçam em vez de depender do LLM para escolher executá-las.

Exemplos de casos de uso incluem:

  • Notificações: Personalize como você é notificado quando o Claude Code está aguardando sua entrada ou permissão para executar algo.
  • Formatação automática: Execute prettier em arquivos .ts, gofmt em arquivos .go, etc. após cada edição de arquivo.
  • Registro: Rastreie e conte todos os comandos executados para conformidade ou depuração.
  • Feedback: Forneça feedback automatizado quando o Claude Code produz código que não segue as convenções da sua base de código.
  • Permissões personalizadas: Bloqueie modificações em arquivos de produção ou diretórios sensíveis.

Ao codificar essas regras como hooks em vez de instruções de prompt, você transforma sugestões em código de nível de aplicativo que executa toda vez que é esperado que execute.

Os hooks executam comandos de shell com suas permissões completas de usuário sem confirmação. Você é responsável por garantir que seus hooks sejam seguros e protegidos. A Anthropic não é responsável por qualquer perda de dados ou danos ao sistema resultantes do uso de hooks. Revise Considerações de Segurança.

Início Rápido

Neste início rápido, você adicionará um hook que registra os comandos de shell que o Claude Code executa.

Pré-requisito do Início Rápido: Instale jq para processamento JSON na linha de comando.

Passo 1: Abrir configuração de hooks

Execute o comando slash /hooks e selecione o evento de hook PreToolUse.

Os hooks PreToolUse executam antes das chamadas de ferramenta e podem bloqueá-las enquanto fornecem feedback ao Claude sobre o que fazer diferente.

Passo 2: Adicionar um matcher

Selecione + Add new matcher… para executar seu hook apenas em chamadas de ferramenta Bash.

Digite Bash para o matcher.

Passo 3: Adicionar o hook

Selecione + Add new hook… e insira este comando:

jq -r '"\(.tool_input.command) - \(.tool_input.description // "No description")"' >> ~/.claude/bash-command-log.txt

Passo 4: Salvar sua configuração

Para localização de armazenamento, selecione User settings já que você está registrando em seu diretório home. Este hook então se aplicará a todos os projetos, não apenas ao seu projeto atual.

Em seguida, pressione Esc até retornar ao REPL. Seu hook agora está registrado!

Passo 5: Verificar seu hook

Execute /hooks novamente ou verifique ~/.claude/settings.json para ver sua configuração:

"hooks": {
  "PreToolUse": [
    {
      "matcher": "Bash",
      "hooks": [
        {
          "type": "command",
          "command": "jq -r '\"\\(.tool_input.command) - \\(.tool_input.description // \"No description\")\"' >> ~/.claude/bash-command-log.txt"
        }
      ]
    }
  ]
}

Configuração

Os hooks do Claude Code são configurados em seus arquivos de configurações:

  • ~/.claude/settings.json - Configurações do usuário
  • .claude/settings.json - Configurações do projeto
  • .claude/settings.local.json - Configurações locais do projeto (não commitadas)
  • Configurações de política gerenciada empresarial

Estrutura

Os hooks são organizados por matchers, onde cada matcher pode ter múltiplos hooks:

{
  "hooks": {
    "EventName": [
      {
        "matcher": "ToolPattern",
        "hooks": [
          {
            "type": "command",
            "command": "your-command-here"
          }
        ]
      }
    ]
  }
}
  • matcher: Padrão para corresponder nomes de ferramentas (aplicável apenas para PreToolUse e PostToolUse)
    • Strings simples correspondem exatamente: Write corresponde apenas à ferramenta Write
    • Suporta regex: Edit|Write ou Notebook.*
    • Se omitido ou string vazia, hooks executam para todos os eventos correspondentes
  • hooks: Array de comandos para executar quando o padrão corresponde
    • type: Atualmente apenas "command" é suportado
    • command: O comando bash para executar
    • timeout: (Opcional) Por quanto tempo um comando deve executar, em segundos, antes de cancelar todos os hooks em progresso.

Eventos de Hook

PreToolUse

Executa após o Claude criar parâmetros de ferramenta e antes de processar a chamada da ferramenta.

Matchers comuns:

  • Task - Tarefas do agente
  • Bash - Comandos de shell
  • Glob - Correspondência de padrão de arquivo
  • Grep - Busca de conteúdo
  • Read - Leitura de arquivo
  • Edit, MultiEdit - Edição de arquivo
  • Write - Escrita de arquivo
  • WebFetch, WebSearch - Operações web

PostToolUse

Executa imediatamente após uma ferramenta completar com sucesso.

Reconhece os mesmos valores de matcher que PreToolUse.

Notification

Executa quando o Claude Code envia notificações.

Stop

Executa quando o agente principal do Claude Code terminou de responder.

SubagentStop

Executa quando um subagente do Claude Code (chamada de ferramenta Task) terminou de responder.

Entrada de Hook

Os hooks recebem dados JSON via stdin contendo informações da sessão e dados específicos do evento:

{
  // Campos comuns
  session_id: string
  transcript_path: string  // Caminho para JSON da conversa

  // Campos específicos do evento
  ...
}

Entrada PreToolUse

O esquema exato para tool_input depende da ferramenta.

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.txt",
    "content": "file content"
  }
}

Entrada PostToolUse

O esquema exato para tool_input e tool_response depende da ferramenta.

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "tool_name": "Write",
  "tool_input": {
    "file_path": "/path/to/file.txt",
    "content": "file content"
  },
  "tool_response": {
    "filePath": "/path/to/file.txt",
    "success": true
  }
}

Entrada Notification

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "message": "Task completed successfully",
  "title": "Claude Code"
}

Entrada Stop e SubagentStop

stop_hook_active é verdadeiro quando o Claude Code já está continuando como resultado de um hook de parada. Verifique este valor ou processe a transcrição para evitar que o Claude Code execute indefinidamente.

{
  "session_id": "abc123",
  "transcript_path": "~/.claude/projects/.../00893aaf-19fa-41d2-8238-13269b9b3ca0.jsonl",
  "stop_hook_active": true
}

Saída de Hook

Existem duas maneiras para os hooks retornarem saída de volta ao Claude Code. A saída comunica se deve bloquear e qualquer feedback que deve ser mostrado ao Claude e ao usuário.

Simples: Código de Saída

Os hooks comunicam status através de códigos de saída, stdout e stderr:

  • Código de saída 0: Sucesso. stdout é mostrado ao usuário no modo de transcrição (CTRL-R).
  • Código de saída 2: Erro de bloqueio. stderr é alimentado de volta ao Claude para processar automaticamente. Veja comportamento por evento de hook abaixo.
  • Outros códigos de saída: Erro não bloqueante. stderr é mostrado ao usuário e a execução continua.

Lembrete: O Claude Code não vê stdout se o código de saída for 0.

Comportamento do Código de Saída 2

Evento de HookComportamento
PreToolUseBloqueia a chamada da ferramenta, mostra erro ao Claude
PostToolUseMostra erro ao Claude (ferramenta já executou)
NotificationN/A, mostra stderr apenas ao usuário
StopBloqueia parada, mostra erro ao Claude
SubagentStopBloqueia parada, mostra erro ao subagente Claude

Avançado: Saída JSON

Os hooks podem retornar JSON estruturado em stdout para controle mais sofisticado:

Campos JSON Comuns

Todos os tipos de hook podem incluir estes campos opcionais:

{
  "continue": true, // Se Claude deve continuar após execução do hook (padrão: true)
  "stopReason": "string" // Mensagem mostrada quando continue é false
  "suppressOutput": true, // Ocultar stdout do modo de transcrição (padrão: false)
}

Se continue for false, Claude para de processar após os hooks executarem.

  • Para PreToolUse, isso é diferente de "decision": "block", que apenas bloqueia uma chamada de ferramenta específica e fornece feedback automático ao Claude.
  • Para PostToolUse, isso é diferente de "decision": "block", que fornece feedback automatizado ao Claude.
  • Para Stop e SubagentStop, isso tem precedência sobre qualquer saída "decision": "block".
  • Em todos os casos, "continue" = false tem precedência sobre qualquer saída "decision": "block".

stopReason acompanha continue com uma razão mostrada ao usuário, não mostrada ao Claude.

Controle de Decisão PreToolUse

Os hooks PreToolUse podem controlar se uma chamada de ferramenta prossegue.

  • “approve” contorna o sistema de permissão. reason é mostrado ao usuário mas não ao Claude.
  • “block” impede que a chamada da ferramenta execute. reason é mostrado ao Claude.
  • undefined leva ao fluxo de permissão existente. reason é ignorado.
{
  "decision": "approve" | "block" | undefined,
  "reason": "Explicação para decisão"
}

Controle de Decisão PostToolUse

Os hooks PostToolUse podem controlar se uma chamada de ferramenta prossegue.

  • “block” automaticamente solicita ao Claude com reason.
  • undefined não faz nada. reason é ignorado.
{
  "decision": "block" | undefined,
  "reason": "Explicação para decisão"
}

Controle de Decisão Stop/SubagentStop

Os hooks Stop e SubagentStop podem controlar se Claude deve continuar.

  • “block” impede que Claude pare. Você deve preencher reason para Claude saber como proceder.
  • undefined permite que Claude pare. reason é ignorado.
{
  "decision": "block" | undefined,
  "reason": "Deve ser fornecido quando Claude é impedido de parar"
}

Exemplo de Saída JSON: Edição de Comando Bash

#!/usr/bin/env python3
import json
import re
import sys

# Define regras de validação como uma lista de tuplas (padrão regex, mensagem)
VALIDATION_RULES = [
    (
        r"\bgrep\b(?!.*\|)",
        "Use 'rg' (ripgrep) em vez de 'grep' para melhor performance e recursos",
    ),
    (
        r"\bfind\s+\S+\s+-name\b",
        "Use 'rg --files | rg pattern' ou 'rg --files -g pattern' em vez de 'find -name' para melhor performance",
    ),
]


def validate_command(command: str) -> list[str]:
    issues = []
    for pattern, message in VALIDATION_RULES:
        if re.search(pattern, command):
            issues.append(message)
    return issues


try:
    input_data = json.load(sys.stdin)
except json.JSONDecodeError as e:
    print(f"Erro: Entrada JSON inválida: {e}", file=sys.stderr)
    sys.exit(1)

tool_name = input_data.get("tool_name", "")
tool_input = input_data.get("tool_input", {})
command = tool_input.get("command", "")

if tool_name != "Bash" or not command:
    sys.exit(1)

# Validar o comando
issues = validate_command(command)

if issues:
    for message in issues:
        print(f"• {message}", file=sys.stderr)
    # Código de saída 2 bloqueia chamada de ferramenta e mostra stderr ao Claude
    sys.exit(2)

Trabalhando com Ferramentas MCP

Os hooks do Claude Code funcionam perfeitamente com ferramentas do Model Context Protocol (MCP). Quando servidores MCP fornecem ferramentas, elas aparecem com um padrão de nomenclatura especial que você pode corresponder em seus hooks.

Nomenclatura de Ferramenta MCP

As ferramentas MCP seguem o padrão mcp__<servidor>__<ferramenta>, por exemplo:

  • mcp__memory__create_entities - Ferramenta de criar entidades do servidor de memória
  • mcp__filesystem__read_file - Ferramenta de ler arquivo do servidor de sistema de arquivos
  • mcp__github__search_repositories - Ferramenta de busca do servidor GitHub

Configurando Hooks para Ferramentas MCP

Você pode direcionar ferramentas MCP específicas ou servidores MCP inteiros:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "mcp__memory__.*",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Operação de memória iniciada' >> ~/mcp-operations.log"
          }
        ]
      },
      {
        "matcher": "mcp__.*__write.*",
        "hooks": [
          {
            "type": "command",
            "command": "/home/user/scripts/validate-mcp-write.py"
          }
        ]
      }
    ]
  }
}

Exemplos

Formatação de Código

Formate automaticamente código após modificações de arquivo:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Write|Edit|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "/home/user/scripts/format-code.sh"
          }
        ]
      }
    ]
  }
}

Notificação

Personalize a notificação que é enviada quando o Claude Code solicita permissão ou quando a entrada do prompt ficou inativa.

{
  "hooks": {
    "Notification": [
      {
        "matcher": "",
        "hooks": [
          {
            "type": "command",
            "command": "python3 ~/my_custom_notifier.py"
          }
        ]
      }
    ]
  }
}

Considerações de Segurança

Isenção de Responsabilidade

USE POR SUA PRÓPRIA CONTA E RISCO: Os hooks do Claude Code executam comandos de shell arbitrários em seu sistema automaticamente. Ao usar hooks, você reconhece que:

  • Você é o único responsável pelos comandos que configura
  • Os hooks podem modificar, excluir ou acessar qualquer arquivo que sua conta de usuário possa acessar
  • Hooks maliciosos ou mal escritos podem causar perda de dados ou danos ao sistema
  • A Anthropic não fornece garantia e não assume responsabilidade por quaisquer danos resultantes do uso de hooks
  • Você deve testar completamente os hooks em um ambiente seguro antes do uso em produção

Sempre revise e entenda quaisquer comandos de hook antes de adicioná-los à sua configuração.

Melhores Práticas de Segurança

Aqui estão algumas práticas principais para escrever hooks mais seguros:

  1. Validar e sanitizar entradas - Nunca confie cegamente nos dados de entrada
  2. Sempre colocar variáveis de shell entre aspas - Use "$VAR" não $VAR
  3. Bloquear travessia de caminho - Verifique por .. em caminhos de arquivo
  4. Usar caminhos absolutos - Especifique caminhos completos para scripts
  5. Pular arquivos sensíveis - Evite .env, .git/, chaves, etc.

Segurança de Configuração

Edições diretas de hooks em arquivos de configurações não têm efeito imediatamente. O Claude Code:

  1. Captura um snapshot dos hooks na inicialização
  2. Usa este snapshot durante toda a sessão
  3. Avisa se hooks são modificados externamente
  4. Requer revisão no menu /hooks para que as mudanças se apliquem

Isso impede que modificações maliciosas de hook afetem sua sessão atual.

Detalhes de Execução de Hook

  • Timeout: Limite de execução de 60 segundos por padrão, configurável por comando.
    • Se qualquer comando individual expirar, todos os hooks em progresso são cancelados.
  • Paralelização: Todos os hooks correspondentes executam em paralelo
  • Ambiente: Executa no diretório atual com o ambiente do Claude Code
  • Entrada: JSON via stdin
  • Saída:
    • PreToolUse/PostToolUse/Stop: Progresso mostrado na transcrição (Ctrl-R)
    • Notification: Registrado apenas para debug (--debug)

Depuração

Para solucionar problemas de hooks:

  1. Verifique se o menu /hooks exibe sua configuração
  2. Verifique se seus arquivos de configurações são JSON válido
  3. Teste comandos manualmente
  4. Verifique códigos de saída
  5. Revise expectativas de formato de stdout e stderr
  6. Garanta escape adequado de aspas
  7. Use claude --debug para depurar seus hooks. A saída de um hook bem-sucedido aparece como abaixo.
[DEBUG] Executing hooks for PostToolUse:Write
[DEBUG] Getting matching hook commands for PostToolUse with query: Write
[DEBUG] Found 1 hook matchers in settings
[DEBUG] Matched 1 hooks for query "Write"
[DEBUG] Found 1 hook commands to execute
[DEBUG] Executing hook command: <Your command> with timeout 60000ms
[DEBUG] Hook command completed with status 0: <Your stdout>

Mensagens de progresso aparecem no modo de transcrição (Ctrl-R) mostrando:

  • Qual hook está executando
  • Comando sendo executado
  • Status de sucesso/falha
  • Mensagens de saída ou erro