ls answers one question: what is actually firing on this revision, and how much of it does my manifest know
about? It lists every schedule the revision holds and marks the ones the manifest covers.
It is the read-only view of drift. Every other command in this group reports drift as a summary line; ls shows
it row by row, with the id you would need to go find the schedule in the web UI.
Synopsis
That is the whole surface. There is no per-schedule filter — narrowing a listing to the subset you already
declared would defeat the point of listing it — and no
--dry-run, because nothing is written locally or
remotely.
What it does
- Loads the manifest and resolves the scheduler blob and revision. This is a read, so a
commit-phase revision lists fine. - Pages
list_schedulesto completion, following the platform’s cursor until it stops returning one. Unlike the definition listing behindblobhub workflow ls, this one really does page, so there is no truncation advisory here and no silently dropped rows. - Matches each schedule’s alias against the manifest’s entries.
- Prints one row per remote schedule, sorted by alias, with aliasless schedules last:
* marks a schedule the manifest covers. An unmarked row is drift: it exists on the revision, no manifest entry
claims it, and — unlike a drifted workflow definition, which sits inert — it is still firing on its cron.
Nothing in this group removes one. blobhub scheduler prune is the removal path the drift messages elsewhere in
this group name, and it is not yet available — so removing a schedule today means the web UI or a
delete_schedule call.
The listing is of the revision, not the manifest. A manifest entry that has not been deployed yet does not
appear here at all — diff is what reports that direction.
STATE is the platform’s own schedule state, not something the CLI computes; ENABLED is the manifest-settable
flag. The two are independent, and a schedule can be enabled and yet in a state where it will never fire again.
Schedule states defines the set.
Under --json the payload carries schedules — each row with alias, id, repeat, enabled, state,
workflow and in_manifest — alongside drift and the envelope’s schema_version, in the same shape every
other command in this CLI reports it. (The workflow key holds the reference as an object — {definition} for a
local reference, {blob, revision, definition} for a blob named by id, or {org, blob, revision, definition}
fully qualified, the same three shapes create_execution takes;
the human table above renders it in the
path form instead.) The rendered drift: line
every other command prints is suppressed here, because an unmarked row already says it; the key is still present
so a script can read it uniformly across commands.
A schedule with no alias
-- in the alias column is not a rendering placeholder for something the CLI failed to read. It means the
platform stored no alias at all.
A schedule’s alias is optional platform-side. create_schedule writes the attribute only when one was
supplied, and the web UI’s create form offers a blank field as a valid choice — so a schedule created in the
browser has no alias unless someone typed one. Its record simply has no alias key.
That schedule is unmanageable declaratively. Alias is a manifest entry’s identity, so nothing in a manifest
can address one that has none: deploy can neither update it nor recognise it,
and pull cannot write it out. It is listed here anyway, by id, precisely because
it is still firing — a schedule you cannot see is worse than one you cannot manage, and the id in that row is the
only handle you have for going and removing it.
In --json its alias stays null rather than being backfilled with its id. That matters for anything reading
the payload: a consumer that could not tell an aliasless schedule from one named after its own id would write a
manifest entry for it, and the next deploy would create a second schedule beside the one still firing.
There is one way out, and it is not a CLI command. The platform’s
Update Schedule operation takes an optional alias, so an
existing schedule can be given one in place — after which it appears in this listing by name and the manifest can
adopt it like any other. No scheduler command will do that for you: deploy matches schedules by alias and
never sends one on an update, so it has no way to name a schedule that has no name yet.
What ls does not check
ls reads the scheduler blob and nothing else. It never resolves a schedule’s target, so the WORKFLOW column
is the reference the platform has stored, reported verbatim in the path form — not a claim that it still resolves
to anything.
That distinction has teeth, because the workflow reference is re-resolved every time the schedule fires. A
workflow definition renamed or deleted in its source revision leaves its schedule listed here, enabled, active,
and firing into nothing. diff is the read-only command that checks the reference
in its source revision; ls is the faster one that does not.
Errors
A schedule on the revision that the manifest does not cover is never an error here. Drift is a finding, not a
failure, and
ls exits 0 however much of it there is.
Every code above, with its remediation, is in Error codes.
See also
blobhub scheduler diff— the other direction: what the manifest has that the revision does not, and how the two differ where they overlap.blobhub scheduler pull— how an unmarked aliased row gets into your manifest.- Scheduler manifest — the alias grammar behind the load-time codes above.
- Scheduler blob type — schedule states, cron syntax and what the platform records for every fire.

