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

Claude Code diz que terminou mas o código não roda, terminal mostrando erro
Resposta rápida

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
Formação Recomendada

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

  1. 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

  1. 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

  1. 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

  1. Rode /code-review no 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 😛

  1. Rode /security-review quando 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

  1. Invoque /verify quando 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

  1. 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

  1. Use /goal com 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á

  1. 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

  1. 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

  1. 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é

  1. 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

  1. 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.



Escrito por | Matheus Battisti

Matheus Battisti
Fundador da Hora de Codar

Programador apaixonado pelo mundo das tecnologias, sempre buscando em aprender e se aprofundar em linguagens, frameworks e o que mais for necessário para executar um bom trabalho. Agora tem uma nova missão que é de passar seu conhecimento adiante para formar novos programadores e especializar mais os que já são.

Subscribe
Notify of
guest

0 Comentários
Oldest
Newest Most Voted

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