schedule
/schedule — Task Scheduling
Orientation
Use when: scheduling a recurring or one-off remote agent run (cron-style, outside the current session). Don't use when: repeating work within the current session (use /loop); continuous unattended campaigns (use /daemon).
Default execution path (READ FIRST)
/schedule add does NOT call CronCreate by default. It shells out to
node scripts/local-schedule.js which installs a native OS entry (Windows
Task Scheduler or Unix cron). Only pass --remote to use Anthropic's routine
system, and only after explicit user confirmation.
Why: CronCreate counts against the account-wide 15 routine runs / 24h
cap; every fire of the scheduled task counts. See
docs/ROUTINE-QUOTA.md.
Default flow — /schedule add "<expr>" "<command>" (no --remote)
Run:
node scripts/local-schedule.js add "<expr>" "<command>"
Then report the returned ID and the removal command. This survives session
end, machine reboot, and consumes zero routine quota. Use
/schedule list and /schedule remove {id} (which also shell out to
local-schedule.js) by default.
Opt-in routine flow — /schedule add --remote ...
Only when --remote is explicitly passed:
- Confirm: "This will use
CronCreate, which counts against your 15 routine runs / 24h quota and is cleared at session end. Continue? (y/N)" - On confirmation, run the
CronCreate-based flow documented below.
The rest of the protocol documents the full CronCreate flow for reference
and for --remote invocations.
When to Route Here
- "run pr-watch every hour"
- "check my PRs automatically"
- "schedule a thing"
- "remind me to run tests every 30 minutes"
- "set up a recurring task"
- "list my scheduled tasks"
- "cancel the PR check"
- Any mention of "schedule", "recurring", "every N minutes/hours", "cron"
Protocol
/schedule list
List all currently scheduled tasks using CronList.
Output format:
Active schedules (N):
[id] {description} — {cron expression} — next run: {time}
No schedules active.
If CronList is not available: output a helpful error (see Fringe Cases).
/schedule add "{description}" {/skill-or-command}
Create a recurring task.
Steps:
- Parse the user's description to extract:
- Natural language interval: "every 30 minutes", "hourly", "every day at 9am"
- The skill or command to run:
/pr-watch,/do status, etc.
- Convert natural language to a cron expression (see Conversion Table below)
- Confirm with user: "I'll run
{command}{natural-language-interval} (cron:{expression}). OK?" - If confirmed: call CronCreate with the expression and command
- Output: "Scheduled. ID: {id}. Use
/schedule remove {id}to cancel."
Cron Expression Conversion Table:
| Natural Language | Cron Expression |
|---|---|
| every minute | * * * * * |
| every 5 minutes | */5 * * * * |
| every 15 minutes | */15 * * * * |
| every 30 minutes | */30 * * * * |
| every hour / hourly | 0 * * * * |
| every 2 hours | 0 */2 * * * |
| every 6 hours | 0 */6 * * * |
| every day / daily | 0 9 * * * (default 9am) |
| every day at {H}am/pm | 0 {H} * * * |
| every weekday | 0 9 * * 1-5 |
| every Monday | 0 9 * * 1 |
If the user provides a raw cron expression directly, use it as-is without converting. Validate it has 5 fields before accepting.
/schedule remove {id}
Remove a scheduled task by ID using CronDelete.
If the user doesn't know the ID: run /schedule list first, show the list,
and ask which one to remove.
Output: "Removed schedule {id} ({description})."
/schedule status
Show all active schedules and their next run times. Equivalent to /schedule list
with additional context about what each task does and when it last ran (if available).
Session-Scoped vs. Cloud-Persistent Scheduling
Session-Scoped (CronCreate)
CronCreate schedules tasks that run during the current Claude Code session only. When the session ends (Claude Code closes or the conversation is reset), all session-scoped schedules are cleared.
Use session-scoped when:
- Running checks during an active work session ("remind me every 30min to commit")
- Polling for PR feedback while you're at the computer
- Triggering skill runs during a long coding session
Cloud-Persistent (RemoteTrigger)
For tasks that need to survive machine sleep, network drops, or session restarts, use RemoteTrigger — a one-off cloud trigger that fires from Anthropic's infrastructure rather than your local session.
Use cloud-persistent when:
- The task needs to run overnight or while you're away
- You want notifications when you return to your machine
- The interval spans multiple days or calendar dates
How to set up a one-off cloud trigger:
- Call RemoteTrigger with the desired delay and the command to run
- Claude Code registers the trigger in Anthropic's cloud scheduler
- When the trigger fires, it wakes a new Claude Code session and runs the command
- Results are delivered as a notification
Note: RemoteTrigger requires Claude Code with cloud features enabled (Pro or Team plan). CronCreate works on all plans but is session-scoped only.
Fringe Cases
CronCreate not available: Output error; suggest OS cron/Task Scheduler. Never fail silently.
Ambiguous interval: Ask for clarification before proceeding.
Raw cron expression: Accept without conversion; validate 5 fields.
Every-minute schedule: Warn about 60 fires/hour; suggest 5m or 15m instead.
No schedules when listing: "No active schedules. Use /schedule add to create one."
Pause requested: Explain pause isn't supported; remove and recreate instead.
Contextual Gates
Disclosure: "Creating schedule: {command} at {cron expression}. OK?"
Reversibility: amber — creates OS cron entries or CronCreate sessions (side effects outside the repo); undo with /schedule remove {id}
Trust gates:
- Any: confirms before creating; shows cron expression before accepting
Quality Gates
- Always confirm before creating (CronCreate is a side effect)
- Always show the cron expression alongside the natural-language description
- Always provide the ID after creation so the user can remove it
- Never leave a user unable to remove a schedule they created
Exit Protocol
/schedule does not produce a HANDOFF block. After each action, output a concise confirmation or list and wait for the next command.
- After
add: "Scheduled. ID: {id}. Use/schedule remove {id}to cancel." - After
remove: "Removed schedule {id}." - After
listorstatus: the active schedule list (or "No active schedules.") - After any error: a clear message and actionable suggestion.