O que é hook no Claude Code e pra que serve na sua rotina?

ilustração explicando o que é um Claude Code hook e como ele automatiza tarefas na rotina
Resposta rápida

Um Claude Code hook é um handler definido por você (comando shell, endpoint HTTP ou prompt de modelo) que roda automaticamente em pontos específicos do ciclo de vida do Claude Code. A diferença pro resto: quem dispara é o evento, não a decisão do modelo. Você escolhe o evento (PreToolUse, PostToolUse, Stop, SessionStart e outros), adiciona um matcher que filtra quando dispara e define o handler que executa. Na prática isso troca lembrete manual por automação: formatar arquivo depois de toda edição, inspecionar comando Bash antes de rodar, injetar contexto no início da sessão

Fala aí, beleza? Tu não precisa lembrar de rodar o formatador depois de cada edição, o Claude Code pode disparar isso sozinho 🙂

Esse post é pra quem já passou do básico, já usa a ferramenta no dia a dia e agora quer automatizar as verificações em vez de ficar de babá do processo

E a ideia central do hook é essa: ele é um handler definido por você (comando shell, endpoint HTTP ou prompt de modelo) que executa automaticamente em pontos específicos do ciclo de vida do Claude Code

Se liga no detalhe que muda tudo: quem dispara é o EVENTO do ciclo de vida, não a decisão do modelo

Ou seja, não é você pedir "roda o lint aí" e torcer pra ele lembrar, é o evento acontecer e o handler rodar, sempre

Se você ainda tá chegando agora e quer o panorama antes, dá uma olhada no post sobre o que é o Claude Code e depois volta aqui

Bora entender a anatomia?

Domine o Claude Code do básico ao avançado
Pré-inscrição Formação Claude Code

Domine o Claude Code do básico ao avançado

Você vai aprender a criar sistemas completos com Claude Code, sem precisar ser programador. Inscreva-se para ter acesso a um desconto de lançamento e bônus especiais!

Como um hook funciona: evento, matcher e handler

A configuração de um hook tem três níveis de aninhamento, e é só isso mesmo

  1. O evento: o ponto do ciclo de vida onde a coisa dispara (ex: PreToolUse ou Stop)
  2. O matcher: o filtro de quando dispara de verdade (ex: só quando a ferramenta for Bash)
  3. O handler: um ou mais, é o que efetivamente roda quando casar

Se você conhece evento e callback em JavaScript, é bem semelhante: alguém emite, você escuta, você reage

Que tipos de handler existem?

Pergunta justa, porque handler aqui não é só "roda um comando". São cinco tipos, segundo a referência oficial de hooks:

  • command: roda um comando shell e recebe o JSON do evento no stdin
  • http: envia o JSON como POST pra uma URL
  • mcp_tool: chama uma ferramenta de um servidor MCP já conectado
  • prompt: manda um prompt pro modelo Claude pra uma decisão sim/não em turno único
  • agent: verificação multi-turno com acesso a ferramentas, e esse é experimental

O mcp_tool é topzera pra quem já tem servidor plugado, porque ele reaproveita o que você configurou pra conectar ferramentas externas via MCP e transforma aquilo em reação automática a evento

E quais eventos eu posso escutar?

A referência do Claude Code documenta estes: SessionStart, UserPromptSubmit, UserPromptExpansion, PreToolUse, PermissionRequest, PostToolUse, PostToolUseFailure, Notification, SubagentStart, SubagentStop, Stop, StopFailure, PreCompact, PostCompact, TeammateIdle, TaskCompleted e ConfigChange

É MUITA superfície pra encaixar verificação, e a maioria das pessoas usa dois ou três

E o handler não roda no vácuo: o payload JSON que ele recebe carrega o contexto do evento

Em PreToolUse e PostToolUse, por exemplo, vem session_id, tool_name e tool_input, e no PostToolUse vem também a saída da ferramenta

