Como fazer o Claude Code rodar os testes em vez de só dizer que funcionou

hooks PostToolUse e Stop fazendo o Claude Code rodar testes antes de concluir a tarefa
Resposta rápida

Fazer o Claude Code rodar testes antes de dizer que terminou não é questão de prompt bonito, é questão de fechar a saída. O CLAUDE.md guarda os comandos exatos de build e de teste, o hook PostToolUse dispara a checagem logo depois de uma edição, o exit code 2 bloqueia a ação e devolve o stderr como feedback pro modelo, e o hook Stop (que é bloqueável) impede o agente de encerrar o turno com teste vermelho. Dá ainda pra empacotar esse loop de verificação como skill e distribuir pro time. Concluído passa a ser teste executado e saída lida, não promessa.

Existe uma frase que todo vibe coder já leu na tela: "pronto, implementei e validei, está tudo funcionando"

Aí você abre o projeto e nada foi executado 🙂

A ideia deste post é trocar a promessa do agente por prova executada, usando o que o próprio Claude Code já oferece: comandos declarados no CLAUDE.md, hooks que disparam a checagem, skills pra empacotar o loop de verificação e o fluxo de TDD que a documentação oficial recomenda

Nada de prompt mágico, beleza? É mecânica mesmo

O buraco na prática: pedi a porta 3000, o servidor subiu na 3005

Esse problema não é teórico, e eu peguei ele ao vivo

Um aviso antes pra ninguém confundir: esse caso NÃO foi no Claude Code

Foi no vídeo em que testo o Pi, um agente minimalista, que é outra ferramenta

Trago ele aqui porque o furo é do mesmo tipo que a gente vai fechar no Claude Code nos passos abaixo: promessa de validação no lugar de comando executado

No prompt de criação do projeto eu já tinha embutido uma verificação executável: rodar o servidor de desenvolvimento e confirmar que abriu na porta 3000

Só que a realidade não obedeceu meu prompt

O servidor subiu na porta 3005, porque as anteriores estavam ocupadas, e eu só descobri isso porque fui LER a saída do terminal

Se eu tivesse aceitado o "confirmei que está rodando", eu teria um número errado na cabeça e uma verificação de mentirinha no bolso

No mesmo vídeo tem um segundo caso, ainda mais clássico

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!

Pedi que o agente criasse uma server action, e junto da resposta ele afirmou por conta própria que tinha feito uma validação da funcionalidade

Não aceitei

Pedi um teste mais manual, e bem concreto: criar uma página de teste que chama a função de buscar commits com um username real do GitHub e renderiza o JSON cru na tela

Depois que o agente criou a página, eu fui até a rota no navegador olhar com os próprios olhos

Aí sim eu sei que funcionou

No vídeo você vê essa sequência inteira: o prompt inicial pedindo leitura, escrita e execução no terminal, o agente pedindo confirmação de entendimento das convenções do projeto antes de gerar código, a porta que não bateu e o teste manual que eu inventei pra não depender da palavra do agente

De novo, pra ficar claro: aquilo ali é o Pi, não o Claude Code

Daqui pra baixo é tudo Claude Code, usando o que ele já traz de fábrica pra transformar "validei" em comando executado

O que você precisa antes de começar

Requisitos curtos, nada de PC da Nasa aqui:

  • Claude Code instalado e um projeto com suíte de testes que JÁ roda no terminal (se o teste não roda na sua mão, ele não vai rodar na mão do agente)
  • saber o comando exato de teste do projeto, o mesmo que você digitaria: npm test, pytest, go test ./..., o que for
  • acesso ao ~/.claude/settings.json (configuração de usuário) ou ao .claude/settings.json do projeto, que é onde os hooks moram, com eventos, matchers e comandos

Um aviso que economiza uma tarde inteira de debug: sessões do Claude Code na web NÃO leem o ~/.claude/settings.json local

