Scheduler

Decides when work is enqueued. The scheduler holds schedule definitions, walks them on a tick, and fires when one comes due, pushing either a one-off agent job into dispatch or a whole run into sequence.

It owns no execution of its own. Firing means handing work to another app.

Three ways to say when#

TriggerMeaning
oncefire at a specific date and time, then complete
crona cron expression, with a timezone
intervalevery 30s, 5m, 2h, 1d

A schedule has exactly one of these.

Cron expressions are taken literally, since the scheduler does no natural-language parsing. /toryo-schedule translates your description into an expression and shows you the result before submitting, which is where an ambiguous "every morning" gets resolved into something you can check.

Policies for the awkward cases#

  • Overlap, what to do when the previous run is still going. The default, skip, records the skip and waits for the next slot. allow fires anyway.
  • Misfire, what to do when the scheduler was down across missed firings. The default, fire-once, fires a single catch-up run and resumes the normal cadence rather than replaying every missed slot at once. skip ignores them.

Editing and running by hand#

A schedule can be edited in place: change the timing, the payload, or both, and it keeps its id and its run history. Changing only the payload leaves the next fire time alone.

Run now fires a schedule immediately regardless of its trigger or status, even a paused one, and records the manual fire in history. It does not advance the schedule's normal cadence, so a nightly job you triggered by hand still runs that night.

Every fire is recorded, including the ones that skipped or failed to enqueue, so "did this actually run last night?" is answerable.

The system maintenance lane#

Some schedules are toryo's own, and you do not create them. On first boot the scheduler materializes an owner=system lane and keeps it healthy: a deleted or edited system schedule is restored on the next pass, and it is protected from deletion. These run directly, without spending a Claude session.

What runs there today:

JobCadence
Memory decaydaily, 03:15
Session-debugger reportdaily, 03:30
Orphaned-knowledge sweepdaily, 03:45
Full code-index reindex, per projectweekly, Sunday 04:00
Janitor garbage collectionon an interval

There is no setup step for any of this. A fresh install has it.

Where things go wrong#

  • A schedule never fires. Check that it is active rather than paused or completed, and that the scheduler daemon is green in toryo foreman check.
  • A schedule fires but nothing runs. The fire is recorded separately from the job it enqueued, so look at the history entry, which names the dispatch job or the enqueue error.
  • A recurring job silently skipped. That is the overlap policy: the previous run was still going.

Full command surface: CLI & contract reference.