Three places to schedule Claude work: Routines run in the cloud while your laptop is closed; Desktop scheduled tasks run on your machine without an open session; /loop runs only while a session is open. Pick by what the work needs to touch (cloud-only repo, local files, the live session) and whether the laptop is reliably on.
Side-by-side
| Routines (cloud) | Desktop scheduled tasks | /loop | |
|---|---|---|---|
| Runs on | Anthropic cloud | Your machine | Your machine |
| Requires machine on | No | Yes | Yes |
| Requires open session | No | No | Yes |
| Persistent across restarts | Yes | Yes | Restored on --resume if unexpired |
| Local file access | No (fresh clone of repo from GitHub) | Yes | Yes |
| MCP servers | Connectors configured per routine | Config files and connectors on the machine | Inherits from current session |
| Permission prompts | None (runs autonomously) | Configurable per task (mode + model) | Inherits from session |
| Trigger shapes | Scheduled, API endpoint, GitHub events | Scheduled (recurring or one-off) | Manual at session start |
| Minimum interval | 1 hour | 1 minute | 1 minute |
| Plan requirement | Pro/Max/Team/Enterprise + Claude Code on the web | Any plan with Desktop app | Any plan |
Decision tree
Does the work need to keep running while your laptop is off? Yes → Routines. The other two stop the moment the machine sleeps.
Does the work need files that live only on your laptop?
Yes → Desktop scheduled task or /loop. Routines clone from GitHub on each run; uncommitted local files, sibling repos, your .env are invisible to them.
Will you be in the session when the work fires?
Yes → /loop. The active session is exactly what /loop extends.
No → Desktop task. Schedule it; the Desktop app starts a fresh session when the time fires, independent of any session you have open.
Is the trigger an external event (PR opened, alert fired, deploy completed)? Routines. The API and GitHub triggers were built for this; the other two only fire on a clock.
Sub-minute polling?
None of these. The minimum interval is 1 minute (Desktop, /loop) or 1 hour (Routines). For sub-second event-driven work, look at channels or a real worker outside Claude Code.
Routines specifics
Each routine bundles a prompt, one or more repos, and a set of connectors. Multiple trigger types can attach to the same routine: a PR-review routine might run nightly and on every new PR and on demand from a deploy script.
The execution model is a fresh cloud session every time, with no state from prior runs and no access to your laptop. That is the whole point: the trade-off for “runs while your laptop is closed” is “cannot see your laptop”. If you want a routine to operate on persistent state, it has to use connectors (database MCP, ticketing system, etc.) that store state outside Claude Code.
Routines are autonomous by design: there is nobody at a keyboard when they fire, so permission prompts do not gate execution. Anything the prompt asks for, the routine does (within the connector set you gave it). Audit the prompt and the connector list as carefully as you would audit any unattended automation.
Desktop scheduled task specifics
The Desktop app checks the schedule every minute while the app is open. When a task is due, Desktop starts a fresh session with the configured prompt, working folder, permission mode, and model. The session is independent of any manual session you have open.
Two helpful toggles per task:
- Worktree. Each run gets an isolated Git worktree, like a parallel session. Use it when scheduled and manual work could conflict on the same files.
- Permission mode. Pick
default,acceptEdits,plan, etc. per task; an unattended audit task should usually bedontAskorplan, not the developer’s normaldefault.
Missed runs: when the app starts or the computer wakes, Desktop checks the last 7 days for missed schedules and starts exactly one catch-up run for the most recently missed time. So if your laptop slept through three nightly runs, you get one catch-up (the most recent), not three. Anything older than 7 days is dropped. For “every weekday morning, run X” workflows that miss occasionally, the catch-up usually does the right thing. For “must run by 9am or the day is wrong”, schedule it earlier or back it up with a Routine.
/loop specifics
Already covered in Monitor tool + self-pacing /loop. Short version: best for “I am at this terminal for the next hour and want this to run periodically while I work”. Wrong for anything that should survive your laptop closing or your terminal dying.
Footguns
Routines see only what is in the GitHub repo. Uncommitted changes, local-only files, sibling repos, anything in ~/scratch/: invisible. A routine that worked on a prototype branch fails after merge if the branch was deleted. Push everything you depend on; treat routines as read-only consumers of GitHub state.
Desktop tasks run with whatever was in the working folder, including uncommitted changes. Convenient when you want a scheduled task to grade your in-progress work; dangerous when an unfinished refactor leaves the tree in a broken state and the scheduled npm publish task fires at 3am. Use the worktree toggle for any task that should run against a clean state.
/loop dies silently when the session does. Closing the terminal, exiting Claude with Ctrl-D, or losing the SSH connection ends the loop. --resume restores prompt-based loops within the 7-day window, but background Bash/Monitor tasks are not restored. Anything that has to survive a restart belongs in Desktop or Routines, not /loop.
Minimum-interval and rounding rules differ. Routines reject any cron expression more frequent than hourly. /loop accepts arbitrary intervals and rounds non-cron-clean values like 7m or 90m to the nearest cron-clean step. Desktop’s UI offers presets and accepts custom intervals when you describe them in plain language. A “run every 30 minutes” instruction works on Desktop and /loop but not on Routines, which will fail validation.
Pricing and plan gating differ. Routines need Pro/Max/Team/Enterprise with Claude Code on the web enabled. Desktop tasks work on any plan that has the Desktop app. /loop works on any plan. A team mixing plan tiers may find some members cannot run Routines at all.
Connector configuration is per-routine, not shared. A Postgres MCP your laptop has configured does not transfer to a Routine; you have to configure the connector inside the routine itself. The same is broadly true for Desktop tasks: connectors and config travel with the task. Plan to maintain config in two places when a workflow has both local and cloud halves.
When NOT to schedule
- The work is reactive, not periodic. A PR review fires per-PR, not every Tuesday at 5pm. Use a Routine with a GitHub trigger or an API trigger, not a scheduled task.
- The work needs sub-minute resolution. None of these schedule fast enough. Use channels (event-driven) or a real queue + worker.
- You need exactly-once semantics. Scheduled tasks fire on a wall clock; if the result must run exactly once across multiple invocations (overlapping schedules, retries, manual fires), idempotency is your responsibility. Build it into the prompt or into the connector.
- The work should run forever.
/loopends automatically after 7 days. Routines and Desktop tasks persist as long as you keep them, but they are still tied to a Claude Code account; for genuinely permanent automation that should outlive any one tool’s lifecycle, run a real worker outside Claude Code that calls Claude on demand. - Two of the three would also work. Pick the cheapest option that satisfies the constraints.
/loopfor in-session experiments; Desktop for “every morning” local workflows; Routines for everything that needs to fire whether or not you are logged in.