Nesses casos os hooks vêm do repositório e das configurações gerenciadas pela organização

Ou seja, hook pessoal na sua máquina não acompanha a sessão da web

Passo a passo para o Claude Code provar que o teste passou

A lógica é simples: se o agente pode declarar sucesso sozinho, ele vai declarar

Então a gente tira essa decisão dele e coloca num comando que roda de verdade

  1. Escreva os comandos exatos de build e de teste no CLAUDE.md

A documentação oficial de boas práticas recomenda exatamente isso: listar os comandos no CLAUDE.md pra o agente não ter que adivinhar

Parece bobo, mas adivinhação é a origem de metade do problema

## Comandos do projeto

- Instalar: `npm ci`
- Build: `npm run build`
- Testes: `npm test`
- Teste de um arquivo: `npm test -- caminho/do/arquivo`

O erro comum deste passo: escrever "rode os testes" e achar que isso é instrução

Sem o comando literal, o agente inventa um script que não existe, toma erro, e depois te conta que "a suíte não foi necessária" 😛

  1. Crie o hook PostToolUse com matcher por ferramenta

O PostToolUse roda DEPOIS que uma ferramenta é executada, então ele é o gancho certo pra disparar a checagem logo em seguida de uma edição de arquivo

É aqui que o "eu acho que está certo" vira "o comando rodou"

A configuração vive nos arquivos settings.json que citei ali em cima, com o evento, o matcher da ferramenta e o comando de shell que você quer disparar

O erro comum deste passo: pendurar a checagem em QUALQUER ferramenta

Se o hook dispara até quando o agente só leu um arquivo, você transforma uma sessão de trabalho numa suíte de teste em loop, e ninguém merece isso

  1. Devolva a falha pro modelo com exit code 2

Esse é o pulo do gato

Um hook que sai com código 2 bloqueia a ação, e o texto escrito em stderr volta pro Claude como feedback, pra ele se corrigir

#!/usr/bin/env bash
# .claude/hooks/rodar-testes.sh

saida=$(npm test 2>&1)
status=$?

if [ $status -ne 0 ]; then
  echo "Os testes falharam. Saída completa abaixo, corrija antes de continuar:" >&2
  echo "$saida" >&2
  exit 2
fi

exit 0

Repara no detalhe: eu jogo a SAÍDA do teste no stderr, não um "deu erro" genérico

O modelo precisa do texto do erro pra corrigir, e não de um aviso vago

O erro comum deste passo: montar um JSON caprichado de resposta e sair com código 2

O Claude Code só processa a saída JSON de um hook quando ele termina com código 0

Se sair com 2, o JSON é IGNORADO e vale o stderr

  1. Feche a saída com o hook Stop

O Stop dispara quando o agente vai encerrar o turno, e ele é bloqueável

Bloquear o Stop impede o encerramento e faz a conversa continuar

Traduzindo: o agente não consegue dar "tarefa concluída" e sumir enquanto o teste estiver vermelho

É a diferença entre um lembrete e um portão

O erro comum deste passo: confiar só no PostToolUse

O agente pode simplesmente parar de editar arquivos e declarar vitória, e aí nenhum hook de edição vai disparar

  1. Ajuste o timeout conforme a sua suíte

O tempo limite padrão de um hook é de 10 minutos, e dá pra ajustar por hook no campo timeout, informado em segundos

Suíte lenta? sobe o valor

Suíte que às vezes trava esperando input? baixa o valor, pra cortar rápido em vez de deixar a sessão pendurada

O erro comum deste passo: passar minutos onde o campo espera segundos

Colocar 10 achando que são dez minutos te dá dez segundos, e a suíte morre no meio sempre

  1. Empacote o loop de verificação como skill

Quando o combo começa a funcionar, você vai querer levar ele pra outros projetos

E esse empacotamento tem artigo oficial: a Anthropic publicou o Building verification loops in Claude Code with skills, assinado por Delba de Oliveira, do time do Claude Code

