Hooks no Claude Code: regras que sempre rodam
Tutorial em pt-BR dos hooks do Claude Code: rode comandos automáticos antes e depois de cada ferramenta, formate código, bloqueie comandos perigosos e force regras do projeto via settings.json.

Você já pediu pro Claude Code "roda o Prettier depois de editar" e, três mensagens adiante, ele esqueceu? Ou viu ele prestes a rodar um comando que você jurava ter proibido? O problema não é o Claude ser desatento. É que você está confiando numa instrução que o modelo pode seguir — em vez de uma regra que sempre roda.
Os hooks resolvem isso. São comandos de shell que o Claude Code dispara sozinho em pontos fixos do ciclo de vida: antes de uma ferramenta rodar, depois que ela termina, quando você manda um prompt, quando ele para de responder. A palavra-chave é determinístico: o hook não depende de o Claude lembrar. Ele acontece toda vez, e ponto.
Se você ainda está se ambientando, vale ter o Claude Code rodando no terminal antes de seguir. Daqui pra frente é configuração.
A ideia em uma frase
Um hook liga um evento do Claude Code a um comando seu. Quando o evento acontece, o comando roda. O Claude não escolhe — o gatilho é fixo.
Isso é o oposto de uma skill, que o Claude usa quando acha que faz sentido. Hook é pra quando a regra não pode depender de bom senso: formatar todo arquivo editado, barrar um comando destrutivo, avisar você quando ele terminou. Coisas que precisam ser garantidas, não sugeridas.
Onde os hooks moram
Tudo vive num arquivo de settings em JSON. Você escolhe o alcance pelo lugar:
~/.claude/settings.json— vale em todos os seus projetos..claude/settings.json— vale só naquele projeto e vai pro Git. Commitou, o time inteiro herda a mesma regra..claude/settings.local.json— regras pessoais daquele projeto, fora do versionamento (entra no.gitignore).
A estrutura é sempre a mesma, em três camadas: evento → matcher → comando. O evento é quando dispara; o matcher filtra qual ferramenta interessa; o comando é o que roda.
Os eventos que você mais vai usar
O Claude Code dispara hooks em vários pontos. Os principais:
PreToolUse— antes de uma ferramenta rodar. É o único que pode bloquear a ação.PostToolUse— depois que a ferramenta termina com sucesso. Perfeito pra formatar ou validar o que foi editado.UserPromptSubmit— quando você envia uma mensagem. Bom pra injetar contexto extra.Stop— quando o Claude termina de responder.Notification— quando ele precisa da sua atenção (pediu permissão, ficou ocioso).SessionStart/SessionEnd— começo e fim da sessão.
Cada hook recebe um JSON pelo stdin com o contexto: session_id, tool_name, tool_input, o diretório de trabalho, o modo de permissão atual. Seu script lê esse JSON e decide o que fazer.
Exemplo 1: formatar todo arquivo que o Claude editar
O caso mais comum. Toda vez que o Claude usar Edit ou Write, rode seu formatador. No .claude/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "npx prettier --write $CLAUDE_FILE_PATHS",
"timeout": 30
}
]
}
]
}
}Repare no matcher Edit|Write: ele só dispara nessas duas ferramentas. Quer pegar qualquer ferramenta? Use "*" ou omita o matcher. Quer pegar ferramentas de um MCP específico? O matcher aceita regex, tipo mcp__memory__.*.
Agora o código sai formatado sempre, sem você pedir e sem o Claude precisar lembrar. É exatamente o tipo de disciplina que mata vários erros comuns de quem começa.
Exemplo 2: barrar um comando perigoso antes de ele rodar
Aqui entra o PreToolUse, o único evento que pode dizer "não". A lógica fica num script, porque ele precisa inspecionar o comando antes de decidir:
#!/bin/bash
# .claude/hooks/bloqueia-rm.sh
COMANDO=$(jq -r '.tool_input.command')
if echo "$COMANDO" | grep -q 'rm -rf'; then
jq -n '{
hookSpecificOutput: {
hookEventName: "PreToolUse",
permissionDecision: "deny",
permissionDecisionReason: "rm -rf bloqueado por regra do projeto"
}
}'
else
exit 0 # sem decisão: o fluxo normal de permissão segue
fiE o settings que aponta pra ele:
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command", "command": ".claude/hooks/bloqueia-rm.sh" }
]
}
]
}
}O script lê o comando pelo stdin (via jq), e se achar um rm -rf, devolve um JSON com permissionDecision: "deny" e o motivo. O Claude recebe esse "não" e segue sem rodar. Se nada bater, ele sai com exit 0 e a vida continua normal.
Os códigos de saída (a regra de ouro)
O jeito mais simples de um hook controlar o fluxo é pelo código de saída:
0— sucesso. Se houver JSON na saída, ele é processado.2— erro bloqueante. A ação é barrada e o que você escreveu nostderrvolta pro Claude como feedback.- qualquer outro — erro não-bloqueante: aparece um aviso, mas a execução segue.
Ou seja: pra barrar algo de forma rápida sem montar JSON, basta o script sair com exit 2 e imprimir o motivo no stderr. O Claude lê e se ajusta.
Exemplo 3: te avisar quando ele terminar
Roda uma tarefa longa e some pra outra aba? Um hook de Notification (ou Stop) te chama de volta:
{
"hooks": {
"Notification": [
{
"matcher": "*",
"hooks": [
{
"type": "command",
"command": "notify-send 'Claude Code' 'Precisa de você'"
}
]
}
]
}
}No macOS troque por osascript; no Windows, por um toast. O ponto é parar de vigiar o terminal.
Onde hooks brilham (e onde não)
Use hooks quando a regra tem que valer sempre: formatação, lint, testes que rodam após cada edição, bloqueios de segurança, logs de auditoria. Como ficam no .claude/settings.json versionado, viram política do repositório — todo mundo que abre o projeto herda.
Não use hook pra coisa que pede julgamento ("será que vale refatorar isso?"). Pra isso existem o Plan Mode e os subagentes, que pensam antes de agir. E lembre que hook é comando que roda na sua máquina com suas permissões: revise o que você cola ali, especialmente vindo de terceiros.
Um detalhe de custo: hooks que injetam contexto (como UserPromptSubmit) gastam tokens a cada disparo. Se você liga muitos, vale revisar os hábitos de gastar menos tokens pra não inflar a janela à toa.
O resumo
Hook é a parte do Claude Code que não negocia. Você define o gatilho — antes da ferramenta, depois dela, no fim da resposta — e o comando roda, sempre. Comece simples: um PostToolUse que formata o que foi editado. Depois um PreToolUse que barra o que não pode. Em pouco tempo seu repositório vira um lugar onde as regras se aplicam sozinhas, e o Claude trabalha dentro delas sem você precisar repetir.
Fonte: documentação oficial da Anthropic — Automate actions with hooks e a referência de configuração de hooks. Os fatos (eventos, formato do settings.json, matchers, códigos de saída e o controle de permissão) vêm de lá; a redação, os exemplos e a estrutura são deste blog.
Perguntas frequentes
O que são hooks no Claude Code?
São comandos de shell que o Claude Code executa sozinho em momentos fixos da sessão: antes de uma ferramenta rodar, depois que ela termina, quando você envia um prompt, quando o Claude para de responder. Diferente de pedir uma ação no chat, o hook é determinístico — ele sempre roda, não depende de o modelo lembrar de fazer. Serve pra formatar código, bloquear comandos perigosos, mandar notificação ou forçar regras do projeto.
Onde eu configuro um hook?
Num arquivo de settings em JSON. Use ~/.claude/settings.json para valer em todos os projetos, .claude/settings.json para um projeto só (esse vai pro Git e o time inteiro herda), ou .claude/settings.local.json para regras pessoais que ficam fora do versionamento. A estrutura é sempre: evento do hook, depois um matcher que filtra quando dispara, depois o comando a rodar.
Quais eventos de hook existem?
Os principais são PreToolUse (antes de uma ferramenta rodar, pode bloquear), PostToolUse (depois que ela termina, bom pra formatar o que foi editado), UserPromptSubmit (quando você manda um prompt), Stop (quando o Claude termina a resposta), Notification (quando ele precisa da sua atenção) e SessionStart/SessionEnd (começo e fim da sessão). Cada um recebe um JSON com o contexto pelo stdin.
Como um hook bloqueia um comando perigoso?
Num hook de PreToolUse, seu script lê o comando pelo stdin e decide. Saindo com código 2, ele bloqueia e manda o motivo (via stderr) de volta pro Claude. Ou você devolve um JSON com permissionDecision igual a 'deny' e um permissionDecisionReason. Saindo com código 0 sem decisão, o fluxo normal de permissão segue. É assim que dá pra barrar um 'rm -rf' antes de ele chegar a rodar.
Hook é a mesma coisa que skill ou subagente?
Não. Skill dá instruções e comandos extras que o Claude escolhe usar quando faz sentido. Subagente roda uma tarefa num contexto isolado. Hook é a peça determinística: um gatilho fixo no ciclo de vida que sempre dispara, sem o modelo decidir. Você usa hook quando a regra não pode depender de bom senso — ela tem que acontecer toda vez.
Continua a leitura

Agent view: rode vários Claude Code de uma tela só
Cansado de abrir um terminal por tarefa? O comando claude agents põe todas as suas sessões do Claude Code numa tela só — e você entra só quando uma delas precisa de você.
Ler
Como criar sua própria Skill no Claude Code (passo a passo)
Pare de colar a mesma instrução toda vez. Crie uma Skill: uma pasta com um SKILL.md que o Claude carrega sozinho quando precisa. Veja como, com exemplo pronto.
Ler
Artifacts no Claude Code: a sessão vira página viva
Em vez de despejar texto no terminal, o Claude Code pode publicar uma página web que se atualiza sozinha enquanto ele trabalha. Entenda os Artifacts e como criar o seu.
Ler