Source: Anthropic official docs — Scheduled tasks Type: Product Feature Product: Claude Code Requires: Claude Code v2.1.72 or later

Session-scoped scheduling for Claude Code: re-run a prompt automatically on an interval (poll a deploy, babysit a PR, watch a build), or set a one-time reminder. Tasks live inside the current conversation and stop when you start a new one. Unlike Routines (cloud, durable) or Desktop scheduled tasks (machine-resident, durable), /loop is the lightweight option for inside an open session. To keep the session working turn after turn until a condition is met rather than on a fixed schedule, see the goal` command (Week 20, v2.1.139)/goal is goal-convergent (Claude decides when done), while /loop is schedule-driven.

Three scheduling options compared

Cloud RoutinesDesktop scheduled tasks/loop (this article)
Runs onAnthropic cloudYour machineYour machine
Requires machine onNoYesYes
Requires open sessionNoNoYes
Persistent across restartsYesYesRestored on --resume if unexpired
Local file accessNoYesYes
MCP serversPer-taskConfig files + connectorsInherits from session
Permission promptsNone (autonomous)ConfigurableInherits from session
Customizable scheduleVia /scheduleYesYes
Minimum interval1 hour1 minute1 minute

/loop usage

Alias: /proactive is an alias for /loop as of Week 16 (v2.1.105). Both forms work identically.

FormExampleBehavior
Interval + prompt/loop 5m check the deployRuns on a fixed cron schedule
Prompt only/loop check the deployClaude picks an interval (1m–1h) per iteration
Interval only / nothing/loop or /loop 15mRuns the built-in maintenance prompt or loop.md

You can also pass another slash command as the prompt: /loop 20m /review-pr 1234. As of v2.1.196, a scheduled fire only runs skills that Claude is allowed to invoke on its own — built-in commands (/permissions, /model, /clear), skills marked disable-model-invocation: true, skills withheld by a skillOverrides setting or Skill deny rule, and MCP prompts (e.g. /mcp__github__list_prs) all reach Claude as plain text instead of executing. Skills an MCP server exposes via the skills primitive still run.

Fixed interval

Supplied intervals can lead (30m do X) or trail (do X every 2 hours) the prompt. Units: s, m, h, d. Seconds round up to the nearest minute (cron has 1-minute granularity). Intervals like 7m or 90m are rounded to the nearest clean cron step and Claude tells you what was picked.

Claude-paced (dynamic) interval

When you omit the interval, Claude chooses one between 1 minute and 1 hour after each iteration based on what it observed: short waits while a build is finishing, longer when nothing is pending. The chosen delay and reasoning print at the end of each iteration. Claude may use the Monitor tool (built-in since v2.1.98, Week 15) for these — a background watcher that streams events into the conversation as new transcript messages, often more token-efficient than re-running prompts. With Monitor, /loop check CI on my PR can stop polling entirely and just react to events as they happen.

Bedrock / Vertex AI / Microsoft Foundry: prompt with no interval runs on a fixed 10-minute schedule instead.

Built-in maintenance prompt

Bare /loop runs Claude through, in order:

  • continue any unfinished work from the conversation,
  • tend to the current branch’s PR (review comments, failed CI, merge conflicts),
  • run cleanup passes (bug hunts, simplification) when nothing else is pending.

Irreversible actions (push, delete) only proceed when they continue something the transcript already authorized.

Bedrock / Vertex AI / Microsoft Foundry: /loop with no prompt prints usage instead of running the maintenance loop.

loop.md (custom default)

Replace the built-in maintenance prompt with your own. Two locations, first match wins:

PathScope
.claude/loop.mdProject-level. Takes precedence when both files exist.
~/.claude/loop.mdUser-level. Applies in any project that does not define its own.

Plain Markdown — write it like you’d type a /loop prompt directly. Edits take effect on the next iteration. Truncated past 25,000 bytes.

Bedrock / Vertex AI / Microsoft Foundry: loop.md isn’t read on third-party providers — /loop with no prompt prints the usage message instead.

Stopping a loop

Press Esc while it’s waiting for the next iteration. This clears the pending wakeup. Tasks scheduled by asking Claude directly (not via /loop) are not affected by Esc — delete them with the cron tools.

In self-paced mode (dynamic-interval /loop), Claude can also end the loop on its own by calling the ScheduleWakeup tool with stop: true (v2.1.202+). This cancels the pending wakeup immediately. Before v2.1.202, not rescheduling was the only way Claude could end a loop autonomously. Fallback behavior: if a self-paced iteration ends without either rescheduling or stopping, Claude Code schedules one fallback wakeup ~20 minutes later; if that fallback iteration also doesn’t reschedule, the loop ends.

Fixed-interval loops keep running until you press Esc or seven days elapse — ScheduleWakeup stop:true only applies to self-paced loops.

One-time reminders

Describe in natural language; Claude schedules a single-fire task that deletes itself after running.

remind me at 3pm to push the release branch
in 45 minutes, check whether the integration tests passed

Manage scheduled tasks

Ask Claude in natural language (“what scheduled tasks do I have?”, “cancel the deploy check”), or reference the underlying tools:

ToolPurpose
CronCreateSchedule a task. Takes a 5-field cron expression, the prompt, and recurring vs one-shot.
CronListList all scheduled tasks with IDs, schedules, and prompts.
CronDeleteCancel a task by 8-character ID.

A session can hold up to 50 scheduled tasks at once.

Cron expression reference

5-field standard: minute hour day-of-month month day-of-week. Wildcards (*), single values (5), steps (*/15), ranges (1-5), comma lists (1,15,30).

ExampleMeaning
*/5 * * * *Every 5 minutes
0 * * * *Every hour on the hour
0 9 * * *Every day at 9am local
0 9 * * 1-5Weekdays at 9am local
30 14 15 3 *March 15 at 2:30pm local

Day-of-week: 0 or 7 is Sunday, 6 is Saturday. Not supported: extended syntax like L, W, ?, name aliases (MON, JAN). When both day-of-month and day-of-week are constrained, a date matches if either matches (vixie-cron semantics).

All times interpreted in local timezone0 9 * * * is 9am wherever you’re running Claude Code, not UTC.

How tasks run

The scheduler checks every second for due tasks and enqueues them at low priority. A scheduled prompt fires between turns, not mid-response. If Claude is busy when a task comes due, the prompt waits until the current turn ends.

Jitter

To stop every session hitting the API at the same wall-clock moment:

  • Recurring tasks fire up to 30 minutes after the scheduled time (or up to half the interval, for tasks that run more often than hourly). An hourly job scheduled for :00 may fire anywhere up to :30. (Prior to W19, this was “up to 10% of period, capped at 15 minutes”.)
  • One-shot tasks scheduled for the top or bottom of the hour fire up to 90 seconds early.

The offset is derived from the task ID, so the same task always gets the same offset. Pick a non-:00/:30 minute (e.g., 3 9 * * *) to skip one-shot jitter entirely.

Seven-day expiry

Recurring tasks automatically expire 7 days after creation. They fire one final time, then delete themselves. To last longer, cancel and recreate before expiry — or use Routines / Desktop scheduled tasks for durable scheduling.

Disable scheduled tasks

Set CLAUDE_CODE_DISABLE_CRON=1 in your environment. The cron tools and /loop become unavailable; already-scheduled tasks stop firing.

Limitations

  • Tasks only fire while Claude Code is running and idle.
  • No catch-up for missed fires — busy through a scheduled time means it fires once when Claude becomes idle, not once per missed interval.
  • Starting a fresh conversation clears all session-scoped tasks. claude --resume / --continue restores unexpired tasks (recurring within 7 days of creation, one-shots whose time hasn’t passed). Background Bash and Monitor tasks are never restored on resume.
  • Backgrounding the session (via agent view) carries /loop tasks over to a background session, which keeps running without a terminal — useful for long-running loops that would otherwise die when you close your terminal.
  • .claude directory symlink check (v2.1.216). Claude Code stores the scheduled task list in the project’s .claude directory. Scheduling a task fails with an error when that directory, or the task file inside it, is a symlink. Before v2.1.216, Claude Code wrote the task file through the link.

Recent additions (2026-07-12 watchlist sweep)

New content in Claude Code scheduled tasks docs as of v2.1.202, sourced from ai-research/watchlist-snapshots/code-claude-com-docs-en-scheduled-tasks-2026-07-12.md:

  • ScheduleWakeup stop:true (v2.1.202). In self-paced (/loop dynamic) mode, Claude can now explicitly end a loop by calling ScheduleWakeup with stop: true. This cancels the pending wakeup immediately. Before v2.1.202, not rescheduling was the only mechanism for Claude to end a loop autonomously.
  • Fallback wakeup behavior documented. If a self-paced iteration ends without rescheduling or stopping, Claude Code schedules a single fallback wakeup ~20 minutes later. If that fallback also doesn’t reschedule, the loop ends. This bounds runaway loops without requiring explicit stop: true.
  • Fixed-interval loop stop clarification. Fixed-interval loops keep running until Esc or 7-day expiry — ScheduleWakeup stop:true does not apply to them.

Recent additions (v2.1.212, July 17)

New in v2.1.212, sourced from ai-research/claude-code-docs-changelog-2026-07-17.md and ai-research/claude-code-docs-whats-new-w29-2026-07-17.md:

  • /fork → new background session; /subtask = in-session fork (v2.1.212). /fork has changed semantics again. As of v2.1.212, /fork creates a new background session with its own row in claude agents — it copies the current conversation context and runs independently while the original session keeps going. The old in-session delegate behavior (dispatch a subagent within the current session, get its result back in-place) is now /subtask. This changes how /fork interacts with scheduled tasks: a /loop-managed session that forks now produces a fully independent background session, not an in-session delegate that the loop supervises. To preserve the old in-session parallel-work pattern, use /subtask instead.

    /fork evolution: Before June 2 (v2.1.160) → copy transcript to manually-driven new session; June 2, v2.1.160/161 → in-session subagent delegate; July 17, v2.1.212 → new background session (own claude agents row). /subtask is the new in-session delegate.

  • Task tool mode parameter deprecated (v2.1.212). The mode parameter on the Task tool is deprecated — scheduling logic has moved to the ScheduleWakeup tool (already the primary scheduling surface for /loop).

Recent additions (2026-08-02 watchlist sweep)

Content confirmed absent from the article and added from ai-research/watchlist-snapshots/code-claude-com-docs-en-scheduled-tasks-2026-08-02.md (pending item from the 2026-07-26 sweep):

  • .claude directory symlink check (v2.1.216). Claude Code stores the scheduled task list in the project’s .claude directory. Scheduling a task fails with an error when that directory, or the task file inside it, is a symlink. Before v2.1.216, Claude Code wrote the task file through the link.

Key Takeaways

  • /loop is the lightweight, session-scoped scheduler — for cloud durability use Routines; for machine durability, Desktop scheduled tasks.
  • Three usage shapes: fixed interval (/loop 5m ...), Claude-paced (/loop ... with no interval), or bare /loop for the built-in maintenance prompt or your loop.md.
  • Recurring loops auto-expire after 7 days; reset by recreating, or pick a durable scheduler upstream.
  • Jitter is deterministic (derived from task ID) — predictable per task, scattered across sessions in aggregate.
  • Esc cancels a pending /loop wakeup; in self-paced mode, Claude can also call ScheduleWakeup with stop: true (v2.1.202+) to end the loop intentionally. Cron tasks scheduled directly need CronDelete by ID.
  • Available since Claude Code v2.1.72. To turn off: CLAUDE_CODE_DISABLE_CRON=1.

Try It

  1. Smoke test: in any session, run /loop 1m print the time. Watch it fire once, cancel with Esc.
  2. PR babysitter: create .claude/loop.md in a project with: “Check the release/next PR. If CI red, pull the failing job log and propose a fix. If review comments arrived, address each. If green and quiet, say so in one line.” Then run bare /loop in that project.
  3. Self-paced poll: /loop check whether CI passed and address any review comments — Claude shortens intervals while active, lengthens once quiet.
  4. One-shot reminder: remind me in 45 minutes to check the integration tests.
  5. List with: “what scheduled tasks do I have?” Cancel with: “cancel the deploy check job.”

Open Questions

  • What is the precise “low priority” enqueue behavior — does a long-running tool call extend wait beyond the user’s current turn?
  • Are session-scoped tasks shared across claude --continue from different terminals, or per-tty?
  • Does the Monitor tool’s streaming output count toward the 50-task session limit?