Três meses. É quanto tempo deixei os Claude Code hooks sentados na documentação, sem ler, enquanto reclamava que a IA continuava produzindo código que ignorava minhas convenções de formatação. Configurei Claude Code em janeiro, comecei a fazer deploy de features com ele quase imediatamente, e me disse que "ia mexer no negócio dos hooks depois". Clássico.
Descobri que os hooks não eram um "nice-to-have". Eram o pedaço que faltava para fazer Claude Code encaixar de verdade em um fluxo de trabalho de agência real, em vez de ser um autocomplete muito caro que ocasionalmente ignorava ESLint.
O Que os Claude Code Hooks Realmente São (Sem Abstrações Vagas)
Hooks são comandos shell que Claude Code dispara em pontos específicos durante sua própria operação. Pense neles como eventos de ciclo de vida, similares aos Git hooks se você já escreveu um script pre-commit, mas conectados ao loop de tool-use da IA em vez do pipeline de commits do Git.
Existem quatro tipos de eventos agora:
PreToolUse, executa antes de Claude chamar qualquer tool (edições de arquivo, comandos bash, etc.)PostToolUse, executa depois que uma chamada de tool é concluídaNotification, dispara quando Claude envia uma notificação para vocêStop, executa quando Claude termina seu turno de resposta completo
Você os configura em um arquivo settings.json dentro da pasta .claude/ do seu projeto, ou globalmente em ~/.claude/settings.json se quiser em todos os lugares. Cada hook recebe um matcher (qual tool ou evento o dispara) e um array hooks com comandos shell para executar.
O output do seu hook é alimentado de volta ao contexto de Claude. Esse último detalhe é o que torna isso genuinamente interessante em vez de apenas ser um fancy cron job.
Por Que Isso É Diferente de Apenas Rodar Scripts por Conta Própria
Você poderia rodar Prettier manualmente após cada edição de Claude. Fiz isso por umas duas semanas, até esquecer durante um push de deadline e fazer push de uma PR com 47 violações de formatação. Os hooks rodam automaticamente, dentro da sessão, e Claude consegue ler seu output. Então se seu linter dispara um aviso, Claude vê e consegue agir sobre isso na mesma sessão. Esse loop de feedback é o ponto todo.
A Configuração Que Realmente Funcionou para Projetos Seahawk
Vou ser específico aqui porque o conselho genérico "adicione hooks ao seu config" que você encontra em muitos write-ups é inútil sem contexto.
Na Seahawk, uma grande parte do nosso trabalho é builds WordPress e customizações WooCommerce. Também fazemos frontends React para setups headless, e estamos usando Next.js pesadamente desde 2022. A configuração de hook que cheguei a atender problemas específicos daqueles stacks.
Aqui está a estrutura settings.json que uso para um projeto Next.js:
`` { "hooks": { "PostToolUse": [ { "matcher": "Write|Edit|MultiEdit", "hooks": [ { "type": "command", "command": "npx prettier --write $CLAUDE_FILE_PATHS && npx eslint --fix $CLAUDE_FILE_PATHS" } ] } ], "Stop": [ { "matcher": ".*", "hooks": [ { "type": "command", "command": "npx tsc --noEmit 2>&1 | head -20" } ] } ] } } ``
O hook PostToolUse dispara Prettier e ESLint imediatamente após Claude tocar em um arquivo. O hook Stop roda uma verificação de tipo TypeScript no final de cada turno e mostra as primeiras 20 linhas de qualquer erro. Claude lê aquele output, e se houver erros de tipo, ele os corrige antes de eu até ver a resposta.
Aquela verificação TypeScript sozinha me economizou provavelmente quatro horas mês passado em um projeto de dashboard fintech onde o cliente tinha noImplicitAny rigorosamente definido. Claude continuava gerando tipos any em funções utilitárias. Depois que adicionei o Stop hook, começou a se auto-corrigir dentro do mesmo turno.
Os Hooks que Uso em Projetos WordPress / PHP
WordPress é uma besta diferente. Sem TypeScript, obviamente, mas PHP_CodeSniffer com o ruleset WordPress Coding Standards é o que mantém as coisas sãs. Lá em 2022 eu tinha um dev junior em um projeto WooCommerce que ficou duas semanas sem rodar PHPCS. A revisão de código foi... nem um pouco agradável.
Para projetos pesados em PHP meu hook PostToolUse roda:
`` vendor/bin/phpcs --standard=WordPress $CLAUDE_FILE_PATHS 2>&1 | tail -30 ``
E eu combino isso com um hook PreToolUse em comandos bash:
`` { "matcher": "Bash", "hooks": [ { "type": "command", "command": "echo 'Bash tool triggered' >> ~/.claude/audit.log && date >> ~/.claude/audit.log" } ] } ``
Aquele segundo é pura paranoia. Escreve cada comando bash que Claude roda em um audit log. Quando você está rodando Claude Code em um ambiente staging ao vivo (sim, eu já fiz, sim é um pouco arriscado), saber exatamente quais comandos shell foram executados é genuinamente tranquilizador.
Bloqueando Comportamento Com Códigos de Saída do Hook
Esta parte da documentação levou um tempo para eu encontrar. Se seu hook sair com código 2, Claude Code trata isso como um bloqueio e não procede com a chamada da ferramenta. Código de saída 0 é sucesso, qualquer coisa não-zero (mas não 2) apenas alimenta o stderr de volta como contexto.
Então você pode escrever um hook PreToolUse que realmente impede Claude de fazer algo. Eu uso isso em projetos que têm um diretório migrations/ que não quero que Claude toque autonomamente:
`` #!/bin/bash if echo "$CLAUDE_FILE_PATHS" | grep -q "migrations/"; then echo "Migrations folder is protected. Do not edit migration files autonomously." exit 2 fi exit 0 ``
Esse script fica em .claude/hooks/guard-migrations.sh. Quando Claude tenta escrever em qualquer coisa sob migrations/, é bloqueado e vê a mensagem. Depois me pergunta para confirmar antes de prosseguir. Simples, eficaz.
Este é o tipo de controle que faz a diferença entre "eu meio que confio nesta IA com minha base de código" e "eu realmente confio nela com minha base de código".
Padrões de Hook Práticos Dignos de Roubar
Estes não são teóricos. Cada um veio de um ponto de dor específico.
- Auto-rodar testes após edições de arquivo. Eu rodo
npx jest --testPathPattern=$CLAUDE_FILE_PATHS --passWithNoTestsem um hookPostToolUse. Ele só roda testes relacionados ao arquivo que Claude acabou de editar, não toda a suíte. Rápido o suficiente para não ser chato. - Snapshot de formatação pronto para commit. Um hook
Stopque rodagit diff --state alimenta o resumo de volta para Claude. Ele vê exatamente o que mudou durante a sessão, o que ajuda a escrever uma mensagem de commit sensata se eu pedir por uma. - Verificação de segurança de variáveis de ambiente. Um hook
PreToolUseemWriteque faz grep para padrões de segredos hardcoded (coisas que parecem chaves de API ou senhas). Se encontra algo suspeito, sai com2. Deveria ter construído este uns 18 meses atrás. - Hook de notificação para tarefas longas. Quando Claude envia uma notificação (o evento Notification), eu lanço uma chamada
curlpara um endpoint Pushover então recebo uma notificação push no meu telefone. Genuinamente útil quando você inicia um grande refactor e vai fazer uma xícara de chá. - Verificação de sintaxe PHP antes do bash. Em projetos WordPress, um rápido
php -l $CLAUDE_FILE_PATHSantes de qualquer execução bash. Pega erros de sintaxe fatal antes de quebrarem um servidor staging.
A documentação oficial de hooks do Claude Code tem uma referência completa para variáveis de ambiente disponíveis dentro de scripts de hook. Vale a pena favoritar.
O Que Hooks Não Consertam
Honestidade importa aqui. Hooks não são uma solução para Claude gerar código logicamente errado. Eles consertam problemas de processo: formatação, linting, segurança de tipo, cobertura de testes. Se Claude entende mal seu modelo de dados e constrói a feature errada, nenhuma quantidade de linting pós-edição vai pegar isso.
Hooks também adicionam latência. Se seu pass Prettier + ESLint leva quatro segundos, cada edição de arquivo agora leva quatro segundos a mais. Em um projeto com 200 edições de arquivo em uma sessão, são 13 minutos de espera. Perfile seus comandos de hook. Mantenha-os rápidos. Eu rodo variantes --fix (que modificam arquivos no local) em vez de variantes report-only precisamente porque um único pass rápido bate um pass lento seguido por um segundo pass corretivo.
E eles exigem que você realmente pense sobre os modos de falha do seu projeto antecipadamente. O que pode dar errado se Claude edita o arquivo errado? Quais padrões absolutamente devem ser impostos? Esse pensamento é valioso independentemente, mas significa que hooks recompensam desenvolvedores experientes mais que iniciantes.
Configurando Hooks: O Passo-a-Passo
Para qualquer um começando do zero:
- Crie uma pasta
.claude/na raiz do seu projeto, se ela ainda não existir. - Adicione um arquivo
settings.jsoncom sua configuração de hooks (estrutura mostrada acima). - Para qualquer coisa maior que uma linha, escreva um script shell separado (.claude/hooks/seu-script.sh), execute
chmod +xnele e o chame a partir da configuração em vez de inserir o comando inline. - Teste executando
claudeno seu projeto e acionando deliberadamente a condição do hook. Leia o que volta no contexto da sessão. - Verifique os logs de execução do hook em
~/.claude/logs/se algo não está disparando como esperado.
A documentação do desenvolvedor da Anthropic cobre o schema completo de settings. E se você está pensando em como hooks se encaixam em fluxos de trabalho mais amplos de IA para codificação, o blog de Simon Willison é onde eu mandaria qualquer um que quer pensar com mais cuidado sobre ferramentas de IA agêntica em projetos reais.
Uma coisa que eu errei inicialmente: coloquei todos os meus hooks no arquivo global ~/.claude/settings.json e depois me perguntei por que meus hooks de PHP estavam disparando em projetos JavaScript. Configurações no nível do projeto sobrescrevem as globais. Coloque hooks específicos da stack no .claude/settings.json do projeto e guarde sua configuração global para coisas que devem se aplicar em todos os lugares (como o log de auditoria e o hook de notificação).
FAQ
Os hooks do Claude Code funcionam no Windows?
Os comandos do hook rodam em qualquer shell que seu sistema use. No Windows, o padrão é PowerShell ou CMD, o que significa que scripts em estilo bash não funcionarão nativamente. WSL2 é a resposta prática aqui. Estou no macOS e Ubuntu nas minhas máquinas de desenvolvimento, então não enfrentei isso pessoalmente, mas a documentação da Anthropic explicitamente nota a dependência de shell.
Os hooks podem acessar o contexto de conversa do Claude?
Não diretamente. Hooks rodam como comandos shell e recebem variáveis de ambiente como CLAUDE_FILE_PATHS e CLAUDE_TOOL_NAME, mas não recebem a transcrição completa da conversa. O que eles podem fazer é escrever saída para stdout, que Claude lê como contexto depois que o hook é executado.
Os hooks vão desacelerar minhas sessões do Claude Code notavelmente?
Depende inteiramente do que seus hooks fazem. Uma verificação de sintaxe php -l em um único arquivo leva menos de 100ms. Executar sua suíte Jest completa a cada edição de arquivo seria irritante. Mantenha comandos de hook individuais em dois ou três segundos e você mal vai notar.
É seguro usar hooks em ambientes de produção?
Eu faria essa pergunta de forma inversa: você está executando Claude Code diretamente em produção? Se sim, hooks são o menor de seus problemas. Use-os em staging, use o padrão de bloqueio PreToolUse para proteger diretórios sensíveis e mantenha Claude completamente longe de bancos de dados de produção.
Qual é a diferença entre hooks no nível do projeto e globais?
Hooks globais vivem em ~/.claude/settings.json e se aplicam a todas as sessões do Claude Code na sua máquina. Hooks no nível do projeto vivem em .claude/settings.json dentro de um projeto específico e só disparam quando você está naquele projeto. O nível do projeto tem precedência onde ambos definem o mesmo evento.
---
O resumo honesto: hooks não são glamurosos. Ninguém vai escrever um post de blog sobre a arquitetura bonita de um script shell que executa Prettier. Mas eles são a diferença entre Claude Code ser um brinquedo de protótipo e ser algo em que você realmente confiaria em trabalho com clientes. Eu deveria ter configurado isso no primeiro dia. Você provavelmente deveria também.