É desse payload que sai a mágica do exemplo de formatação que a gente vai ver mais pra frente 😀

PreToolUse x PostToolUse: qual evento usar em cada caso

Esses dois são os que mais aparecem, e a confusão entre eles é a fonte de metade da frustração de quem tá começando

Critério PreToolUse PostToolUse
Momento Antes de a ferramenta executar Depois da execução da ferramenta
Pode bloquear? Sim, inspeciona e pode barrar a ação Não desfaz nada, a ferramenta já rodou
Uso típico Inspecionar comando Bash e bloquear padrão inseguro, ou liberar a execução Rodar formatador, registrar log, devolver mensagem de falha
Relação com permissão Dispara antes de qualquer checagem do modo de permissão, incluindo dontAsk Roda depois, sem poder de veto
Caso extremo Um permissionDecision: "deny" bloqueia a ferramenta até em bypassPermissions ou com --dangerously-skip-permissions Só consegue reagir ao que já aconteceu

Repara nessa última linha, porque ela é forte: o PreToolUse é o único lugar onde tu tem poder de veto de verdade

Já o PostToolUse é o lugar do "arruma" e do "registra", não do "impede"

Escolheu errado o evento, o hook até roda, só não faz o que você imaginava…

Pra que serve um hook na rotina de quem já usa Claude Code

Teoria é legal, mas o que muda no dia?

1. Formatar arquivo sozinho depois de toda edição

Esse é o caso clássico e tem exemplo oficial: um hook PostToolUse que roda o Prettier depois de toda edição de arquivo

O que isso substitui? O lembrete manual de "depois eu formato", que ninguém cumpre 100% das vezes

2. Barrar comando Bash inseguro antes de rodar

Com PreToolUse dá pra inspecionar o comando Bash antes de ele executar, bloquear padrões inseguros ou liberar

Os rm -rf da vida agradecem, né?

E como esse evento dispara antes de qualquer checagem do modo de permissão, ele continua valendo mesmo naquelas sessões em que você afrouxou tudo

3. Injetar contexto no começo da sessão ou no envio do prompt

Aqui tem uma pegadinha ótima: o stdout do hook vira contexto visível pro Claude em apenas três eventos, UserPromptSubmit, UserPromptExpansion e SessionStart

Então se a tua ideia é "toda sessão começa sabendo X", é nesses eventos que tu encaixa

Substitui aquele hábito de colar o mesmo bloco de contexto na mão toda vez que abre o terminal

4. Avisar um sistema externo sem escrever integração

O handler http manda o JSON do evento como POST pra uma URL

Dá pra pendurar isso num evento de fim de tarefa, tipo Stop ou TaskCompleted, e deixar o aviso sair sozinho em vez de você lembrar de avisar

5. Padronizar o time distribuindo hooks num plugin

Hooks podem ser empacotados dentro de um plugin do Claude Code: uma pasta hooks/ na RAIZ do plugin, com um arquivo hooks.json no mesmo formato do objeto hooks do settings

Tome cuidado! Isso NÃO vai dentro de .claude-plugin/, que é onde mora o plugin.json

E aí o hook deixa de ser a mania pessoal de um dev e vira padrão do time, junto com slash commands, subagents e servidores MCP que o plugin também distribui

Como configurar seu primeiro hook no Claude Code

Bora ver na prática? Vou seguir o exemplo oficial de formatação, que é o mais fácil de sentir o efeito

  1. Decida o nível do settings

Os hooks são definidos em arquivos JSON de settings: ~/.claude/settings.json é nível usuário e vale em todo projeto, e .claude/settings.json é nível projeto e vai versionado com o repositório (também existe o settings.local.json)

A regra prática: se o hook faz sentido pro time, ele mora no projeto e entra no git

O erro comum deste passo é colocar no nível usuário algo que só faz sentido em um repo, e aí o hook começa a disparar em projeto que não tem nada a ver

  1. Escreva o objeto hooks com evento, matcher e handler

