Claude / Operating Manual · Topics

← All Operating Manual pages

Loops & Autonomy

Make Claude Code run itself. In-session orchestration, self-paced multi-turn loops, scheduled cloud routines, and spec-driven autonomous runs. When to reach for which, and the cadence math nobody tells you.

GA · updated 2026-06-14

"Loops" is not one feature. It is the whole family of ways to make Claude Code keep working without you driving every turn. The community has a name for the skill now: loop engineering, the shift from typing prompts into an agent to writing the program that prompts the agent for you. As one widely shared post put it, "stop prompting your agent, start building loops." A loop is just a recursive goal: you define a purpose and the agent iterates until it is met.

The mechanisms sit on a spectrum, from inside a single response to fully detached from any session. Picking the right one comes down to two questions: how long is the gap between iterations, and who decides when the next one runs.

The five loop shapes

ShapeMechanismGap between iterationsWho paces itReach for it when
In-session orchestrationWorkflow tool (while / pipeline / parallel)ms to secondsthe scriptfan out many agents in one turn; loop until done / dry / budget
Self-paced multi-turn/loop (no interval) + ScheduleWakeupseconds to minutesthe modela task needing several turns at a cadence the model judges
Fixed-interval/loop 5m /cmdexactly Nyou (the interval)the same check on a clock (poll a deploy every 5 min)
Scheduled / detached/schedule, Cron toolsminutes to daysa cron, no session openrecurring jobs that run whether or not you are around
Spec-driven autonomousRalph (prd.json), /goaluntil donethe spec / goalgrind a whole backlog to completion, unattended

Most people babysit one agent at a time. The real gain is in the lower rows: handing a whole workflow to a running loop and walking away.

Anatomy of a loop that actually works

Recent write-ups converge on the same five parts. A loop missing the last two either spins forever or declares fake victory:

  1. Goal. The purpose the loop iterates toward.
  2. Step. The unit of work done each firing (a prompt, a command, a workflow).
  3. State. Memory that survives across firings. For detached loops this is a real file on disk (a state.json the loop reads at the top and writes at the bottom), because a fresh firing starts with no conversation history.
  4. Verifier. How the loop knows progress is real (tests pass, CI is green, the item is gone from the queue), not just that a turn happened.
  5. Stop condition. The exit. "Until the PR is green," "until the backlog is empty," "after N idle rounds." Without it you have a runaway.

Verification, cost, and a stopping criterion are the three things that separate a loop you can leave alone from one you have to watch.

The building blocks

Background tasks. Bash(run_in_background: true) detaches a command. It keeps running across turns and re-invokes you when it exits. You do not poll it; the harness wakes you. Foreground sleep is blocked on purpose; to wait on a condition, use a Monitor with an until loop. This is the primitive everything else is built on. See Background tasks.

Monitor. Streams events from a long-running script: every stdout line becomes a notification. Three patterns, by how many notifications you want:

  • one notification ("tell me when the build is done") → Bash background with an until loop that exits;
  • one per occurrence, forever ("every ERROR line") → Monitor with tail -f / while true;
  • one per occurrence until a known end ("each CI step, stop when the run completes") → Monitor with a command that emits then exits.

/loop. A built-in skill that runs a prompt or slash command repeatedly. Give it an interval (/loop 5m /babysit-prs, units s / m / h / d) for clockwork, or omit the interval to let the model pace itself turn to turn. Default interval if you say nothing is about 10 minutes. It is session-scoped: it lives and dies with the session.

ScheduleWakeup. The pacing engine behind self-paced /loop. You pick delaySeconds (clamped to 1 minute up to 1 hour) and pass the same prompt forward so the next firing repeats the task. Short waits while a build finishes, long waits when nothing is pending. The non-obvious part is cost. See the next section.

Cron tools and /schedule. For work that should run with no session open. /schedule creates cloud routines; the Cron tools (CronCreate / CronList / CronDelete) schedule programmatically using standard 5-field cron expressions (*/15 * * * *, wildcards, ranges, steps, lists). One-time future runs are supported too. Safety rails: recurring tasks auto-expire after a bounded window (docs and community cite about 7 days, after which it fires one last time and deletes itself), and a session caps at around 50 scheduled tasks, so a forgotten loop cannot run forever. (Verify the exact current numbers in the docs; they have moved.)

Workflows. Deterministic in-session fan-out. Scripts persist at .claude/workflows/<name>.js, are invoked by name with args, compose one level deep, and are cron-schedulable, which is how an in-session orchestration loop becomes a detached recurring one. See Workflows.

Ralph / /goal. Spec-driven autonomous runners. Convert a PRD to prd.json (/ralph) and the agent loops the backlog until it is done; /goal runs until a stated goal is met. The in-session cousins are the Workflow tool's loop-until-dry and loop-until-budget patterns.

Wake-up cadence and the prompt cache

When you self-pace with ScheduleWakeup, delaySeconds is not just "how long to wait." The Anthropic prompt cache has a 5-minute (300s) TTL. Sleep past it and the next wake-up re-reads your whole conversation uncached: slower and more expensive. So there are only two sensible bands:

  • 60 to 270s (cache stays warm). Use only when you are actively polling external state the harness cannot notify you about: a CI run, a deploy, a remote queue.
  • 1200s or more (one cache miss buys a long wait). Use for idle ticks, or as a long fallback heartbeat when something else is the real wake signal.

Never pick 300s. It pays the cache miss without amortizing it. If you are tempted to "wait 5 minutes," drop to 270s (stay warm) or commit to 1200s and up (amortize the miss).