No Claude Code, cada skill é uma pasta com um arquivo SKILL.md como ponto de entrada, configurado por frontmatter YAML seguido do conteúdo em markdown

~/.claude/skills/          # skills pessoais
  verificacao/
    SKILL.md

.claude/skills/            # skills do projeto
  verificacao/
    SKILL.md

As skills de projeto são carregadas do diretório onde o Claude Code foi iniciado e dos diretórios pais até a raiz do repositório

E tem uma facilidade MUITO boa aqui: ao adicionar, editar ou remover uma skill nessas pastas, o Claude Code detecta a mudança dentro da sessão atual, sem precisar reiniciar

Dá pra iterar no texto da skill com a sessão aberta e testar na hora

O erro comum deste passo: escrever a skill como um manifesto filosófico sobre qualidade

Skill de verificação boa é chata e concreta: rode ESTE comando, leia a saída, se falhou conserte e rode de novo

  1. Rode o fluxo de TDD que a documentação recomenda

Hook é o portão, mas TDD é o que dá o que verificar

O fluxo descrito na documentação oficial é o clássico red-green-refactor: escrever um teste que falha com o código atual, implementar a correção e confirmar que o MESMO teste passa sem quebrar o resto

A documentação ainda sugere usar uma sessão do Claude pra escrever os testes e outra pra escrever o código que os faz passar, mantendo os testes independentes

Faz sentido: quem escreve o teste e o código na mesma cabeça tende a ajustar o teste até ele passar 🙂

O erro comum deste passo: deixar o agente "consertar" o teste em vez do código

Se o teste vermelho vira teste verde por edição do arquivo de teste, você não tem prova, tem teatro

Se você está começando agora, vale dar uma olhada também nos erros comuns de quem usa o Claude Code, porque vários deles nascem justamente de aceitar tarefa não executada

Quando a checagem não segura o agente: sintomas e correções

Montou tudo e mesmo assim o agente escapou? se liga na tabela

SintomaCausa provávelCorreção
Hook configurado, nada acontece na sessão webSessões do Claude Code na web não leem o settings.json local do usuárioMover a configuração pro repositório do projeto ou pras configurações gerenciadas pela organização
O JSON que o hook devolve é ignoradoO hook terminou com código 2, e o JSON só é processado no exit 0Decidir: ou bloqueia com exit 2 e fala pelo stderr, ou sai com 0 e usa o JSON
O agente encerra o turno com teste falhandoFaltou o hook Stop, que é o bloqueável no encerramentoAdicionar o Stop e bloquear enquanto a checagem não passar
A mensagem não aparece pra quem está usandoFalta o campo continue definido como falseUsar continue: false com o stopReason, que é exibido ao usuário
A suíte é cortada no meioBateu o tempo limite padrão de 10 minutosAjustar o campo timeout do hook, lembrando que o valor é em segundos

Como prevenir tudo isso de uma vez: teste o hook com um teste que você QUEBROU de propósito

Sério, quebra uma asserção na mão e manda o agente mexer no projeto

Se ele conseguir dizer "concluído" com aquele teste vermelho, o portão não existe, existe decoração

Onde esse loop de verificação compensa mais

Nem todo projeto precisa desse aparato no dia 1, então vale escolher onde ele paga o esforço:

  • refatoração ampla, em que o agente toca dezenas de arquivos e ninguém consegue revisar tudo com o olho
  • correção de bug com teste de regressão, o caso mais bonito de todos: o teste falha, a correção entra, o mesmo teste passa e ele fica lá pra sempre segurando a regressão
  • projeto com suíte rápida, onde rodar a cada edição custa poucos segundos e o feedback volta quente
  • padronizar o time, empacotando o loop como skill de projeto dentro de .claude/skills/ pra todo mundo herdar o mesmo portão

Se a distribuição for pra mais de um repositório, plugin resolve

