Scenario
You want a daily nudge on WhatsApp at 09:00 asking whether the code-review inbox has anything stale. The agent should read your local review-queue file, summarise, and deliver the summary to your phone — no matter whether your laptop is in the middle of another task.
The moving parts:
- A running
rousseau whatsappdaemon. - A cron job persisted in SQLite via
rousseau cron add. - The
robfig/cron/v3scheduler goroutine inside the daemon fires the job; the reply is dispatched through the same WhatsApp transport.
Prerequisites
rousseau whatsapppaired and delivering messages to at least one JID (First transport).- A file the prompt can point at — for this walkthrough, a Markdown queue at
/workspace/review-queue.md.
Step 1 — Register the job
rousseau cron add \
--name daily-review-nag \
--schedule "0 9 * * *" \
--prompt "Read /workspace/review-queue.md and list every PR that has been open for more than 3 days. Reply with 3 bullets max." \
--deliver-to 447900123456@s.whatsapp.net
--schedule is a 5-field POSIX-style cron expression parsed by robfig/cron/v3 (min hour dom mon dow). Rousseau validates the expression at add time; an invalid schedule fails fast before it lands in the store.
--deliver-to is the WhatsApp JID that will receive the reply. For groups, use the @g.us form.
Step 2 — Confirm the job is live
rousseau cron list
Output:
b7a3f2e1 on daily-review-nag 0 9 * * * last=never
Read /workspace/review-queue.md and list every PR that has been open for more than 3 days. Reply with 3 bullets max. → 447900123456@s.whatsapp.net
New jobs become live within the next scheduler poll interval (default 60 seconds). No restart required.
Step 3 — Force a dry run
Scheduled jobs are fired by the running rousseau whatsapp daemon. To verify the wiring without waiting until 09:00, temporarily change the schedule to run one minute from now:
rousseau cron remove daily-review-nag
rousseau cron add \
--name daily-review-nag \
--schedule "*/1 * * * *" \
--prompt "..." \
--deliver-to 447900123456@s.whatsapp.net
Watch the daemon's log:
cron.fire name=daily-review-nag job=b7a3f2e1
tool.execute name=read id=t_1
cron.deliver name=daily-review-nag target=447900123456@s.whatsapp.net bytes=284
Once you see the message on your phone, delete the every-minute copy and re-add the daily version.
Step 4 — Disable without deleting
rousseau cron disable daily-review-nag
Toggling enabled=false leaves the job in the store but skips it on every fire. Re-enable with rousseau cron enable daily-review-nag.
What happens under the hood
rousseau cron addwrites a row to thecrontable in~/.local/share/rousseau/sessions.db.- The
rousseau whatsappdaemon starts arobfig/cron/v3scheduler goroutine at boot and polls the table everyPollInterval(60s default). - When the cron expression fires,
Runner.RunOnce(ctx, prompt)runs a one-shot agent turn against a fresh session (no history from prior fires). - The reply passes through
Delivery— a transport-agnostic callback the daemon wires toclient.Deliver(ctx, target, body). last_run_atis updated in the store. Failures are logged but do not disable the job.
The scheduler is durable: if the daemon dies mid-fire, the next launch picks up the queue. Jobs never fire twice for the same minute because robfig/cron/v3 deduplicates by tick.
Common patterns
| Schedule | Meaning |
|---|---|
0 9 * * * |
09:00 every day. |
*/15 9-17 * * 1-5 |
Every 15 minutes, 09:00–17:59, Mon–Fri. |
0 * * * * |
Top of every hour. |
0 0 * * 0 |
Midnight every Sunday. |
Layering with skills
Long prompts get tedious. If a scheduled job's prompt keeps growing, move the boilerplate into a skill and let the prompt reference it. The skill is spliced into the system prompt at fire time.
Caveats
- Scheduled jobs run against the daemon's configured provider. If your primary provider is
claudecliand you rotate the underlyingclaudelogin, the fire fails until you re-authenticate. - The delivery target must belong to the daemon's allowlist. Rousseau will not deliver to an out-of-allowlist JID even if a scheduled job asks it to.
- The cron scheduler runs inside the
rousseau whatsappdaemon by design. Runningrousseau slackalongside gives you two independent schedulers reading the same table — jobs will fire twice. Pick one daemon to own the schedule.
Next
- Cron reference — every subcommand, every flag.
- Skills — share prompt boilerplate across jobs.
- Audit + approval policies — lock down what the scheduled prompt can do.