Scheduling workflows
Run a workflow on a cron schedule, unattended. Both kinds of workflow ā flat step sequences and DAG workflow skills ā can be scheduled.
mur workflow schedule set nightly-scan "0 3 * * *"
mur workflow schedule list
mur workflow schedule disable nightly-scan # keeps the entry, stops the firing
On macOS the schedule is installed as a launchd agent; on Linux as a crontab
entry. Either way it runs mur run <name>.
Schedules fire in local time
The cron expression is read in your machine's local time zone, not UTC.
0 3 * * * means 3am where you are. mur workflow schedule list shows the
zone that will actually be used:
š Active schedules:
nightly-scan ā `0 3 * * *` (Asia/Taipei)
This is the same behaviour on both backends: launchd's StartCalendarInterval
and crontab both interpret the fields as local wall-clock time, which is why a
schedule set for 2:30am can fire twice or not at all on a daylight-saving
changeover. Avoid scheduling anything important inside that hour.
If an entry was written by an older version it may carry a stored UTC label
that never applied. The list marks those explicitly:
old-job ā `20 23 * * *` (Asia/Taipei)
stored timezone: UTC (not used locally)
Nothing needs fixing there ā the schedule already fires at 23:20 local. Do not shift the expression to "correct" for a zone that was never in play.
Use the exact name
A schedule fires mur run <name>, which resolves an exact flat workflow or an
exact category: Workflow skill. A near-miss name falls through to fuzzy
search, and a fuzzy match is refused when there is no terminal to confirm it ā
so a typo in a schedule is a silent no-op rather than an error. The scheduled
run exits cleanly having done nothing.
mur workflow schedule set checks the name against both lookups when you
create the schedule, so a name it accepts is a name that will run:
$ mur workflow schedule set does-not-exist "0 3 * * *"
Error: Workflow 'does-not-exist' not found ā no ~/.mur/workflows/does-not-exist.yaml,
and no `category: Workflow` skill of that name with a `content.procedure`.
What a scheduled run can reach
launchd and cron start a job with a bare PATH of
/usr/bin:/bin:/usr/sbin:/sbin ā no Homebrew, no mise, no language version
manager. A step calling mysql, gh, or node would work perfectly by hand
and fail at fire time.
MUR freezes the PATH of the shell that created the schedule into the job, so
the scheduled run reaches the same binaries you just proved the steps against.
Two consequences worth knowing:
- Set the schedule from the shell you actually use, not a minimal one.
- If you later change your
PATHin a way the workflow depends on, re-runmur workflow schedule setto refresh it.
Approvals still wait
A scheduled run executes non-interactively, but an approval node in a workflow skill still pauses and waits. Scheduling a workflow with unresolved human-in-the-loop gates defers the wait; it does not grant the approval.
Writing a flat workflow by hand
mur workflow new writes every field of the record, so a generated file looks
like it has a dozen required keys. It does not. Only these are required ā
everything else (schema, tier, importance, tags, timestamps, ā¦) has a
default:
name: nightly-scan # must match the filename stem
description: two shell steps
content: what this workflow is for
steps:
- order: 1 # 1-based; order + description are required
description: first
command: echo one # optional ā omit for a prompt-only step
- order: 2
description: second
command: echo two
Save it as ~/.mur/workflows/<name>.yaml. A missing required field is reported
by name ā missing field `content` ā so read the error rather than guessing.
Note that a flat workflow's steps use order + description. That is not
the same shape as a workflow skill's DAG procedure, which uses id + kind
with an edges list.
Commands
| Command | What it does |
|---|---|
mur workflow schedule set <name> "<cron>" | Create or update a recurring schedule |
mur workflow schedule list | Show active and disabled schedules, with the firing zone |
mur workflow schedule remove <name> | Delete the schedule and its system entry |
mur workflow schedule disable <name> | Stop firing, keep the entry |
mur workflow schedule enable <name> | Resume a disabled schedule |
Cron only ā there is no one-shot "run at" scheduling. For a single future run,
use your platform's own tooling (at, a calendar event, a one-off launchd
job).
If the MUR daemon is running, it claims the schedule and runs it itself; a stale daemon PID is reclaimed for system cron automatically the next time you set a schedule.