Skip to content

/crons

Manage scheduled reminders (crons) — list, add, delete, pause, resume, reconcile, or import from OpenClaw. Triggers on /agent:crons, /agent:reminders; listing ("list reminders", "show crons", "recordatorios", "mis crons", "mis recordatorios"); creating from natural language via

shell
$ npx -y skills add crisandrews/ClawCode --skill crons --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/crons
How auto-invocation works

Context preview

The summary Claude sees to decide when to auto-load this skill.

Manage scheduled reminders (crons) — list, add, delete, pause, resume, reconcile, or import from OpenClaw. Triggers on /agent:crons, /agent:reminders; listing ("list reminders", "show crons", "recordatorios", "mis crons", "mis recordatorios"); creating from natural language via

SKILL.md

crons.SKILL.md
name: crons
description: Manage scheduled reminders (crons) — list, add, delete, pause, resume, reconcile, or import from OpenClaw. Triggers on /agent:crons, /agent:reminders; listing ("list reminders", "show crons", "recordatorios", "mis crons", "mis recordatorios"); creating from natural language via any channel ("recordame", "recuérdame", "me recuerdas", "hazme acordar", "agendame", "agéndame", "avísame", "remind me", "remind me in", "reminder in", "schedule a reminder", "set a reminder", "wake me at", "every day at", "todos los días a las", "every monday|tuesday|...", "todos los lunes|martes|...", "cada N minutos|horas"); importing ("import crons", "importar crons", "traer crons").
user-invocable: true

Crons & Reminders

This workspace maintains a persistent cron registry at `memory/crons.json` — the source of truth for every scheduled task across sessions. The SessionStart hook reconciles it against the live harness; the PostToolUse hook captures ad-hoc `CronCreate`/`CronDelete` calls automatically.

All writes to the registry go through one script: `bash ${CLAUDE_PLUGIN_ROOT}/skills/crons/writeback.sh <subcommand>`. Never edit `memory/crons.json` by hand.

**`CronCreate` / `CronList` / `CronDelete` are deferred tools** — call `ToolSearch(query="select:CronList,CronCreate,CronDelete")` once per session before invoking them. The parameter name is `cron`, not `schedule`. Always pass `durable: true` (forward-compat for when the upstream flag is fixed).

---

⛔ FORBIDDEN — read before touching anything

These rules are non-negotiable. Violating any of them silently breaks reminders for the user.

1. **Never compute cron expressions yourself.** LLMs miscompute timezones inconsistently (sometimes UTC, sometimes local — verified empirically). Claude Code's cron daemon uses the **host's LOCAL time**. The only correct way to produce a cron expression is to call `bash $CLAUDE_PLUGIN_ROOT/bin/cron-from.sh ...`. The helper does deterministic epoch arithmetic and returns cron + human-readable confirmation in the host's TZ. *(Enforced: a PreToolUse hook blocks `CronCreate` with exit 2 unless the cron expression matches a cron-from.sh output from the last 120s. If the mode you need isn't covered by `relative`/`absolute`/`recurring`, use `cron-from.sh passthrough "<cron>"` as an escape hatch.)*

2. **Never use `ScheduleWakeup` for user-facing commitments.** `ScheduleWakeup` is intra-session only (dies on `/exit`). Any reminder, alert, or recurring task the user requests via chat MUST go through `CronCreate(durable: true)`. The reconcile hook keeps it alive across restarts.

3. **Never tell the user the reminder is "session-only", "may not arrive", or any equivalent degraded-persistence phrasing in any language.** With this skill, every commitment is durable. If you genuinely cannot create the cron (e.g. helper failed), surface the error to the user — don't silently degrade to a verbal-only promise.

4. **Never call `writeback.sh upsert` after a `CronCreate` for an ad-hoc reminder.** The PostToolUse hook captures it automatically with `source: ad-hoc`. Manual upsert would duplicate. *(Enforced: `writeback.sh upsert` refuses with exit 5 if an active entry with the same cron + prompt already exists under a different key. If you see that error, the hook already did its job — drop your manual upsert call.)*

Common failure pattern (verified 2026-04-19)

When the agent thinks "I know what time +2 minutes is, I'll just compute the cron myself" and skips the helper, this is the bug that ships:

Now (local):     15:21  (UTC-4, Santiago)
User asks:       "recordame en 2 minutos"
Agent computes:  15:21 + 2 = 15:23 → grabs UTC hour by mistake
                 → cron = "23 19 19 4 *"  ← hour 19 (UTC), not 15 (local)
Daemon fires at: 19:23 LOCAL (cron uses local time of host)
                 = 7:23 PM = 4 hours late

The helper exists exactly to prevent this. There is no situation in which computing a cron expression in your head is acceptable — even for "obvious" cases like "in 2 minutes". Always run `bash $CLAUDE_PLUGIN_ROOT/bin/cron-from.sh ...` first.

---

Subcommand dispatcher

Parse the user's phrasing and route to the right flow:

| Phrasing | Subcommand | |---|---| | `/agent:crons list`, `/agent:reminders`, "list reminders", "show crons", "recordatorios", "mis crons", or no args (registry populated) | **LIST** | | `/agent:crons add <cron> <prompt>`, "add reminder", "agrega un recordatorio", **plus all natural-language requests for a future-time commitment**: "recordame en X", "me recuerdas en X", "hazme acordar X", "avísame a las X", "agendame X", "remind me in X", "remind me at X", "every Monday at X", "todos los lunes a X", "cada N minutos/horas", etc. | **ADD** | | `/agent:crons delete <key|N>`, "delete reminder X", "borra el recordatorio X" | **DELETE** | | `/agent:crons pause <key>`, "pausa reminder X" | **PAUSE** | | `/agent:crons resume <key>`, "reanuda X" | **RESUME** | | `/agent:crons reconcile`, "reconcile" | **RECONCILE** | | `/agent:crons import`, "importar crons", "traer crons", or no args (OpenClaw source present + registry empty) | **IMPORT** |

---

LIST — show current reminders

1. Retire fired one-shots first so they don't render as falsely missing:

   bash "$CLAUDE_PLUGIN_ROOT/skills/crons/writeback.sh" prune-expired

2. Call `CronList`. Output is plain text, one line per live job:

   <8hex-id> — <cron-expr> (recurring|one-shot) [session-only|durable]: <prompt>

Empty state is the literal string `No scheduled jobs.`.

3. Pipe the FULL CronList output (verbatim, including a literal `No scheduled jobs.`) to the mechanical auditor — it refreshes `lastSeenAlive`, relinks entries that survived under a new task id, and persists `.audit` for doctor/status to read offline:

   printf '%s\n' "<full CronList output>" | bash "$CLAUDE_PLUGIN_ROOT/skills/crons/writeback.sh" audit

Exit 4 = format drift or blank i

Read more
Read it on GitHub ↗

Showing the first part of this file.

Ships withcrisandrews-agent

Persistent agents for Claude Code as a plugin, not a harness. Memory, personality, messaging across WhatsApp, Telegram, and Discord, plus a service mode for 24/7 runs. Imports from OpenClaw.

Get the whole plugin, auto-invoked
Stats
61
Stars
0
Views
14
Forks
Active
Maintenance
TypeScript
Language
MIT
License
2d ago
Last commit
3mo ago
Created

Repo: crisandrews/ClawCode