Você adiciona o marketplace e instala:

/plugin marketplace add usuario-ou-org/nome-do-repo
/plugin install <plugin>@<marketplace>

E pra script e automação existem os subcomandos não interativos claude plugin marketplace, equivalentes aos comandos /plugin da sessão interativa

O conceito por trás disso tudo é aquele artigo que citei lá no passo 6

O loop de verificação é definido ali como o ciclo em que o agente checa o próprio trabalho (testes, linters, checagens próprias) e corrige o que falha antes de seguir

É literalmente o que a gente montou nos passos acima, só que com nome de gente grande 😀

Um detalhe prático: suíte rodando a cada edição consome tempo e contexto, então se o seu projeto é grande vale combinar isso com as ideias de fazer o plano render mais e reservar o loop completo pras etapas que realmente importam

Conclusão

A régua muda de lugar aqui, e essa é a parte importante

Concluído não é o agente dizendo que validou

Concluído é teste executado e saída LIDA, do mesmo jeito que eu fui olhar a porta no terminal e a rota no navegador em vez de acreditar no resumo bonitinho

Se você quer um próximo passo prático, faz na ordem: primeiro o CLAUDE.md com os comandos exatos de build e de teste, depois o hook PostToolUse em UM projeto só, e por último o Stop bloqueável

Aí quebra um teste de propósito e vê se o portão segura mesmo o encerramento

Se segurar, você acabou de trocar promessa por prova

até o próximo post!

Perguntas frequentes

Como faço o Claude Code rodar os testes automaticamente depois de cada edição?

Configura um hook no evento PostToolUse, que dispara logo depois que uma ferramenta é executada. Ele mora no settings.json (do usuário ou do projeto) com o matcher da ferramenta e o comando de shell que roda a suíte. É esse hook que troca o "confirmei que está rodando" por um comando executado de verdade.

O hook configurado no settings.json funciona nas sessões do Claude Code pela web?

Não. Sessões do Claude Code na web não leem o ~/.claude/settings.json local, então um hook pessoal na sua máquina simplesmente não acompanha essa sessão. Nesses casos, os hooks vêm do repositório e das configurações gerenciadas pela organização.

Qual a diferença entre o hook PostToolUse e o hook Stop no Claude Code?

PostToolUse dispara depois que uma ferramenta é executada, então é o gancho certo pra checar uma edição de arquivo assim que ela acontece. Já o Stop dispara quando o agente vai encerrar o turno, e ele é bloqueável: bloquear o Stop impede o encerramento e força a conversa a continuar, mesmo que o agente já tenha parado de editar arquivos.

Por que o hook precisa sair com exit code 2 em vez de só devolver um JSON de resposta?

Porque o Claude Code só processa a saída JSON de um hook quando ele termina com código de saída 0. Se o hook sai com código 2, o JSON é ignorado e o que vale é o texto escrito no stderr, que volta pro modelo como feedback pra ele se corrigir.

Dá pra usar o fluxo de TDD (test driven development) com o Claude Code?

Dá, e a documentação oficial descreve esse fluxo: escrever um teste que falha com o código atual, implementar a correção e confirmar que o mesmo teste passa sem quebrar o resto. A própria documentação ainda sugere separar a sessão que escreve o teste da sessão que escreve o código, pra manter os testes independentes.

O que são as skills de verificação do Claude Code e onde elas ficam?

É o formato que a Anthropic descreveu no artigo ‘Building verification loops in Claude Code with skills’, assinado por Delba de Oliveira, do time do Claude Code, o mesmo citado no passo 6 do post: uma skill é uma pasta com um arquivo SKILL.md como ponto de entrada, com frontmatter YAML e o conteúdo em markdown. Skills pessoais ficam em ~/.claude/skills/ e skills de projeto em .claude/skills/, e mudanças nessas pastas são detectadas na sessão em curso, sem precisar reiniciar.




Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

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