And the trap that wastes the most money: do not poll for work the harness already tracks. A run_in_background task or a workflow re-invokes you automatically when it finishes, so a short wake-up just to "check on it" is wasted. Schedule a long fallback (1200s or more) as a safety net and let the notification do the waking.

Decide: which loop do I reach for?

  1. All inside one response (fan out agents, retry until clean)? → Workflow tool loop. No /loop, no scheduling.
  2. Needs several turns, but only while I'm in the session?
    • same action on a fixed clock → /loop <interval> <cmd>
    • cadence the model should judge → /loop with no interval (self-paced)
  3. Should run when no session is open?/schedule (cloud routine) or CronCreate (programmatic), recurring or one-time.
  4. "Grind this whole backlog to done, unattended"? → Ralph / /goal.
  5. Just waiting on one background thing to finish? → don't loop at all. Fire it with run_in_background (or a workflow) and let the auto re-invoke wake you; add one long ScheduleWakeup fallback only as insurance.

The three that get confused are /loop (repeat in-session), Cron (schedule in-session or programmatic), and /schedule (detached cloud routine). Rule of thumb: in-session and rhythmic → /loop; survives the session closing → /schedule or Cron.

Recipes

1. Babysit a CI run (external state the harness can't see). The run is outside the harness, so you must poll. Keep the cache warm:

/loop            # self-paced, no interval
→ poll `gh run watch` / the run status
→ still running:  ScheduleWakeup delaySeconds: 270, reason: "watching CI run #1234"
→ done:           report result, end the loop (omit ScheduleWakeup)

270s keeps you in cache across the roughly 8-minute run instead of paying a cache miss per tick.

2. Wait on a local build (harness-tracked): the anti-recipe. Do not /loop and poll. Background it and get woken:

Bash(run_in_background: true): npm run build
# keep working; the harness re-invokes you when it exits

If you must guard a hang, add one ScheduleWakeup delaySeconds: 1800 fallback, not a 60s poll.

3. 24-hour autonomous run (detached, durable). The community pattern: Claude Code plus CronCreate plus a state file on disk. The cron fires the step, the step reads and writes state.json, the verifier gates each cycle, the stop condition retires the cron.

/schedule  (or CronCreate "0 * * * *")  → step reads state.json → does work
           → verifier (tests/CI green?) → writes state.json → repeats
           → stop when goal met; recurring task also auto-expires as a backstop

4. Nightly portfolio sweep (recurring, no session open).

/schedule  → cron "0 6 * * *"  → run /content-sweep (or a custom routine)

Reports back when it runs; you read the result next time you're in.

5. Stream errors during a long local run (per-occurrence).

Monitor: tail -f dev.log | grep -E --line-buffered "ERROR|Traceback|FAILED|Killed"

One notification per matching line. Grep the failure signatures, not just success, or a crash looks identical to "still running."

6. Grind a backlog to done (autonomous).

/ralph  → prd.json  → loops until every task is complete

Best for well-scoped, verifiable work (migrations, broad refactors), not open-ended design.

Failure modes

  • Polling harness-tracked work. A 60s wake-up to "check the background job" burns the cache several times before the job finishes, for nothing. Let the auto re-invoke wake you; schedule only a long fallback.
  • The 300s cache cliff. A round "5 minutes" is the worst possible delay. 270s or 1200s and up, never 300.
  • No stop condition means a runaway. A self-paced loop with no exit keeps firing. The Workflow tool has a 1000-agent backstop and scheduled tasks auto-expire, but a bare /loop relies on you defining the exit. State it up front, then end the loop by omitting the next wake-up.
  • No verifier means fake victory. A loop that checks "did a turn happen" instead of "did the test pass" will happily report a broken build as done. Gate on real signal.
  • Loops run in isolation. A running loop has no built-in way to reach another loop, another agent, or your Slack. Cross-loop coordination is on you (shared state file, a queue, an external trigger), so don't assume two loops can talk.
  • Cron without a cost cap. A detached recurring agent that calls a paid API spends while you sleep. Put the spending cap in the job, not in your intentions. (House rule: every paid API gets a daily cap.)
  • Forgetting it's session-scoped. /loop and Cron tools die when the session closes. If it has to survive that, it belongs in /schedule or a cloud routine.

Quick reference

You wantReach forKey form
Fan out + loop in one turnWorkflow toolwhile (budget.remaining()...), parallel, pipeline
Same task every N min (in session)/loop/loop 5m /cmd
Model-paced multi-turn (in session)/loop + ScheduleWakeupomit interval; delaySeconds 270 or 1200+
Wait on background workrun_in_backgroundno loop; auto re-invoke + 1800s fallback
Per-line event streamMonitortail -f | grep --line-buffered
Recurring, no session open/schedule / CronCreate5-field cron expression
Unattended backlog grindRalph / /goalprd.json / goal statement

Cadence cheat: poll external state → 270s. Idle tick → 1200 to 1800s. Never 300s.

The mechanics above have a quick-reference card at Scheduled tasks & /loop.

Related reference

  1. Scheduled tasks & /loopRun a prompt on a repeat or on a clock. /loop and the Cron tools schedule inside a session; /schedule runs detached cloud routines.
  2. Background TasksCoordinate long-running work across sessions, subagents, and context windows with a shared task list stored on disk.
  3. WorkflowsHave Claude orchestrate tens to hundreds of parallel subagents in the background, with verification.