scheduler command group makes it a
file — one manifest that lists every schedule the revision should carry, with its target written in names rather
than in UUIDs.
The manifest is the unit of work, exactly as it is for the workflow group. It names a blob and a revision, lists
every schedule that belongs on that revision, and every command in this group starts by loading it.
The shape of a deployable project
One file. A scheduler blob holds no code and no documents, so there is nothing for the manifest to point at:schedules.yaml, for a revision holding one schedule that runs the checkout_flow workflow every morning:
A schedule targets a workflow in another blob
The schedule lives in the scheduler blob. What it runs does not —target: names a workflow blob, its revision,
a session on that revision, and a workflow definition by alias. So a single scheduler deploy legitimately spans
both of the platform’s engines: it writes schedules with scheduler_blobhub against its own blob, while
validating every target with workflow_blobhub calls against the target revision.
A key that can write the scheduler blob is not sufficient. Firing a schedule writes an execution into the
target revision, so the platform requires WRITE on the target blob as well — the same role it gates the
scheduler blob itself on. Read access on the target is not enough, and a key that has only that will still be
refused.
The target revision itself is only ever read by the CLI, though. Deploying a schedule creates a session on that
revision but never touches the revision’s own content, so scheduling against a target in commit phase is fine —
which is the normal case, since what you schedule is usually a committed workflow.
Two more consequences are worth knowing before the first deploy:
- The platform reports every target failure as the same opaque
403. A missing target revision, a target you cannot reach, an unresolvable session, a session belonging to a different revision, and a workflow alias that resolves to nothing are deliberately indistinguishable, so that a caller cannot tell “does not exist” from “exists but you may not see it”. That is a permanent security property. It is also whydeployprobes the target itself, one step at a time, before writing anything: the CLI can name which of the five was wrong, and the platform structurally cannot. workflow:is re-resolved every time the schedule fires. The alias is stored as a string and sent verbatim, so the definition behind it can be replaced freely — but renaming or deleting it leaves the schedule pointing at a name that resolves to nothing, invisibly, until the next fire.deployanddiffcheck that the alias is a liveworkflow-category definition on the target revision for exactly this reason.
pull and deploy are not a symmetric pair
In the workflow group, pull and push are a symmetric pair: a document that goes out through one and comes
back through the other comes back byte-symmetric. Nothing here works like that.
That last side effect is the asymmetry.
pull cannot undo it: nothing in a manifest deletes a session, and the
CLI will not delete runtime state it cannot prove it created. So a round trip through these two is not the
identity, and treating it as one is how you end up with sessions you did not intend.
The group has no push, and that is deliberate rather than unfinished. push means one specific thing in
this CLI — a code-unaware, byte-symmetric transport that interprets nothing. The scheduler’s local-to-remote
operation resolves references, creates sessions, and validates four things about every target. Calling that
push would make one verb mean “move bytes” in one group and “resolve, create, validate” in another. It is
deploy, which already means the composite that makes the manifest real and checks its own work.
The four commands
deploy is the one to reach for day to day, and diff is what to run before it. ls and diff are the two
that write nothing at all, locally or remotely.
Drift is not inert here
Schedules on the revision that the manifest does not cover are drift. As everywhere else in this CLI, drift is reported, left untouched, and still exits0 — but the consequence is different in this group, and the messages
say so.
An orphaned definition sits there doing nothing until something deploys or executes it. An orphaned schedule
keeps firing on its cron: it consumes execution quota, appends to its session on every fire, and can saturate
that session on its own. The message says so, names blobhub scheduler prune as the removal path, and states
that it is not yet available — so removing one today means the web UI, or a delete_schedule call.
One kind of drift can never be resolved from a manifest at all. A schedule’s alias is optional platform-side
— the web UI’s create form offers a blank field — and nothing declarative can address a schedule that has none.
ls shows it anyway, by id, because a schedule you cannot see is worse than one you cannot manage; pull skips
it and reports it separately, since writing an aliasless entry would produce a manifest this CLI’s own loader
rejects.
What every command shares
The manifest is always explicit.-f/--file is required on all four commands; there is no default path and no
search of the working directory.
Every command operates on the whole schedule set. There is no per-schedule narrowing flag — no counterpart to
the workflow group’s --definition. A manifest describes one revision’s schedules, and these commands act on
that set.
--dry-run belongs to deploy alone, and it is not free of side effects. It skips the
create_schedule/update_schedule calls, and nothing else: every target is still resolved, which means a
session: alias that does not exist yet is still created. diff is the command that does not — it reports an
absent session as one deploy would create. That is the one place the two genuinely differ in cost.
Global flags come before the group, since they belong to the binary rather than the command:
deploy needs a writable revision. It requires status ready and phase draft or managed; ls,
pull and diff also accept commit. A scheduler blob is created in phase managed with a single revision, so
in practice revision: latest names the one revision there is and the gate is rarely what stops you.
See also
- Scheduler manifest — the
scheduler_blob_deploymentbody in full, and the four constraints checked before anything is written. - Concepts — manifests, drift, and the platform behaviours behind several messages in this group.
- Configuration — credentials, the precedence ladder, output streams and the
--jsonenvelope. - Error codes — every code these commands can raise, with its remediation.
- Scheduler blob type — cron syntax, timezones, date windowing, schedule states and what the platform records for every fire.
- Workflow overview — the group this one is modelled on, where
pullandpushreally are a symmetric pair.

