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

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
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
- O evento: o ponto do ciclo de vida onde a coisa dispara (ex:
PreToolUseouStop) - O matcher: o filtro de quando dispara de verdade (ex: só quando a ferramenta for
Bash) - 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 stdinhttp: envia o JSON como POST pra uma URLmcp_tool: chama uma ferramenta de um servidor MCP já conectadoprompt: manda um prompt pro modelo Claude pra uma decisão sim/não em turno únicoagent: 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
- 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
- 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
- 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.
Formações
Formação Vibe Coding
Do Prompt ao Produto: Crie Software Real com IA
- 474 aulas
- 20 projetos
- 39h 27min
Blog | Mais populares
As diferenças de var, let e const
Como fazer redirecionamento com PHP
Neste artigo você vai aprender a como fazer redirecionamento com PHP, utilizaremos abordagens fáceis de entender e de aplicar Fala programador(a), beleza? Bora aprender mais […]
Checklist de segurança n8n VPS pública: guia essencial para proteger sua instalação
Checklist de segurança n8n VPS pública: guia essencial para proteger sua instalação A popularidade da automação de processos com o n8n está em alta, principalmente […]