No .claude/settings.json da raiz do projeto:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}

Lê de dentro pra fora: o evento é PostToolUse, o matcher é Edit|Write e o handler é um command que pega o file_path de dentro do payload JSON e joga pro Prettier

O erro comum deste passo é esperar que Edit|Write dispare em outras ferramentas: ele dispara só quando o Claude usa Edit ou Write, e NÃO dispara em Bash, Read ou qualquer outra

  1. Confira no /hooks

Dentro do Claude Code, o comando /hooks abre um navegador dos hooks configurados: mostra cada evento com a contagem de hooks, deixa entrar nos matchers e ver o detalhe de cada handler, inclusive de qual arquivo de settings ele veio

Esse último detalhe é ouro quando você tem hook em três níveis e não sabe de onde veio aquele que tá te incomodando

O erro comum deste passo é achar que o /hooks edita: ele é SOMENTE LEITURA. Pra adicionar, alterar ou remover, tem que editar o JSON de settings (ou pedir pro próprio Claude editar)

E uma boa notícia pra fechar: o Claude Code observa os arquivos de settings e recarrega quando eles mudam, então edição na maioria das chaves já vale na sessão em andamento, sem reiniciar 😀

Erros comuns de hook (e como prevenir)

Sintoma: o hook rodou, mas o Claude não viu a saída

Causa: o stdout do hook só vira contexto visível pro Claude em UserPromptSubmit, UserPromptExpansion e SessionStart

Nos demais eventos o stdout vai pro log de debug e não aparece no transcript

Prevenção: se a intenção era ALIMENTAR o Claude com informação, escolhe um desses três eventos. Se era só rodar um comando, tá tudo certo, o silêncio é esperado

Sintoma: o JSON de controle do hook foi simplesmente ignorado

Causa: o hook do tipo command se comunica de volta por código de saída

No exit 0 o Claude Code lê o stdout procurando JSON de controle. No exit 2 é erro bloqueante: o stdout (e qualquer JSON nele) é IGNORADO, e o que volta pro Claude como mensagem de erro é o texto do stderr

Prevenção: escolhe uma abordagem por hook, não as duas. Ou tu fala por JSON no exit 0, ou tu bloqueia com exit 2 escrevendo no stderr

Sintoma: o hook do time "sumiu" (ou você achou que tinha desligado tudo)

Causa: as entradas de hook SOMAM entre os níveis de settings em vez de substituir umas às outras

User, project e local adicionam os hooks deles sem remover os gerenciados (managed). Então aquele hook que você não lembra de ter escrito pode estar vindo de outro nível

E tem mais: disableAllHooks definido em user, project ou local NÃO desativa hooks vindos de managed settings, só o disableAllHooks no nível managed desativa os gerenciados

Prevenção: usa o /hooks pra ver de qual arquivo cada handler veio antes de sair caçando fantasma

E fecha com a recomendação que a própria documentação faz: revise os hooks antes de usar em ambiente compartilhado ou de produção

Hook é código que roda sozinho, então merece o mesmo olhar que tu daria pra qualquer script no seu terminal

O que eu aprendi usando Claude Code no dia a dia

No vídeo abaixo eu mostro os hooks dentro de uma rotina maior de uso profissional da ferramenta, ao lado das skills e dos slash commands criados na pasta do projeto

O que eu tento passar lá é justamente isso que a gente viu aqui: hook não é algo que tu aciona na mão, é algo que dispara em pontos determinados da execução

A anatomia que eu descrevo é fixa e simples: o ponto de disparo e o que vai ser feito ali

Os pontos que eu uso no vídeo são depois da ferramenta ser executada, antes da ferramenta ser executada, quando o Claude notifica o usuário e quando o Claude termina uma tarefa

Meu exemplo é um hook que roda um linter pra verificar falhas de código JavaScript toda vez que o Claude executa uma mudança de código

