Skip to content

Scheduled tasks and /loop

Re-run prompts on an interval, let Claude pace its own polling, set one-off reminders and manage session-scoped cron jobs in Claude Code.

A lot of waiting happens during development: for CI, for a deploy, for a reviewer. Scheduled tasks let the session do the waiting. You give Claude a prompt and a cadence (or let it pick one), and it re-runs the prompt between your turns, for example checking a pipeline every few minutes and fixing whatever breaks.

These tasks belong to the session. If you need something that runs whether or not a terminal is open, use a different tool (compared below). If you would rather react to events than poll for them, look at channels, and if you want Claude to keep going turn after turn until a condition holds, see /goal.

Picking the right scheduler

Cloud routinesDesktop scheduled tasks/loop and session tasks
Where it runsAnthropic-managed cloud by defaultYour machineYour machine
Machine must be onNoYesYes
Session must be openNoNoYes
Survives restartsYesYesRestored on --resume, with exceptions
Local filesNo, a fresh cloneYesYes
MCP serversConnectors chosen per taskConfig files and connectorsWhatever the session has
Permission promptsNone, runs autonomouslyConfigurable per taskSame as the session
Custom scheduleVia /schedule in the CLIYesYes
Shortest interval1 hour1 minute1 minute

My rule of thumb: routines for anything that must run reliably while my laptop is shut, desktop tasks for recurring jobs that need my local toolchain, and /loop for "keep an eye on this while I work on something else".

/loop in three forms

/loop is a bundled skill. Both arguments are optional and the combination you give changes its behaviour:

You typeExampleResult
Interval and prompt/loop 10m is the staging deploy healthy yet?Fixed cron schedule
Prompt only/loop watch the PR and deal with review feedbackClaude chooses the gap after each run
Interval only, or nothing/loop or /loop 30mThe built-in maintenance prompt, or your loop.md

The prompt can be a skill invocation, such as /loop 15m /triage-inbox. On scheduled fires, only skills Claude may invoke by itself actually execute. These arrive as plain text instead:

  • Built-in commands like /model, /permissions or /clear.
  • Skills with disable-model-invocation: true (the bundled /verify skill is one).
  • Skills hidden from Claude by a skillOverrides setting or a Skill deny rule.
  • MCP prompts such as /mcp__jira__my_open_issues.

See Skills for how invocation control works.

Fixed intervals

Give an interval and Claude turns it into a cron expression, schedules it, and replies with the cadence and a job ID.

/loop 3m tail the migration job logs and tell me the moment it errors or completes

The interval can come first as a bare token (45m) or at the end as a phrase (every 2 hours). Units are s, m, h and d. Cron works in whole minutes, so seconds round up, and awkward values like 7m or 90m are rounded to the nearest interval cron can express cleanly; Claude tells you what it chose.

Self-paced loops

Leave the interval out and Claude decides how long to wait after each iteration, anywhere from one minute to one hour, depending on what it saw. A build in progress means short waits; a quiet PR means long ones. Each iteration ends with the chosen delay and the reason.

/loop keep the nightly-import PR green: rerun flaky jobs once, fix real failures, answer review comments

Where the Monitor tool is available, Claude may use it instead: Monitor runs a background script and streams each line of output back, which avoids polling and tends to be cheaper and quicker to react.

Self-paced loops show up in the task list and can be cancelled like any other. Jitter does not apply to them, but the seven-day expiry does.

The built-in maintenance prompt

A bare /loop runs Claude's own housekeeping prompt at a self-chosen interval (add an interval, such as /loop 20m, for a fixed cadence). Each pass, in priority order, it:

  1. Continues unfinished work from the conversation.
  2. Looks after the current branch's pull request: review comments, failing CI, merge conflicts.
  3. Does clean-up passes (bug hunting, simplification) when nothing else is waiting.

It does not start new initiatives, and irreversible steps such as pushing or deleting only happen when they continue something the conversation already approved.

Self-paced loops and the maintenance prompt work on every provider and with feature-flag fetching turned off. On Amazon Bedrock, Claude Platform on AWS, Google Vertex AI and Microsoft Foundry, or with fetching off, both need v2.1.248 or later.

Your own default with loop.md

Write a loop.md to replace the maintenance prompt for bare /loop. It is one default prompt, not a list of jobs, and it is ignored whenever you pass a prompt on the command line.

