← claude-core
Recursos
▮ CLAUDE-CORE · ACADEMY CLAUDE CODE v2.1.143 /goal · DEEP DIVE ▮

O COMANDO /goal

Um comando, oito módulos, ~25 minutos. Define a linha de chegada, sai de perto — e entende o que tá rodando por baixo.

Por que uma classe inteira sobre um comando

/goal parece açúcar sintático — você digita uma condição, o Claude continua trabalhando até a condição valer — mas o movimento arquitetural por baixo é grande: o agente fazendo o trabalho não é mais o agente que decide que está pronto. Um segundo modelo, menor, julga a condição a cada turno. Acerte a condição e você converteu um loop de chat em um contrato.

O que você vai aprender

Construído contra

Claude Code v2.1.143. O comando chegou na v2.1.139 (maio de 2026). O diálogo de trust precisa ter sido aceito no workspace, já que /goal é açúcar com escopo de sessão em cima do sistema de hooks.

§1

O que /goal é

fundamentos

TL;DR/goal <condição> define uma condição de conclusão com escopo da sessão. Depois de cada turno, um modelo pequeno e rápido julga se a condição vale. Se não, o Claude pega mais um turno — automaticamente, sem precisar de "continua aí" de você.

▸ Os três usos, mesmo comando

  • /goal <condição> — define (ou substitui) o goal ativo. Um turno começa imediatamente, a própria condição vira a diretiva.
  • /goal (sem args) — mostra o status: condição, tempo de execução, turnos avaliados, custo em tokens, última razão do evaluator.
  • /goal clear — remove o goal ativo. Aliases: stop · off · reset · none · cancel.

▸ A sacada arquitetural

VOCÊ — define a condição uma vez │ ▼ WORKER (turno principal do Claude) — faz o trabalho │ ▼ EVALUATOR (modelo pequeno e rápido, Haiku por padrão) — lê o transcript, decide "pronto?" │ ├─ sim → goal limpo, controle volta pra você └─ não → razão é injetada como guia, worker pega mais um turno

Essa separação é o que faz o comando valer a pena. O worker fica otimista ("quase lá"); o evaluator é cético ("você disse que os testes passam — me mostra"). Dois papéis, dois modelos, um loop.

▸ Um primeiro goal

/goal todos os testes em test/auth passam e o passo de lint está limpo

Enquanto o goal está ativo, um indicador ◎ /goal active mostra há quanto tempo está rodando. A condição pode ter até 4.000 caracteres — o suficiente pra detalhar restrições.

Aprofundar → docs oficiais do /goal
Próximo → §2 · /goal vs alternativas
§2

/goal vs /loop vs Stop Hook vs Modo Auto

fundamentos

TL;DR — quatro mecanismos mantêm uma sessão rodando entre prompts. Escolhe por o que deve iniciar o próximo turno e quem decide que está pronto.

▸ A comparação de quatro

/goal próximo turno: turno anterior termina · para: modelo evaluator diz "pronto" /loop próximo turno: intervalo de tempo passa · para: você para OU Claude julga pronto Stop hook próximo turno: turno anterior termina · para: SEU script/prompt decide Modo auto próximo turno: nunca (turno único) · para: Claude julga trabalho pronto /goal e Stop hook ambos disparam após cada turno. /goal é açúcar com escopo de sessão em cima de um Stop hook baseado em prompt. Modo auto é ortogonal — remove prompts por ferramenta, não inicia novos turnos. Combina: /goal + modo auto = loop sem supervisão.

▸ Quando puxar cada um

  • /goal — trabalho substancial com um estado final verificável, em que o evaluator consegue ler a prova no transcript. Migração até os testes passarem. Quebrar um arquivo até cada pedaço estar abaixo de um limite de tamanho.
  • /loop — polling agendado. "Checa o deploy a cada 5 min." "Cuida de uma fila de PR." Não é uma condição de conclusão; é uma cadência de re-execução.
  • Stop hook — quando você quer um check determinístico (comando shell, exit code) ou lógica de prompt customizada que vive nas settings e vale na sessão inteira.
  • Modo auto — combine com qualquer um dos acima quando você não quer prompts de permissão por ferramenta. Crítico pra uso sem supervisão; ortogonal a "quando o loop para".
