There’s a failure mode that’s easy to miss. You schedule an agent task in system crontab, it fires at 7am, no errors in the log, but the work was never done. No research file. No draft. Nothing. The job ran—the shell just couldn’t find claude, so it exited cleanly with nothing to show.
That’s what happens when you use the wrong cron system.
The Problem
When you install claude or openclaw via npm with nvm, the binary lives somewhere like:
/home/user/.nvm/versions/node/v22.22.0/bin/claude
System crontab runs with a stripped-down PATH. It doesn’t source your shell profile. It doesn’t know about nvm. So claude --skill my-skill fails with command not found—and because you didn’t add log redirection, you never see the error.
You can patch this with the full binary path and >> /path/to/log 2>&1, and it’ll work. But you’re still fighting the environment instead of using a system designed for the job.
The Right Split
Not all cron jobs are the same. Some call a model. Some just run a script. That distinction is the line.
| Job type | Right tool |
|---|---|
| Agent tasks (research, drafts, briefings, nudges) | OpenClaw cron |
| Scripts (git backup, Python monitor, health checks) | System crontab |
The rule: if it calls a model, put it in OpenClaw. Everything else can stay in crontab.
Why does this matter? OpenClaw cron gives you things system crontab can’t:
- Observability —
openclaw cron listshows last run, status, consecutive errors, next run - Isolated sessions — each job starts clean, no context bleed from previous runs
- Discord delivery — results route to the right channel automatically
- Model fallbacks — primary fails, it tries the next in your chain
- Restart catch-up — if the gateway crashes and restarts, missed slots replay
System crontab gives you none of that. You get a line in a file and a log you have to remember to check.
Migrating a Job
Remove the system crontab entry. Replace it with an OpenClaw cron job:
openclaw cron add \
--name "daily-research" \
--description "Daily incremental research pass" \
--cron "0 7 * * *" \
--tz "America/Los_Angeles" \
--session isolated \
--message "Run the research skill." \
--no-deliver \
--timeout-seconds 900
A few flags worth understanding:
--no-deliver — Use this when the skill handles its own Discord posting (via the Discord API directly). Without it, OpenClaw will also try to deliver the agent’s response to a channel, and you’ll get double posts. If the skill is silent when there’s nothing to report, --no-deliver keeps that behavior intact.
--exact — OpenClaw applies a small random stagger to top-of-hour jobs by default to spread load. If job B depends on job A finishing first (say, a Wednesday draft that consumes Monday–Wednesday research), add --exact to the earlier job so timing is predictable.
--timeout-seconds — The default timeout is 30 seconds. Agent tasks that fetch from multiple sources or generate long-form content need much more. Set it to something real: 600–1200 seconds for research and draft jobs.
--session isolated — Always. Isolated sessions start fresh each run, which is what you want for scheduled jobs. Without it you risk context bleed from whatever the agent was doing in its main session.
Verify It Landed
openclaw cron list
You should see your job with the next scheduled run, last status, and target session. If it’s been running, you’ll also see lastDurationMs and consecutiveErrors—the two numbers that tell you whether it’s actually working.
Key Takeaway
System crontab was built for scripts. OpenClaw cron was built for agents. The failure mode for using the wrong one is a silent success—the job reports ok, but nothing happened. Pick the right tool, and you get observability, delivery, and fallbacks for free.
Resources
- OpenClaw Cron Jobs: Common Problems & Solutions — Community-sourced breakdown of the most common cron failure modes, with diagnostic commands and recommended fixes for each.