PathScope
.claude/loop.mdThis project; wins if both exist
~/.claude/loop.mdEvery project without its own

It is free-form Markdown. Mine for a client project looks like this:

Look at open PRs I authored on this repo.
- Failing checks: read the log, fix if the cause is in our code, otherwise comment with the cause.
- Unanswered review comments: address them and reply on the thread.
- Nothing to do: reply "all quiet" and nothing else.
Never force-push.

Changes apply from the next iteration, so you can tune it while the loop runs. Anything past 25,000 bytes is truncated.

Stopping a loop

  • Self-paced: press Esc while it is waiting to cancel the pending wake-up. Claude can also end the loop itself when the job is done by calling the ScheduleWakeup tool with stop: true. If an iteration neither reschedules nor stops, Claude Code sets a single fallback wake-up about 20 minutes later and ends the loop if that run does not reschedule either.
  • Fixed interval: runs until you cancel it (see below) or seven days pass. Esc does not affect tasks you scheduled by asking Claude directly.

One-off reminders

For a single future action, just say it:

at 17:30 remind me to switch the feature flag back off
in 20 minutes, check whether the Lighthouse run finished and summarise the scores

Claude schedules a one-shot task pinned to that hour and minute, confirms the time, and the task deletes itself after firing.

Listing and cancelling

Ask in plain language ("what's scheduled?", "cancel the deploy watcher"). Under the hood Claude uses three tools:

ToolDoes
CronCreateCreates a task from a five-field cron expression, a prompt, and whether it recurs or fires once
CronListShows every task with its ID, schedule and prompt
CronDeleteRemoves a task by ID

IDs are eight characters. A session can hold at most 50 tasks.

How firing works

  • The scheduler checks every second and queues due tasks at low priority.
  • A task fires between turns, never in the middle of a response. If Claude is busy, it waits for the turn to finish.
  • Times use your local time zone: 0 9 * * * is 09:00 where you are, not UTC.

Jitter

To stop every session in the world calling the API at the same instant, fire times get a fixed offset derived from the task ID:

  • Recurring: up to 30 minutes late, or up to half the interval for jobs more frequent than hourly. An hourly job at :00 might fire as late as :30.
  • One-shot at :00 or :30: up to 90 seconds early.

If timing matters, avoid the round numbers. 4 9 * * * instead of 0 9 * * * sidesteps the one-shot adjustment.

Seven-day expiry

Recurring tasks fire one last time seven days after creation and then delete themselves, so a forgotten loop cannot run forever. For longer schedules, recreate before expiry or move to routines or desktop tasks.

Cron syntax

Five fields: minute hour day-of-month month day-of-week. Each field accepts *, a single value, steps (*/10), ranges (1-5) and lists (0,20,40).

ExpressionFires
*/10 * * * *Every 10 minutes
15 * * * *Quarter past every hour
0 8 * * 1-508:00 on weekdays
30 18 * * 518:30 every Friday
0 0 1 * *Midnight on the first of each month
45 11 24 12 *11:45 on 24 December

Sunday is 0 or 7, Saturday 6. No L, W, ? or names like MON/JAN. If both day-of-month and day-of-week are restricted, a date matches when either does (standard vixie-cron behaviour).

Turning the scheduler off

Set CLAUDE_CODE_DISABLE_CRON=1. The cron tools and /loop disappear and existing tasks stop firing. Other disable switches are listed in Environment variables.

Limitations

  • Tasks fire only while Claude Code is running and idle. Close the terminal and they stop. Backgrounding the session (see agent view) carries /loop tasks into a background session that keeps going without a terminal.
  • Missed fires are not replayed. If several intervals pass during a long request, the task fires once when Claude is free.
  • claude --resume and claude --continue restore CronCreate tasks, except expired recurring tasks and one-shots whose time has passed. Self-paced /loop is not restored, so start it again. Background Bash and monitor tasks are never restored.
  • With feature-flag fetching off, a task you asked to keep across sessions is saved to the project's .claude/scheduled_tasks.json. If .claude or that file is a symlink, scheduling fails with an error. Saved tasks only run in the folder where you created them; copying the file into another folder (a new worktree, say) lists the tasks there but does not run them.

For unattended cron-style automation, use routines, a schedule trigger in GitHub Actions, or desktop scheduled tasks.