← Alle Recipes
Phase 5 · Daily Use·12 min·7 steps

/schedule and recurring agents

Claude Code has /schedule for cron-like recurring agents. When to use it vs a real crontab. Common gotchas including the jitter rule.

7 steps0%
Du liest ohne Account. Mit Login speichern wir Step-Fortschritt + Notes.

/schedule and recurring agents

Most automation can stop being manual. The morning brief from Recipe 5.1, a weekly cleanup, a Friday-afternoon retrospective, a "ping me if X" watcher — those are recurring tasks. You do not need to type the prompt every time. Schedule them.

Claude Code has the /schedule slash command for this. It registers a recurring agent that fires on a cron-style schedule and runs a saved prompt. Behind the scenes it is a job runner with a few smart defaults. This recipe walks through when to use /schedule versus a real crontab, plus the gotchas that bit us.

Step 1: /schedule vs /loop vs cron — which to use

Three tools, three failure modes if you pick wrong:

| | /schedule | /loop | crontab | |---|---|---|---| | Persistence | Yes (web/desktop, survives restart) | No (session-scoped, dies on exit) | Yes | | Runs an LLM prompt | Yes | Yes | Possible but you wire it yourself | | Runs a shell command | Indirectly (prompt calls Bash) | Same | Yes, native | | Cadence input | cron expression or natural-language preset | cron expression or 5m shorthand | cron only | | Visible in /agents UI | Yes | While session is active | No | | Off-machine | No | No | No (use systemd timers / remote scheduler) |

Pick /schedule for anything that should keep running across days even when you are not in a session — morning brief, weekly memory consolidation, daily PR digest. Pick /loop for short-lived "keep checking until X is done" patterns inside one session — /loop 5m check the deploy while you wait on a build, then exit. Pick crontab for shell scripts where the LLM is not in the loop (database backups, log rotation, certificate renewals).

CLAUDE_CODE_DISABLE_CRON=1 disables the scheduler mid-session if you need to silence everything for a few hours.

Step 2: Pick a recurring task that earns its keep

A schedule earns its keep when:

  • You actually need the work done (you skip it manually about half the time → automate it)
  • The output is short and read-once (a brief, an alert, a status email — not a 50-line report you would skim and forget)
  • It runs often enough that drift matters (daily, weekly — not monthly, monthly is too rare to get a routine going)

Three good first picks:

  • Morning brief at 08:30 weekday mornings (Recipe 5.1)
  • Weekly memory cleanup Sunday 18:00 — runs nex_consolidate + nex_deduplicate + nex_decay stats
  • Friday retrospective Friday 17:00 — runs nex_synthesize over the week, writes one summary

Pick one. Build confidence with one before adding three more.

Step 3: Register it with /schedule

In Claude Code:

/schedule

Claude prompts for a name, a schedule (cron-style or natural language), and the prompt body to run. For the morning brief:

  • Name: morning-brief
  • Schedule: 30 8 * * 1-5 (Mon-Fri, 08:30)
  • Prompt: Run the morning-brief skill and post the output to Telegram (or wherever).

Claude saves the routine to ~/.claude/routines.json. You can edit that file directly later if you want — it is a JSON list of { name, schedule, prompt } objects.

For the weekly cleanup:

  • Name: weekly-memory-cleanup
  • Schedule: 0 18 * * 0 (Sunday 18:00)
  • Prompt: Run nex_consolidate to merge today's session summaries. Then nex_deduplicate scan to flag duplicate entries. Then nex_decay stats to surface entries that have not been read in 45+ days. Output a one-line summary plus the deduplication report.

Step 4: Verify

Run aiguide_validate_step. The cron_routine_active validator checks two things in order:

  1. Does ~/.claude/routines.json exist with at least one entry? If yes, pass.
  2. Otherwise, does crontab -l return at least one non-comment line? If yes, pass.

If both fail, the validator hint tells you what to do. Either path counts.

Client check · run on your machine
(test -f ~/.claude/routines.json && echo "claude routines OK") || (crontab -l 2>/dev/null | grep -v "^#" | grep -v "^$" | head -5)
Expect: Either ~/.claude/routines.json exists OR crontab has at least one active line.
If stuck: Use Claude Code `/schedule` to register a recurring agent, or add a `crontab -e` line.

Step 5: The jitter rule (this one bit us)

Real recurring jobs should not fire on round-minute boundaries. If everyone schedules their daily job at 0 9 * * *, half the world's cron jobs hit external APIs at exactly 09:00:00 and you get rate-limit storms.

Claude Code has a built-in jitter for routines: it shifts the actual fire time by up to 10% of the schedule period (max 15 minutes). A 0 9 * * * job actually fires somewhere between 08:54 and 09:09. For one-shot jobs scheduled at round times, it nudges them up to 90 seconds earlier.

Cron does not auto-jitter. Best practice for raw crontab: always pick odd minutes deliberately. Instead of 0 9 * * *, write 13 9 * * * or 27 8 * * *. Anti-stampede default.

Tell Claude this rule explicitly when scheduling new routines:

Schedule a daily memory cleanup at around 06:00 — pick an off-minute like 53 or 17, not 00 or 30.

The model sets the cron string accordingly.

Step 6: One file lock (so two clients do not double-fire)

If you run Claude Code on two machines (laptop + desktop) both reading the same routines.json (synced via iCloud, Syncthing, etc), they will both try to fire the same job at the same time. Fix: file lock on the routines file. Claude Code picks up the lock before firing and skips the run if another process holds it.

This is on by default in newer Claude Code versions (cronTasksLock). If you see double-fires, check that both clients are on a recent version.

Step 7: When the schedule does NOT fire (debug checklist)

Three common causes:

  • Claude Code is not running. /schedule runs only when Claude Code is alive somewhere. If your laptop sleeps overnight, the morning routine fires when you wake up — not at 08:30. For "fire even when offline" you need crontab on a server, not /schedule.
  • The routine is registered globally but you launched Claude Code from a project. Project-scoped Claude has different routines.json. Use the global one for cross-project routines.
  • The prompt failed silently. Check the agent log: ~/.claude/agents/<name>/log. The most common failure is "tool was renamed and the prompt still uses the old name".

What you do NOT schedule

  • Anything that needs human judgment in the loop (PR reviews, customer responses, hiring decisions)
  • One-off cleanup that is technically recurring but realistically you only do twice a year (annual audit, certificate renewal — leave those manual)
  • Anything where a missed run is silent and bad. Schedules can fail silently. For "must-run" tasks that have monetary or safety consequences, build alerting on top — and do not rely on /schedule alone.

The right things to schedule are small, low-risk, high-frequency tasks where seeing the output is the point. Start with one, add the second after two weeks.

Morning brief — start the day Debrief — clean session ends s