TL;DR
/goal <condition>leaves a persistent note: "don't return control to me until this holds". After every turn, Haiku reads the transcript and decides yes/no against your condition. No → Claude starts another turn automatically. Yes → control returns to you. Use it for sweeping refactors, migrations, or draining an issue queue — anything with a verifiable "done".
There are tasks you know will finish, but they force you to type "keep going" every two turns. Migrating an import across the repo. Getting a legacy test suite to pass. Draining a labeled issue queue. After each turn Claude stops and waits for your nod. /goal breaks that cycle: you state the stop condition and stop being a human cron.
How it works
/goal wraps a session-scoped prompt-based Stop hook. Every time Claude finishes a turn:
- The condition and the conversation so far are sent to the small fast model (Haiku by default).
- The evaluator returns yes/no plus a short reason.
- "No" → Claude continues, with the reason injected as guidance for the next turn.
- "Yes" → the goal clears itself and control returns to you.
The evaluator does NOT call tools — it only reads what Claude has already surfaced in the conversation. Conditions must be verifiable from the transcript.
Result preview
> /goal all tests in test/auth pass and the lint step is clean
◎ /goal active · 0m
# Claude runs npm test → 3 failures
# Evaluator: condition not met — 3 tests still failing in test/auth/*
# Claude fixes the first test → next turn
# Claude fixes the other two → next turn
# npm test green, npm run lint clean
# Evaluator: condition met
◎ /goal cleared — achieved in 4m 12s, 6 turns
How to use it
1. Set the condition
/goal all tests in test/auth pass and the lint step is clean
Setting the goal starts a turn immediately, with the condition as the directive — no extra prompt needed. Up to 4,000 characters per condition.
2. Write conditions verifiable from the transcript
The evaluator only sees what Claude has surfaced in the conversation:
- "
npm testexits 0" → Claude runs it, the output lands in the transcript - "every
getUsercall site now readsfetchUser" → Claude greps, the result is visible - "the app is production-ready" → not verifiable, don't use it
Add constraints ("don't touch migrations") and an upper bound ("or stop after 20 turns") when there's a real risk of looping.
3. Status and cancel
/goal # status: condition, turns, time, tokens, last evaluator reason
/goal clear # cancel (aliases: stop, off, reset, none, cancel)
Running /clear to start a new conversation also drops the active goal.
4. Resume across sessions
If the session ended with an active goal, claude --resume or --continue restores it. The condition persists; the turn counter and timer reset.
5. Headless (CI / cron / scripts)
claude -p "/goal CHANGELOG.md has an entry for every PR merged this week"
Single invocation; runs until the condition holds or you hit Ctrl+C.
/goal vs /loop vs your own Stop hook
| When | Mechanism |
|---|---|
/goal |
There's a verifiable done: migration, refactor, draining an issue queue |
/loop |
Watch something at intervals: deploys, logs, new PRs |
| Your own Stop hook | Deterministic logic in a bash script, or a rule you reuse across sessions |
/goal is the closest thing to "Claude, don't come back to me until this is done".
And if the task is one of the hard, long ones, hand it to Fable 5 under a /goal and walk away for a while.
Reference
| Aspect | Detail |
|---|---|
| Command | /goal <condition> · /goal (status) · /goal clear |
| Active goals | 1 per session |
| Max size | 4,000 characters |
| Evaluator | Configured small fast model (Haiku by default), no tool access |
| Cost | Evaluator tokens, typically negligible vs the main turn |
| Requirements | Trusted workspace, hooks enabled (disableAllHooks disables it) |
| Persistence | Survives --resume / --continue (counters reset) |
| Headless | claude -p "/goal ..." runs until met or Ctrl+C |
Official docs: Keep Claude working toward a goal