Aprofundar → opções de agendamento (docs Anthropic)
Próximo → §3 · Anatomia de uma boa condição
§3

Anatomia de uma boa condição

prática

TL;DR — uma condição que sobrevive a 20+ turnos tem três ingredientes: um estado final mensurável, um check declarado que o Claude pode rodar, e restrições nomeando o que não pode mudar.

▸ Ingrediente 1 — Estado final mensurável

Uma quantidade observável que vai de "ainda não" pra "sim" exatamente uma vez. Não é uma sensação. Exemplos que funcionam: exit code de uma execução de testes, contagem de arquivos, tamanho de uma fila, "git status limpo". Exemplos que falham: "o código está bom", "os usuários vão ficar felizes", "production-ready".

▸ Ingrediente 2 — Check declarado

Como o Claude deve provar o estado final. O evaluator lê o transcript; se a prova não está no transcript, o goal trava. Soletra o comando que o Claude deve rodar: "npm test sai com exit 0", "jq . config.json executa com sucesso", "o diretório build/ contém index.html".

▸ Ingrediente 3 — Restrições

O que não pode mudar enquanto chega no estado final. Sem isso, o worker pode "consertar" testes deletando eles ou fazer downgrade de uma dep em vez de corrigir o bug.

/goal todos os testes em test/auth passam (npm test --silent sai com exit 0),
o diff só toca em src/auth/* e test/auth/*,
e package.json fica inalterado.

▸ O orçamento de 4.000 caracteres

A condição pode ser longa — usa esse espaço. Uma condição de dois parágrafos com restrições tipicamente performa melhor que uma de cinco palavras porque o evaluator tem mais pistas pra julgar. A partir de ~1.000 caracteres o worker também lê ela como uma mini spec.

Aprofundar → Master Class §4 Permissões (o pareamento de segurança)
Próximo → §4 · Galeria de bom vs ruim
§4

Bom vs Ruim — uma galeria

prática

TL;DR — lê esses lado a lado. O padrão se revela mais rápido que qualquer regra.

▸ Testes

✓ /goal todos os testes em test/auth passam (npm test --silent sai com exit 0)
✗ /goal conserta os testes

▸ Migração

✓ /goal todo call site de db.queryOld foi substituído por db.queryV2,
   bun tsc --noEmit sai com exit 0, nenhum .ts fora de src/db toca em db.queryOld
✗ /goal migra as chamadas de banco

▸ Limpeza

✓ /goal CHANGELOG.md tem uma entrada por PR mergeado nos últimos 7 dias
   (verificado por gh pr list --state merged --search "merged:>=2026-05-10");
   cada entrada tem data, tipo e link.
✗ /goal atualiza o changelog

▸ Refactor

✓ /goal src/parser.ts foi quebrado de modo que cada arquivo resultante tem ≤200 linhas,
   todos os callers compilam, bun test sai com exit 0, nenhuma nova dep em package.json
✗ /goal quebra o parser em arquivos menores

▸ Backlog

✓ /goal toda issue com label "good-first" está fechada,
   com label "blocked", ou tem um comentário meu explicando o próximo passo.
   Para depois de 30 turnos mesmo se não estiver pronta.
✗ /goal faz triagem das issues

▸ O padrão

Todo exemplo "bom" nomeia uma coisa pra contar, um comando pra rodar e o que fica intocado. Todo exemplo "ruim" nomeia um verbo e confia que o worker vá definir "pronto".

Próximo → §5 · Pondo limites no run
§5

Pondo limites no run

prática

TL;DR — não há limite built-in numa sessão de /goal. Adiciona uma cláusula de parada na própria condição, ou queima dinheiro enquanto dorme.

▸ Built-in: nada

Um goal continua rodando até o evaluator dizer "sim" ou você rodar /goal clear. Não há max-turn padrão, não há orçamento padrão, não há timeout padrão.

▸ Três formas de limitar

  1. Inline na condição. Anexa "ou para depois de 20 turnos" ou "ou para depois de 1 hora". O worker reporta progresso a cada turno; o evaluator lê o progresso e julga a cláusula.
  2. Caps headless. Quando rodando com -p, adiciona --max-turns N e --max-budget-usd X na CLI. Esses são impostos pelo próprio Claude Code, não pelo evaluator.
  3. Kill switch externo. Ctrl+C no modo interativo, ou matar o processo no headless. Bruto mas confiável.

▸ Um goal limitado na prática

/goal flake-2-de-5 em test/network/* está resolvido
(rodando cada suite 5× e mostrando 5/5 passes no output),
ou para depois de 25 turnos. Restrição: não tocar em test infra
a não ser que o setup de um único arquivo de teste seja a causa.

▸ Uma razão real pra setar um cap

Sem cap, um goal que não consegue convergir vai iterar pra sempre, cada turno custando dinheiro real. O autor da claude-goal da comunidade (pré-oficial) defaultou pra 500 continuações como proteção contra runaway — o que te diz o quão ruim isso pode ficar.

Aprofundar → Master Class §9 Custo & Fit do Modelo
Próximo → §6 · Como o evaluator funciona
§6

Como o evaluator funciona

internos

TL;DR/goal é um wrapper sobre um Stop hook baseado em prompt, com escopo de sessão. Após cada turno, condição + transcript são enviados pro modelo pequeno e rápido configurado (padrão: Haiku). Ele retorna sim/não + uma razão curta. É toda a máquina.

▸ O loop, em detalhe

turno N termina │ ▼ Stop hook dispara (escopo de sessão, instalado pelo /goal) │ ▼ monta payload: {condição, transcript-até-agora} │ ▼ envia pro modelo pequeno e rápido (tier "haiku" do provider por padrão) │ ▼ parseia resposta: {decision: "yes" | "no", reason: "..."} │ ├─ sim → goal limpo, entrada "achieved" escrita no transcript, controle volta └─ não → razão injetada como guia, turno N+1 inicia imediatamente

▸ O que o evaluator CONSEGUE ver

  • Toda mensagem de usuário e mensagem de assistant no transcript da sessão.
  • A condição que você setou.
  • Chamadas de tools e seus resultados, incluindo stdout e exit codes que o Claude já rodou.

▸ O que o evaluator NÃO consegue ver

  • Arquivos no disco que ele ainda não vê no transcript.
  • Qualquer coisa que o Claude não printou. Um teste que passa silenciosamente não conta até o Claude mostrar o exit code.
  • Estado vivo. O evaluator não consegue abrir um browser, não consegue bater numa API, não consegue chamar tools.

▸ O custo

Tokens do evaluator são cobrados no tier de modelo pequeno e rápido (classe Haiku) e tipicamente são desprezíveis comparados ao turno principal. Concretamente: uma sessão de goal de 20 turnos que custa $4 em tokens de worker pode adicionar $0.05 em tokens de evaluator.

▸ A nota de implementação que importa

Como /goal É um Stop hook, ele fica indisponível quando disableAllHooks está setado ou quando allowManagedHooksOnly o bloqueia. O diálogo de trust precisa estar aceito pro workspace. O comando te diz por que está indisponível em vez de silenciosamente não fazer nada.

Aprofundar → Hook Cookbook §2 Receita de Stop hook
Próximo → §7 · /goal headless
§7

/goal headless

produção

TL;DR — passa /goal <condição> como o prompt pra claude -p e o loop inteiro roda em uma invocação só. Combina com --max-turns + --max-budget-usd + modo auto pra ter um agente sem supervisão com tetos duros.

▸ A forma headless

claude -p "/goal CHANGELOG.md tem uma entrada por PR mergeado nesta semana"
        --permission-mode bypassPermissions
        --max-turns 30
        --max-budget-usd 1.50
        --output-format json

▸ Um passo real de GitHub Actions

- name: Triagem noturna de issues
  run: |
    claude -p \
      --permission-mode bypassPermissions \
      --max-turns 40 \
      --max-budget-usd 2.00 \
      --output-format json \
      "/goal toda issue com label 'needs-triage' está
       (a) com label de um de {bug, feature, question, won't-fix},
       (b) fechada com uma razão, ou
       (c) comentada com uma pergunta de follow-up pro autor.
       Para depois de 40 turnos mesmo se não estiver pronto."
  env:
    ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}

▸ Comportamento no resume

Se uma sessão termina com um goal ainda ativo, --resume ou --continue restaura a condição. A contagem de turnos, o timer, e o baseline de tokens resetam no resume. Um goal já achieved não é restaurado.

▸ As três regras de disciplina

  1. Sempre seta --max-turns E --max-budget-usd. Headless sem caps é um runaway disfarçado de workflow.
  2. Trata o envelope --output-format json como contrato — falha o passo do CI se o JSON estiver malformado em vez de deixar o consumidor downstream consumir lixo.
  3. Usa o modo bypassPermissions em CI, nunca numa workstation de verdade. Sandboxes de CI são efêmeras; o ~ do seu laptop não é.
Aprofundar → Master Class §12 CI/CD & Headless
Próximo → §8 · Limitações & anti-padrões
§8

Limitações & Anti-padrões

produção

TL;DR — cinco modos de falha queimam dinheiro ou colocam código ruim no ar. Lê esses antes de setar seu primeiro goal de longa duração.

▸ #1 — A condição não é observável

"Deixa o app production-ready" nunca consegue ser provado num transcript. O evaluator não tem noção de "ready"; só consegue checar o que o Claude printou. Sintoma: cada turno o evaluator diz "ainda não" e o loop roda pra sempre. Correção: reescreve como uma lista de estados finais contáveis ("0 erros de lint, 0 erros de tipo, todos os testes passam, >80% de cobertura de linha medida por vitest --coverage").

▸ #2 — O worker "conserta" deletando

"Todos os testes passam" pode ser satisfeito deletando os testes que falham. Sintoma: goal atinge em 3 turnos, suite está vazia. Correção: adiciona uma restrição — "nenhum arquivo de teste é deletado; git diff --name-only test/ mostra só modificações, não deleções".

▸ #3 — Goals compostos sobrecarregam o worker

"Migra o DB E refatora o parser E escreve a doc" é estados finais independentes demais. O worker faz context-switch, o evaluator se confunde com sinais misturados, o loop nunca converge. Correção: sequencia eles — três goals, um de cada vez, seta o próximo quando o anterior atingir.

▸ #4 — Sem cap de turno num goal exploratório

Goals em tarefas onde não está claro quantos turnos são necessários (debugar um flake, explorar uma codebase desconhecida) facilmente rodam 100+ turnos. Correção: sempre inclui "ou para depois de N turnos" pra trabalho exploratório. Você sempre pode setar outro goal depois.

▸ #5 — Confiar na entrada "achieved"

O evaluator pode estar errado. "Sim os testes passam" pode significar "o último comando npm test que o Claude rodou saiu com exit 0" — mas o Claude pode ter stubado a assertion que falhava. Correção: pra goals de alto risco, adiciona um check externo (uma execução separada de CI, um code review) depois que o goal atinge. /goal é um focador forte de atenção, não um substituto pra review.

▸ Quando NÃO usar /goal de jeito nenhum

  • Edições rápidas. Um fix de duas linhas não precisa de loop; só pede.
  • Trabalho genuinamente exploratório. Se você não sabe como "pronto" se parece, /goal não é a ferramenta. Tenta /loop com um intervalo de polling, ou só itera.
  • Trabalho que exige julgamento humano por turno. Code review, decisões de design, qualquer coisa com aceitação subjetiva. O evaluator não consegue ver seu gosto.
Aprofundar → Master Class §4 Permissões (combina /goal com caps + deny lists)