Esse hook de lint eu considero universal, serve de ponto de partida pra praticamente qualquer projeto

Eu deixo ele já configurado antes da demonstração, no settings.local.json, e o Claude roda ele depois da próxima modificação no projeto, sem eu pedir nada

E a partir desses pontos de disparo dá pra criar outros hooks pra outras funcionalidades, é só questão de decidir o que você quer verificar e onde

Pra mim é isso que separa o uso amador do profissional: encaixar verificação automática exatamente nos pontos importantes da execução deixa o projeto MUITO mais robusto, sem depender de você lembrar de rodar nada

Próximo passo: escolha um lembrete manual e vire hook

O exercício é esse, e é bem direto: pensa num "não esquecer de" que mora na tua cabeça hoje

Formatar depois de editar, rodar o lint, checar comando perigoso, carregar o mesmo contexto toda vez que abre a sessão

Pega UM deles e transforma em evento

Meu palpite de começo é o hook de formatação em PostToolUse no .claude/settings.json do projeto, porque ele é curto, tem exemplo oficial e o efeito aparece na primeira edição que o Claude fizer

Depois abre o /hooks e confere se ele tá lá, no evento certo, vindo do arquivo certo

E quando o teu conjunto de hooks estabilizar, dá pra empacotar tudo num plugin (pasta hooks/ na raiz, com o hooks.json) e distribuir pro time inteiro em vez de pedir pra cada um copiar JSON na mão

É assim que lembrete vira automação, beleza?

Até o próximo post! 🙂

Perguntas frequentes

Onde ficam configurados os hooks do Claude Code?

Em arquivos JSON de settings: o ~/.claude/settings.json vale em todo projeto (nível usuário) e o .claude/settings.json vale só naquele repositório, geralmente versionado com o código. Também existe o settings.local.json. As entradas de hook desses níveis somam entre si em vez de se substituírem, então um hook do projeto não apaga um hook definido no nível usuário.

O comando /hooks serve pra criar ou editar um hook?

Não, o /hooks abre só um navegador de leitura dos hooks já configurados. Ele mostra cada evento com a contagem de hooks e deixa entrar nos matchers pra ver o detalhe de cada handler, incluindo de qual arquivo de settings ele veio. Pra adicionar, alterar ou remover, o caminho é editar o JSON de settings direto, ou pedir pro próprio Claude editar.

Como um hook do tipo command avisa o Claude Code se deu certo ou errado?

Pelo código de saída: exit 0 é sucesso, e aí o Claude Code lê o stdout procurando um JSON de controle. Exit 2 é erro bloqueante, o stdout é ignorado e o texto do stderr volta pro Claude como mensagem de erro. Então dá pra escolher uma abordagem por hook, não misturar as duas no mesmo handler.

Dá pra desativar todos os hooks de uma vez no Claude Code?

Existe a configuração disableAllHooks, mas ela tem uma pegadinha de precedência: definida em user, project ou local, ela NÃO desativa hooks vindos de managed settings. Só o disableAllHooks no próprio nível managed desativa os hooks gerenciados.

Preciso reiniciar o Claude Code depois de editar um hook no settings.json?

Não precisa. O Claude Code observa os arquivos de settings e recarrega quando eles mudam, e edições na maioria das chaves já valem na sessão em andamento.

Um hook PreToolUse consegue bloquear até em modo bypassPermissions?

Consegue. Hooks PreToolUse disparam antes de qualquer checagem do modo de permissão, incluindo o dontAsk, e um hook que devolve permissionDecision: "deny" bloqueia a ferramenta até em bypassPermissions ou rodando com –dangerously-skip-permissions.




Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted

Formações

Formação Vibe Coding

Formação Vibe Coding

Do Prompt ao Produto: Crie Software Real com IA

  • 474 aulas
  • 20 projetos
  • 39h 27min

Blog | Mais populares