Extend Soft ยท in-session ยท until-done GA v2.1.139+ ⓘ legend

Goal mode (/goal)

Condition-driven repetition inside an open session. /goal sets a completion condition and Claude keeps working turn after turn until it holds — without you prompting each step. After every turn a small fast model (Haiku by default) checks the condition; if it’s not met, Claude starts another turn instead of returning to you. This is the productized “ralph loop.”

Analogy โ€” a finish-line judge. Claude keeps running laps; after each lap a separate referee (a fresh Haiku call) checks whether you’ve actually crossed the line you described, and only then calls the race. The runner doesn’t get to declare its own victory.

/goal vs /loop vs a Stop hook vs auto mode All keep a session moving, but on different triggers. /loop advances on a clock (every N minutes); /goal advances when the previous turn finishes and stops when a condition is confirmed. A Stop hook also fires after every turn but lives in your settings and can run a custom script — /goal is the session-scoped shortcut for the common case. Auto mode removes per-tool prompts within a turn; /goal removes per-turn prompts — they’re complementary.

Mechanism โ€” a wrapper around a Stop hook

Setting a goal starts a turn immediately with the condition as the directive; you don’t send a separate prompt. Then each turn loops through:

turn finishes
evaluate
the condition + the conversation so far go to your small fast model (default Haiku)
verdict
yes / no + reason
“no” โ†’ Claude continues with the reason as guidance; “yes” โ†’ the goal clears
judged from
the transcript only
the evaluator reads what Claude surfaced; it does not run tools or read files itself
/goal all tests in test/auth pass and the lint step is clean   # set it; a turn starts immediately
/goal                                                          # status: turns, tokens, last reason
/goal clear                                                    # stop early (aliases: stop/off/reset/none/cancel)
claude -p "/goal CHANGELOG.md has an entry for every PR merged this week"   # run to completion, non-interactive
Writing an effective condition

Because the evaluator only judges what’s in the transcript, write the condition as something Claude’s own output can demonstrate. A durable condition has: one measurable end state (a test result, a build exit code, an empty queue); a stated check (“npm test exits 0”); and constraints that matter (“no other test file is modified”). Up to 4,000 characters. To bound runtime, add a clause like or stop after 20 turns.

One goal is active per session. A goal still active at session end is restored on --resume (the condition carries over; turn count, timer, and token baseline reset). An achieved or cleared goal is not restored. Running /clear also removes it.

Evaluation tokens bill on the small fast model and are typically negligible vs main-turn spend.

When to reach for it

โœ“
Substantial work with a verifiable end state — migrate every call site until tests pass; split a file until each module is under budget.
โœ“
Working a backlog until the queue is empty, where “done” is checkable from Claude’s output.
โœ“
You want a fresh model to decide completion, not the one that did the work (externalized completion).

When not to

โœ•
You mean “check every N minutes,” not “until done” โ†’ /loop.
โœ•
The condition can’t be shown in the transcript (needs the evaluator to run commands) โ†’ write a custom Stop hook instead.
โœ•
It must run unattended with your laptop closed โ†’ a routine.

Best practices

โ˜…
Pair with auto mode so each goal turn runs without per-tool approvals — otherwise it stalls on prompts.
โ˜…
Make the check concrete (“npm test exits 0”) so Claude surfaces evidence the evaluator can read.
โ˜…
Always bound it — a turn/time clause in the condition, plus an eye on token spend. Like any loop it can run a long way.
It’s a hook — so it needs trust /goal runs only in workspaces where you’ve accepted the trust dialog, because the evaluator is part of the hooks system. It’s unavailable when disableAllHooks is set at any level or allowManagedHooksOnly is set in managed settings (the command tells you why). And because completion is judged only from the transcript, a condition Claude can’t demonstrate will never clear.

Sources