Install
openclaw skills install task-schedulerSchedule tasks and commands to run at specific times. Execute shell commands, agent tasks, API calls, and automations on a cron schedule. Tested on Telegram & Discord.
openclaw skills install task-schedulerExecute tasks and commands on a schedule using natural language. Run shell commands, agent tasks, API health checks, file operations, and automations — one-shot or recurring.
/schedule run npm test in 5 minutes
/schedule git pull origin main tomorrow at 6am
/schedule generate weekly sales report every monday at 9am
/schedule check https://api.example.com/health every 30m
/schedule clean /tmp files every day at 3am silently
/schedule back up database every sunday at 2am
/schedule restart server in 10 minutes silently
/schedule list
/schedule cancel <jobId>
When the user triggers /schedule, determine the intent:
cron.list and show active scheduled tasks.<jobId> → call cron.remove with that jobId.Extract four things: WHAT (the task to execute), WHEN (the time), RECURRENCE (one-shot or recurring), DELIVERY (announce results or run silently).
Classify the user's request into a task type:
| Task Type | Trigger Words | Agent Action |
|---|---|---|
| Shell command | run, execute, do, command-like syntax (npm, git, docker, curl, python) | Execute the command using Bash tool |
| Agent task | generate, summarize, analyze, write, create, compile, review | Perform the task using available agent tools |
| API/health check | check, ping, hit, call, URL patterns (https://...) | Fetch the URL and report status |
| File operation | clean, back up, copy, move, archive, compress | Perform file operations using available tools |
| Custom prompt | anything else | Execute as a free-form agent prompt |
The WHAT becomes the payload.message — a clear instruction for the agent that wakes up to execute it.
Use the same time-parsing pipeline as the remindme skill:
Layer 1: Pattern Matching
Scan for these patterns (first match wins):
Relative durations — in <number> <unit>:
| Pattern | Duration |
|---|---|
in Ns, in N seconds | N seconds |
in Nm, in N min, in N minutes | N minutes |
in Nh, in N hours | N hours |
in Nd, in N days | N * 24 hours |
in Nw, in N weeks | N * 7 days |
Absolute clock times — at <time>:
| Pattern | Meaning |
|---|---|
at HH:MM, at H:MMam/pm | Today at that time (or tomorrow if past) |
at Ham/pm, at HH | Today at that hour |
Named days:
| Pattern | Meaning |
|---|---|
tomorrow | Next calendar day, default 9am |
tonight | Today at 8pm |
next monday..sunday | Coming occurrence, default 9am |
Recurring — every <pattern>:
| Pattern | Schedule |
|---|---|
every Nm/Nh/Nd | kind: "every", everyMs: N * unit_ms |
every day at <time> | kind: "cron", expr: "M H * * *" |
every <weekday> at <time> | kind: "cron", expr: "M H * * DOW" |
every weekday at <time> | kind: "cron", expr: "M H * * 1-5" |
every weekend at <time> | kind: "cron", expr: "M H * * 0,6" |
every hour | kind: "every", everyMs: 3600000 |
Unit conversion table:
| Unit | Milliseconds |
|---|---|
| 1 second | 1000 |
| 1 minute | 60000 |
| 1 hour | 3600000 |
| 1 day | 86400000 |
| 1 week | 604800000 |
Layer 2: Slang & Shorthand
| Phrase | Resolves to |
|---|---|
in a bit, shortly | 30 minutes |
in a while | 1 hour |
later, later today | 3 hours |
end of day, eod | Today 5pm |
end of week, eow | Friday 5pm |
morning | 9am |
afternoon | 2pm |
evening | 6pm |
midnight | 12am next day |
noon | 12pm |
Layer 3: Ambiguity — Ask, Don't Guess
If you can't determine WHEN, ask the user. Never silently pick a default time.
| User says | Delivery mode |
|---|---|
silently, quietly, in background, no output | "none" — runs without reporting back |
Nothing specified, or report, show results, announce | "announce" — sends task output to channel |
Timezone rule: ALWAYS use the user's local timezone (system timezone). Never default to UTC.
One-shot → ISO 8601 timestamp with the user's local timezone offset.
Recurring (cron) → 5-field cron expression with tz set to the user's IANA timezone.
Recurring (interval) → kind: "every" with everyMs in milliseconds.
Before scheduling, check if the task involves destructive operations:
Destructive patterns (require explicit user confirmation):
rm, del, remove, wipe, clean (unless cleaning temp/cache)drop, truncate, delete from, destroyreset --hard, push --force, branch -Dkill, shutdown, reboot, formatiptables, firewall, ufwIf a destructive pattern is detected:
<command>). Are you sure you want to schedule this?"[CONFIRMED DESTRUCTIVE] in the job name for audit trail.Safe patterns (no confirmation needed):
ls, cat, git status, git log, curl GET, pingnpm test, npm build, make, cargo testgenerate, summarize, analyze, compile reportSame priority order as remindme:
channel: "last".cron.addOne-shot task:
{
"name": "Task: <short description>",
"schedule": {
"kind": "at",
"at": "<ISO 8601 timestamp>"
},
"sessionTarget": "isolated",
"wakeMode": "now",
"payload": {
"kind": "agentTurn",
"message": "SCHEDULED TASK: <detailed task instruction>. Execute this task now and report the results."
},
"delivery": {
"mode": "announce",
"channel": "<detected channel>",
"to": "<detected target>",
"bestEffort": true
},
"deleteAfterRun": true
}
Recurring task (cron):
{
"name": "Recurring Task: <short description>",
"schedule": {
"kind": "cron",
"expr": "<cron expression>",
"tz": "<IANA timezone>"
},
"sessionTarget": "isolated",
"wakeMode": "now",
"payload": {
"kind": "agentTurn",
"message": "RECURRING TASK: <detailed task instruction>. Execute this task now and report the results."
},
"delivery": {
"mode": "announce",
"channel": "<detected channel>",
"to": "<detected target>",
"bestEffort": true
}
}
Recurring task (interval):
{
"name": "Recurring Task: <short description>",
"schedule": {
"kind": "every",
"everyMs": "<interval in milliseconds>"
},
"sessionTarget": "isolated",
"wakeMode": "now",
"payload": {
"kind": "agentTurn",
"message": "RECURRING TASK: <detailed task instruction>. Execute this task now and report the results."
},
"delivery": {
"mode": "<announce or none>",
"channel": "<detected channel>",
"to": "<detected target>",
"bestEffort": true
}
}
Silent task (no delivery):
{
"name": "Task: <short description>",
"schedule": {
"kind": "at",
"at": "<ISO 8601 timestamp>"
},
"sessionTarget": "isolated",
"wakeMode": "now",
"payload": {
"kind": "agentTurn",
"message": "SCHEDULED TASK (SILENT): <detailed task instruction>. Execute this task now. No delivery needed — log results only."
},
"deleteAfterRun": true
}
After cron.add succeeds, reply with:
Task scheduled!
Command: <task description>
Runs: <friendly time description> (<ISO timestamp or cron expression>)
Delivery: <channel or "silent">
Job ID: <jobId> (use "/schedule cancel <jobId>" to remove)
deleteAfterRun: true for one-shot tasks. Omit for recurring.sessionTarget: "isolated" — tasks run in their own sandboxed session.wakeMode: "now" — ensures execution at the scheduled time.delivery.bestEffort: true when delivery mode is "announce".act:wait or loops for delays. Cron handles timing.deleteAfterRun.rm, drop, kill, etc.Task: (one-shot) or Recurring Task: (recurring) for audit trail and scoped cleanup.This skill has zero bundled dependencies because it relies on OpenClaw's built-in capabilities:
cron.add, cron.list, cron.remove are native agent tools.openclaw.json. No API keys needed in this skill.This skill creates cron jobs with payload.kind: "agentTurn" which wake an isolated agent session to execute tasks. The following controls are enforced:
sessionTarget: "isolated" — every scheduled task runs in a sandboxed session. It cannot access the main session's state, history, or tools beyond what's available to a fresh agent session.deleteAfterRun: true — one-shot tasks self-delete after execution, preventing stale job accumulation.Task: or Recurring Task:, making them auditable via cron.list and distinguishable from other skills' jobs.always: true — this skill is not always-on. It only activates when the user invokes /schedule.jobId that the user can inspect (/schedule list) or cancel (/schedule cancel <jobId>) at any time.cron.list to check. Verify gateway was running at the scheduled time.cron.list to see lastStatus and lastError fields.references/TEMPLATES.md for the cleanup job.See references/TEMPLATES.md for copy-paste templates and cleanup setup.