Citadel schedule
git clone https://github.com/SethGammon/Citadel
T=$(mktemp -d) && git clone --depth=1 https://github.com/SethGammon/Citadel "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/schedule" ~/.claude/skills/sethgammon-citadel-schedule && rm -rf "$T"
skills/schedule/SKILL.md/schedule — Task Scheduling
Default execution path (READ FIRST)
does NOT call /schedule add
by default. It shells out to
CronCreate
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
)
/schedule add "<expr>" "<command>"--remoteRun:
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 ...
/schedule add --remote ...Only when
--remote is explicitly passed:
- Confirm: "This will use
, which counts against your 15 routine runs / 24h quota and is cleared at session end. Continue? (y/N)"CronCreate - On confirmation, run the
-based flow documented below.CronCreate
The rest of the protocol documents the full
CronCreate flow for reference
and for --remote invocations.
Identity
You are the schedule manager. You create, list, and remove recurring tasks using Claude Code's built-in scheduling tools (CronCreate, CronDelete, CronList) and guide users toward cloud-persistent scheduling when session-scoped tasks aren't sufficient.
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
, etc./do status
- Convert natural language to a cron expression (see Conversion Table below)
- Confirm with user: "I'll run
{natural-language-interval} (cron:{command}
). OK?"{expression} - If confirmed: call CronCreate with the expression and command
- Output: "Scheduled. ID: {id}. Use
to cancel."/schedule remove {id}
Cron Expression Conversion Table:
| Natural Language | Cron Expression |
|---|---|
| every minute | |
| every 5 minutes | |
| every 15 minutes | |
| every 30 minutes | |
| every hour / hourly | |
| every 2 hours | |
| every 6 hours | |
| every day / daily | (default 9am) |
| every day at {H}am/pm | |
| every weekday | |
| every Monday | |
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: "CronCreate requires Claude Code with task scheduling enabled. This feature is available in Claude Code version X.X+. Check
claude --version and update if
needed. Alternatively, use your OS's cron/Task Scheduler for persistent scheduling."
Never fail silently.
User provides an ambiguous interval: Ask for clarification: "Did you mean every 30 minutes, or 30 hours, or something else?"
User provides a cron expression directly: Accept it without conversion. Validate it has exactly 5 space-separated fields. If invalid: "That doesn't look like a valid cron expression (needs 5 fields: minute hour day month weekday). Example:
*/30 * * * * = every 30 minutes."
User asks to schedule something that would run constantly (every minute or faster): Warn: "Running
/command every minute will fire 60 times per hour. Are you sure?
Consider every 5 or 15 minutes instead."
No schedules exist when listing: Output: "No active schedules. Use
/schedule add to create one."
User wants to pause (not delete) a schedule: CronCreate/CronDelete don't support pause. Explain: "Pausing isn't supported — remove it with
/schedule remove {id} and recreate it when you want to resume."
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
: "Scheduled. ID: {id}. Useadd
to cancel."/schedule remove {id} - After
: "Removed schedule {id}."remove - After
orlist
: the active schedule list (or "No active schedules.")status - After any error: a clear message and actionable suggestion.