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
- A sintaxe exata, incluindo aliases e o orçamento de 4.000 caracteres da condição.
- Quando
/goalganha de/loope um Stop hook — e quando não ganha. - Os três ingredientes de uma condição que sobrevive a mais de 20 turnos.
- Como o evaluator realmente decide "pronto", e o que ele nunca consegue ver.
/goalheadless em CI, mais os anti-padrões que queimam dinheiro silenciosamente.
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.
O que /goal é
fundamentosTL;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
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.
/goal vs /loop vs Stop Hook vs Modo Auto
fundamentosTL;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
▸ 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".
Anatomia de uma boa condição
práticaTL;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)Bom vs Ruim — uma galeria
práticaTL;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".
Pondo limites no run
práticaTL;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
- 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. - Caps headless. Quando rodando com
-p, adiciona--max-turns Ne--max-budget-usd Xna CLI. Esses são impostos pelo próprio Claude Code, não pelo evaluator. - 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.
Como o evaluator funciona
internosTL;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
▸ 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.
/goal headless
produçãoTL;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
- Sempre seta
--max-turnsE--max-budget-usd. Headless sem caps é um runaway disfarçado de workflow. - Trata o envelope
--output-format jsoncomo contrato — falha o passo do CI se o JSON estiver malformado em vez de deixar o consumidor downstream consumir lixo. - Usa o modo
bypassPermissionssó em CI, nunca numa workstation de verdade. Sandboxes de CI são efêmeras; o~do seu laptop não é.
Limitações & Anti-padrões
produçãoTL;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,
/goalnão é a ferramenta. Tenta/loopcom 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.