← All guides
πŸ€–automation

/goal vs /loop vs /schedule vs Ralph: Which Loop Do You Actually Need?

/goal vs /loop vs /schedule vs Ralph: Which Loop Do You Actually Need?

Four ways to make Claude Code run without you. They look interchangeable from the outside β€” "the agent keeps going" β€” but their stop conditions, lifetimes, and blast radii are completely different, and picking the wrong one is how you end up with a loop that either quits too early or never quits at all.

Here's the decision guide, with semantics verified against the official docs (all facts below are from code.claude.com/docs, checked 2026-07-01).

The one-table version

| | /goal | /loop | /schedule (Routines) | Ralph | |---|---|---|---|---| | Next turn starts when | previous turn finishes | interval elapses | cron fires / API call / GitHub event | previous process exits (fresh session) | | Stops when | fast model confirms condition from transcript | you stop it, Claude ends it, or 7-day expiry | you pause it / daily run cap | your harness says so (cap, check) β€” *nothing built in* | | Context | one continuous session | one continuous session | fresh clone per run | fresh context every iteration | | Lives where | your terminal | your terminal (session-scoped) | Anthropic cloud, laptop closed | wherever your bash runs | | Min interval | n/a (back-to-back) | 1 minute | 1 hour | n/a (back-to-back) | | Built-in cap | none β€” write it into the condition | 7-day expiry, 50 tasks/session | daily per-account run cap | none β€” you MUST add one | | Permission prompts | normal session rules | normal session rules | none at all (scoped by repo/branch/connectors) | whatever flags you pass | | Best for | converge on a verifiable outcome | poll something that changes | recurring/event-driven jobs | grinding a backlog overnight |

Now the nuance, because the nuance is where loops die.

`/goal` β€” when there's a finish line

/goal <condition> runs turn after turn until the condition holds. The mechanics matter: after each turn, a small fast model (defaults to Haiku) reads the transcript and answers yes/no. "No" comes with a reason, which becomes guidance for the next turn. Under the hood it's officially "a wrapper around a session-scoped prompt-based Stop hook."

Two properties trip people up:

1. The evaluator cannot run commands or read files. It judges only what's in the conversation. So /goal the auth module is refactored is unenforceable, but /goal npm test exits 0 and npx tsc --noEmit is clean β€” run both and show the output works, because Claude surfaces the proof in the transcript. 2. There is no built-in turn cap. The official pattern is to write the cap into the condition itself: ...or stop after 20 turns. Conditions max out at 4,000 characters; one goal per session; /goal alone shows status including token spend; the evaluator's own cost is billed on the fast model and is typically negligible.

Headless works too: claude -p "/goal ..." runs the whole loop in one invocation.

Pick /goal when the outcome is binary and provable from command output: [fix-tests-and-lint](/loops/fix-tests-and-lint) is the archetype, [kill-flaky-tests](/loops/kill-flaky-tests) the harder cousin (exit condition: 10 consecutive green runs). More at [/type/goal](/type/goal).

`/loop` β€” when there's no finish line, just a pulse

/loop 20m check CI and fix anything red re-runs a prompt on an interval while the session stays open. Key semantics:

  • Session-scoped. Tasks live in the current conversation, stop when you start a new one, and are restored on --resume only if unexpired.
  • Seven-day expiry. Every recurring task self-deletes 7 days after creation β€” an intentional bound on forgotten loops.
  • 1-minute minimum, and fires are jittery (up to 30 minutes late, or half the interval for sub-hourly). Never build a loop that assumes exact fire times.
  • Self-pacing. Omit the interval and Claude picks the delay each iteration (1 min–1 hr) based on what it saw, and can end the loop itself once work is provably done.
  • loop.md. A .claude/loop.md replaces the built-in maintenance prompt for bare /loop β€” your project's default loop, versioned in git.

Pick /loop when you're reacting to external change rather than converging on a state: [ship-pr-until-green](/loops/ship-pr-until-green) polls CI and pushes fixes until it's green. Browse [/type/loop](/type/loop).

`/schedule` β€” when the laptop is closed

/schedule creates a Routine: prompt + repos + connectors, executed on Anthropic-managed cloud infrastructure (research preview; Pro/Max/Team/Enterprise). Calling it "cloud cron" undersells it β€” one routine can have a schedule, an HTTPS fire endpoint, *and* GitHub event triggers.

The safety model is structural, and you should know it before you rely on it: routines run with no permission prompts at all. Blast radius is contained by fresh clones (no local files), pushes restricted to claude/-prefixed branches by default, connector scoping, and a daily per-account run cap. Minimum schedule interval is 1 hour β€” sub-hourly polling belongs in /loop, not a routine.

Pick /schedule when the job recurs on a calendar or fires on an event and doesn't need your machine: nightly audits, morning triage, PR-opened reviews. Examples at [/type/schedule](/type/schedule).

Ralph β€” when you want brute force with amnesia

The [original Ralph Wiggum loop](/loops/the-original-ralph-wiggum-loop) is a bash while true around claude -p "$(cat prompt.md)". Fresh context every iteration; all memory in files. That amnesia is the feature β€” no context rot, no 200-turn drift β€” and the danger: Ralph has no built-in stop, cap, or expiry. None. Every guardrail is yours to add: a hard MAX_ITER, a programmatic success check (never let the loop grade its own homework), and a guardrails file the agent reads at start and appends learnings to at the end of each pass.

There's also a bashless variant β€” a Stop hook that re-injects the prompt each time the agent tries to end its turn: [stop-hook-ralph](/loops/stop-hook-ralph-deterministic-loop-without-bash). Same semantics, one session, still needs a hard cap by construction. Whole family: [/type/ralph](/type/ralph).

Pick Ralph when you have a backlog of independent items and a mechanical check per item, and you're willing to build the harness. If you're not, you don't want Ralph yet.

The 30-second decision

  • Provable end state, one sitting? β†’ /goal (cap in the condition).
  • Watch something and react, this session? β†’ /loop (remember: 7-day expiry, jitter).
  • Recurring or event-driven, laptop closed? β†’ /schedule (1h minimum, no prompts β€” scope it).
  • Backlog to grind overnight, fresh context each pass? β†’ Ralph (bring your own cap or don't run it).

They compose, too: a routine that fires on PR events can set a /goal inside the run; a Ralph iteration is just a headless session that could itself carry a goal. And whichever you pick, an unattended loop should be able to tell you it finished β€” ConnectMyEmail gives your agent an email lane so "notify me" isn't the hard part of the harness.

Still unsure? Describe the job in the [loop builder](/builder) β€” it picks the loop type from your goal and exit condition and generates the harness, budgets included. Then run the result through [/grade](/grade) before its first unattended night.

Ready to run one? Browse the loop directory β†’