Time drives one. State drives the other.
Both commands answer the same question — what makes Claude take the next turn without you typing it — and they answer it differently. `/loop` fires a prompt when a time interval elapses. `/goal` continues the session when a separate model reads the transcript and decides the work isn't finished yet.
The documentation puts them side by side on purpose. They are not alternatives to pick between once; they are two axes. Reach for the clock when the outside world changes on its own schedule. Reach for the condition when the work has a finish line you can describe.
`/loop` repeats on a timer. `/goal` repeats until a condition holds. Neither survives a closed session.
A timer on the oven versus a thermometer in the meat. The timer knows nothing about the food — it just rings every ten minutes so you go look. The thermometer doesn't care how long it takes; it tells you when it's done.
Both die when the session dies
This is the constraint that decides everything else. Close the terminal, shut the laptop, and neither command survives. There is a third path for work that has to outlive the session, and it is not a Claude Code command at all.
Four pieces to hold in your head
The mechanics are simple once you separate what triggers the next turn from what ends the run. Two different questions, and each command answers them differently.
Why the evaluator is the interesting part
The evaluator only sees what Claude surfaced in the conversation. It cannot run a test or open a file to check for itself. So a condition is only as good as the evidence Claude puts on screen — write conditions that force the proof into the transcript, not conditions that assume it.
This trips people up. A goal keeps the turns coming; it does not approve tool calls. Claude will still stop and ask on anything not already permitted. Pair it with auto mode if you want it to run unattended.
Three ways to keep working, one boundary
The docs compare the first two directly. The third is not in the docs — it is what you use when the session boundary is the dealbreaker.
Next turn fires on a clock. Stops when you stop it, when Claude decides the work is done, or at the 7-day expiry.
Next turn fires as soon as the previous one ends. Stops when the evaluator confirms the condition is met.
System cron or launchd calls Claude headless. Survives closed terminals and reboots. No session to lose.
`/loop` and `/goal` cost nothing to set up and vanish with the session. Headless costs you a scheduler, a script, and somewhere for the output to land — and it runs whether you are there or not.
Using them without surprises
Most of the friction with these two commands comes from four documented behaviours that are easy to miss on first read.
The evaluator reads the conversation, nothing else. "Tests pass" works only if Claude actually ran them and the output is on screen.
There is no max-turns flag. Add the limit to the text: "...or stop after 20 turns." Claude reports progress against your clause.
Recurring tasks fire up to 30 minutes late by design — half the interval on sub-hourly jobs. The offset is deterministic, derived from the task ID.
Esc stops a `/loop` that is waiting for its next iteration. Tasks you scheduled by asking Claude in plain language are not stopped by Esc — those need deleting.
Recurring loops self-delete after 7 days. A goal clears itself when met, on `/clear`, or with `/goal clear`. Fifty scheduled tasks per session is the ceiling.
Running `/goal` headless with `claude -p` prints nothing until the condition is met. Add `--output-format stream-json --verbose` to watch it work instead of staring at a blank terminal.
End-to-end: a fix that has to survive CI
A test file is failing and the fix needs to land, pass CI, and reach production. Three different waits, and each one wants a different mechanism.
There is no interval here — you have no idea how long it takes. You know what done looks like, so you describe it and let Claude keep going.
The reason from each round feeds the next turn as guidance. Run `/goal` with no argument at any point to see the condition, the turn count, the spend, and the last reason.
CI belongs to someone else's clock. There is no condition to evaluate locally — you just want to be told when the outside world changes.
You close the laptop. The loop stops firing and the goal freezes — both restore with --resume, but nothing happened while you were gone. If the work had to continue anyway, it never belonged in a session.
The logic lives in a Markdown file, not in the crontab line. Edit the brief without touching the schedule — and give the output somewhere to land, or the run may as well not have happened.
Three waits, three mechanisms, one rule to remember: match the trigger to what you are actually waiting for. A finish line you can describe wants `/goal`. A clock you don't own wants `/loop`. Anything that has to happen while you sleep never belonged in a session at all.
Code Examples
The first two are commands you type inside a session. The third is the escape hatch — plain shell, no session required.
`/loop` writes a cron entry scoped to your session and fires the prompt on that cadence, with deterministic jitter
`/goal` installs a session-scoped Stop hook; after every turn a small fast model reads the transcript and votes yes or no
On no, the evaluator's reason is handed to Claude as guidance and another turn begins; on yes, the goal clears itself
Both restore on --resume while unexpired — the turn count and spend baseline reset, the clock does not rewind