Claude Code diz que terminou mas o código não roda: como conferir antes de aceitar

Quando o Claude Code diz que terminou e o código não roda, quase sempre não teve execução nenhuma no meio do caminho: a doc oficial explica que ele para quando o trabalho parece pronto, e sem um check que ele mesmo possa rodar, quem vira o loop de verificação é você. A defesa é curta: ler o diff com /diff, rodar o comando de verdade e olhar o exit code, passar /code-review e /security-review no diff, e pedir evidência (comando rodado, saída, retorno) em vez de aceitar o resumo. Depois automatize com /goal ou um Stop hook.
Fala aí, beleza? Aquela cena você já conhece: o agente escreve "pronto, implementado e funcionando", você roda o comando e quebra na primeira linha
E aí vem a sensação de que a IA mentiu na sua cara
Mas não é bug aleatório nem má fé
A documentação oficial de boas práticas explica direto: o Claude para quando o trabalho "looks done", ou seja, quando parece pronto. Sem um check que ele mesmo possa rodar, esse "parece pronto" é o único sinal disponível, e a verificação sobra pra você
Ou seja: quando o Claude Code diz que terminou, isso é uma afirmação, não uma evidência
Neste post eu explico a causa desse comportamento e monto um checklist curto pra você rodar antes de aceitar qualquer tarefa como encerrada, além das automações que tiram esse trabalho das suas costas…
O agente declarou sucesso sem rodar nada: causa e solução
Antes de sair configurando coisa, vale entender que quase todo "terminei" falso cai em um de três padrões
Cada um tem a mesma raiz e uma solução operacional diferente
Sintoma 1: declarou pronto sem executar
O resumo está lindo, a lista de tarefas toda marcada, e nada foi rodado
Causa: ele parou no ponto em que o trabalho parecia concluído. Sem check executável no meio, não existe sinal de pass ou fail pra contradizer essa impressão
Solução: peça evidência em vez de aceitar a afirmação de sucesso. A doc recomenda exatamente isso: peça a saída do teste, o comando que foi rodado e o que ele retornou, ou um screenshot do resultado
Revisar evidência é mais rápido que refazer a verificação do zero, e essa é a economia real aqui
Formação Claude Code
Domine Claude Code do absoluto zero até o avançado
- 116 aulas
- 4 projetos
- 9h 23min
Sintoma 2: mudou o que não deveria (ou mudou de menos)
A feature até funciona, mas veio junto uma refatoração que ninguém pediu
Ou o contrário: ele descreveu três mudanças e escreveu uma
Causa: você está lendo o texto do agente, não o resultado dele. O resumo é uma narrativa do que ele acha que fez
Solução: /diff mostra o que mudou de verdade, e é comando nativo do Claude Code. Texto é opinião, diff é fato 🙂
Sintoma 3: "corrigi" sem verificação ponta a ponta
Esse é o mais traiçoeiro: o bug foi tratado no arquivo certo, mas ninguém rodou o fluxo inteiro
Causa: de novo, ausência de check rodável. A correção parece completa isoladamente
Solução: rode /code-review no diff atual, que caça bugs de correção e limpezas, e /security-review quando a mudança encosta em coisa sensível
Se você quer se aprofundar em como conferir uma feature antes de confiar, esse ponto merece atenção separada
Como prevenir os três de uma vez:
A doc lista três formas de fechar o loop de verificação, e elas resolvem os três sintomas acima na origem:
- pedir na mesma mensagem que ele rode o check e itere até passar
- definir o check como condição de
/goal - usar um Stop hook que roda o check como script e bloqueia o fim do turno até passar
Detalhe importante: o check precisa produzir pass ou fail. Pode ser suíte de testes, exit code de build, linter, script que compara saída com fixture ou até screenshot comparado com o design
"Ficou bom?" não é check. "Saiu 0 ou saiu 1?" é check
Checklist de verificação antes de aceitar a tarefa
Esse é o processo manual, pra rodar sempre que aparecer aquele "tudo funcionando"
São poucos passos e dá pra fazer em menos tempo do que leva pra descobrir o problema em produção
- Leia o diff com
/diff
Comece pelo que mudou, não pelo que ele disse que mudou
O erro comum deste passo: revisar o texto do resumo em vez do diff. O resumo é escrito pelo mesmo cara que achou que estava pronto haha
- Rode o comando de verdade e olhe o exit code
Build, teste, subir a aplicação, o que for o comando de pass ou fail do seu projeto
O erro comum deste passo: ler só a última linha do log. Warning bonito no fim não anula erro no meio, e o exit code é quem manda
- Abra a tela ou a saída real quando for interface
Se a mudança é visual, ela precisa ser vista. Componente que compila não é componente que renderiza
O erro comum deste passo: aceitar "o componente foi criado com sucesso" como prova de que a tela funciona
- Rode
/code-reviewno diff
Ele checa o diff atual atrás de bugs de correção e limpezas
Algumas variações úteis: --fix aplica os achados, passar um número de PR (ex: /code-review high 1234) revisa o pull request, /review é alias, e /code-review ultra roda revisão multiagente na nuvem
O erro comum deste passo: rodar a revisão e não ler o que ela devolveu 😛
- Rode
/security-reviewquando o diff encosta em coisa sensível
Ele checa o diff atual em busca de vulnerabilidades de segurança
Vale sempre que a mudança toca autenticação, entrada de usuário ou dependências
O erro comum deste passo: deixar pra fazer isso só no PR, quando o contexto da mudança já esfriou
- Invoque
/verifyquando quiser os checks mais longos
/verify é uma skill embutida que roda apenas sob invocação explícita
Isso é de propósito: mantém você no controle de quando esses checks mais demorados gastam tempo e tokens
O erro comum deste passo: achar que ele roda sozinho no fim de toda tarefa. Não roda, você precisa chamar
Como automatizar o check e parar de ser o loop de verificação
Rodar checklist na mão funciona, mas cansa
A ideia aqui é subir a régua aos poucos, do mais leve pro mais firme
- Peça o check na mesma mensagem
O nível zero de automação: na própria instrução, mande ele rodar o check e iterar até passar
É o mais barato de todos e resolve boa parte dos casos. A diferença entre "implementa o endpoint" e "implementa o endpoint, roda os testes e me mostra a saída" é enorme
Esse é o pulo do gato de escrever um prompt verificável desde o começo
O erro comum deste passo: pedir o check numa mensagem separada, depois que ele já declarou vitória
- Use
/goalcom a condição desejada
/goal seguido da condição adiciona um avaliador separado, que checa a condição depois de cada turno
/goal os testes de integração passam e o build sai com exit code 0
Como funciona: a condição e a conversa vão para o modelo pequeno e rápido configurado (por padrão o Haiku). Se a resposta é "não", o Claude continua trabalhando e recebe o motivo como orientação. Se é "sim", a meta é limpa
Definir a meta já inicia um turno, sem precisar de prompt separado, e enquanto ela está viva aparece o indicador ◎ /goal active
Por baixo do capô, /goal é um wrapper sobre um Stop hook baseado em prompt, com escopo de sessão
O erro comum deste passo: escrever condição subjetiva. "o código está bom" não dá pra avaliar, "o comando X sai com exit code 0" dá
- Configure um Stop hook pra bloquear o fim do turno
Esse é o modo firme: o hook vive no arquivo de settings, vale pra toda sessão no escopo dele e dispara após cada turno
A configuração de hooks fica em settings.json ou settings.local.json, e os tipos suportados incluem command, http, mcp_tool, prompt e agent
O segredo está no exit code: sair com exit 2 no evento Stop impede o Claude de parar e faz a conversa continuar (exit 2 é o sinal de erro bloqueante dos hooks)
Agora se liga nisso, porque é aqui que a galera se ferra: sem guarda, o hook bloqueia o fim do turno, o Claude tenta parar de novo, o hook bloqueia de novo, e você inventou o moto perpétuo
Pra evitar o loop infinito, o script precisa ler o campo stop_hook_active do JSON de entrada e sair antes se ele for true:
#!/usr/bin/env bash
INPUT=$(cat)
# guarda obrigatoria contra loop infinito
if [ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ]; then
exit 0
fi
# troque pelo comando de pass ou fail do seu projeto
if ! ./scripts/check.sh; then
echo "o check falhou, continue trabalhando" >&2
exit 2
fi
O erro comum deste passo: esquecer a guarda do stop_hook_active no topo. Tome cuidado, é literalmente a primeira coisa do script
Como desfazer quando você aceitou e o código quebrou
Aconteceu, você aceitou, e agora tem arquivo mexido que você nem sabia que existia
Respira, tem rota de volta
- Abra o menu de rewind
Rode /rewind, ou aperte Esc duas vezes com o campo de prompt vazio
O Claude Code tira um snapshot do arquivo antes de editar, então existe pra onde voltar
- Escolha o ponto no menu
O menu lista cada prompt enviado na sessão, então dá pra mirar o momento exato em que as coisas ainda estavam de pé
- Decida o que restaurar
Você pode restaurar o código, a conversa, ou os dois
O erro comum deste passo: restaurar só a conversa e achar que os arquivos voltaram junto
- Entenda os limites antes de confiar demais nisso
Aqui é onde muita gente se engana, então vou listar seco:
- só rastreia arquivos editados na sessão atual
- é local à sessão e separado do git
- cobre as edições do Claude, não as suas nem comandos bash
- não faz rewind de symlinks ou hard links
- checkpoints somem junto com as sessões depois de 30 dias
A própria doc recomenda usar checkpointing junto com controle de versão, não no lugar dele
Traduzindo: commit continua sendo seu cinto de segurança, o rewind é o airbag
Ajustes de rotina que reduzem o "terminei" falso
Checklist ataca o sintoma
Esses ajustes atacam a raiz, e são coisa de configurar uma vez só
Grave as regras fixas no CLAUDE.md:
O CLAUDE.md é lido no início de cada sessão, e serve pra guardar o que o Claude precisa saber SEMPRE
A doc recomenda manter ali comandos de build, convenções, layout do projeto e regras do tipo "sempre faça X"
É o lugar natural pro seu comando de verificação: se o "como testar" está no arquivo, ele não precisa adivinhar
Porém, não vira despejo de texto: acima de 200 linhas o arquivo consome mais contexto e pode reduzir a aderência às instruções. E um arquivo acima de 4 MiB é simplesmente ignorado
Menos e mais afiado ganha de completão bagunçado 😀
Use plan mode antes de qualquer edição:
O plan mode pesquisa e propõe as mudanças sem editar os arquivos de código
Você entra com Shift+Tab ou prefixando um único prompt com /plan
Ele lê, busca, roda comandos de exploração e apresenta um plano pra sua aprovação antes de mexer em qualquer coisa
É MUITO mais barato discordar de um plano do que reverter uma implementação inteira
Escolha o modo de permissão certo:
Os modos disponíveis são default, acceptEdits, plan, auto, dontAsk e bypassPermissions
A troca é com Shift+Tab na CLI, pelo indicador de modo no VS Code ou pelo seletor no Desktop
O acceptEdits serve justamente pra quem prefere revisar as mudanças depois no editor ou via git diff, em vez de aprovar cada edição na hora
Não existe modo certo universal, existe o que combina com o seu jeito de revisar
Lembre das três fases:
O Claude Code trabalha em três fases por tarefa: reunir contexto, agir e verificar resultados
E elas se repetem dentro de uma mesma correção de bug, não é uma passada só
Quando o "terminei" falso aparece, é quase sempre a terceira fase ficando sem material pra trabalhar
Não é só com você: o que dizem as issues do repositório oficial
Se você achou que estava sendo azarado, calma: esse comportamento é reportado publicamente no repositório anthropics/claude-code
| Issue | Título |
|---|---|
| #14947 | Claude marks tasks complete without verifying implementation |
| #12369 | Claude Code fails to verify task completion against documented requirements |
| #37818 | Claude repeatedly declares fixes done without end-to-end verification |
| #32281 | Claude Code reports task completion without actually executing operations |
| #6528 | TodoWrite Task Completion Falsification: Marking Tasks Without Execution |
O que isso muda na sua vida? Basicamente confirma que a sua percepção está certa e que a defesa não pode ser sorte nem "prompt mágico"
A defesa é processo: check rodável, evidência pedida, diff lido
Conclusão
Enquanto não existir um check que o próprio agente possa rodar, a verificação é sua, e o "parece pronto" continua sendo o único sinal que ele tem
Então o resumo do post fica assim: leia o diff, rode o comando, olhe o exit code, peça evidência em vez de afirmação
E o próximo passo é pequeno, dá pra fazer hoje: escolha UM comando de pass ou fail do seu projeto, coloque ele no CLAUDE.md e use como condição de /goal na próxima tarefa
Se funcionar bem e você cansar de digitar, sobe pro Stop hook e deixa ele bloquear o turno por você
Bora testar isso na próxima tarefa e ver quantos "terminei" sobrevivem ao check? 😀
até o próximo post!
Perguntas frequentes
Por que o Claude Code diz que terminou a tarefa mas o código quebra na hora de rodar?
Porque o agente para quando o trabalho "looks done", ou seja, quando parece pronto pra ele. Sem um check executável no meio do processo, esse "parece pronto" é o único sinal disponível, e não existe pass ou fail contradizendo a impressão. É por isso que a verificação sobra pra você, e não é a IA mentindo, é ausência de um check rodável.
Como pedir evidência ao Claude Code em vez de aceitar que ele terminou a tarefa?
Peça a saída do teste, o comando que foi rodado e o que ele retornou, ou um screenshot do resultado. A própria documentação recomenda isso no lugar de aceitar a afirmação de sucesso. Revisar essa evidência é mais rápido do que refazer a verificação do zero.
Qual a diferença entre /code-review e /security-review no Claude Code?
O /code-review checa o diff atual atrás de bugs de correção e limpezas, e tem o alias /review. O /security-review checa o mesmo diff atual, mas focado em vulnerabilidades de segurança. Use o /code-review sempre, e some o /security-review quando a mudança encostar em autenticação, entrada de usuário ou dependências.
O que é o /goal do Claude Code e como ele evita conclusão sem verificação?
O /goal é um comando que recebe a condição desejada e funciona como um wrapper sobre um Stop hook baseado em prompt, com escopo de sessão. Depois de cada turno, a condição e a conversa vão para o modelo pequeno configurado (por padrão o Haiku), que decide se o objetivo foi cumprido. Se a resposta for "não", o Claude continua trabalhando usando o motivo como orientação, e enquanto a meta está ativa aparece o indicador ◎ /goal active.
Dá para desfazer uma alteração se o Claude Code disser que terminou errado?
Dá. O Claude Code tira um snapshot do arquivo antes de editar, então existe pra onde voltar, e você escolhe restaurar o código, a conversa ou os dois. Só que isso não substitui controle de versão: a própria doc recomenda usar o checkpointing junto com o git, não no lugar dele.
O /verify roda sozinho toda vez que o Claude Code termina uma tarefa?
Não. O /verify é uma skill embutida do Claude Code que só roda quando é invocada explicitamente. Isso é proposital: mantém você no controle de quando esses checks mais longos vão gastar tempo e tokens.
Formações
Formação Vibe Coding
Do Prompt ao Produto: Crie Software Real com IA
- 474 aulas
- 20 projetos
- 39h 27min
Blog | Mais populares
Bateu o limite de uso do Claude Code? Como retomar a tarefa sem refazer tudo
Bateu o limite de uso do Claude Code? Veja como retomar a tarefa de onde parou com /usage, CLAUDE.md e --continue, sem refazer nada.
Como pagar o Claude Code no Brasil: cartão, dólar, IOF e quanto fica em reais
Claude Code preço Brasil na prática: câmbio, IOF de 3,5% e quanto fica na fatura. Planos Pro e Max convertidos em reais e como pagar com cartão.
Como instalar uma skill no Claude Code: passo a passo
Saiba como instalar skill no Claude Code: use a pasta pessoal para todas as sessões ou a pasta de projeto para versionar. Frontmatter YAML é obrigatório.
