Work the orchestrator's work list — the backlog it works — from the shell, as a client of the work list API the orchestrator serves: add an item, read the work, stop a running item, remove an item.
spinloop work add --url http://127.0.0.1:4010 --id fix-parser --instructions "fix the failing tests" --dir ./parser
spinloop work list --url http://127.0.0.1:4010
spinloop work abort --url http://127.0.0.1:4010 fix-parser
spinloop work remove --url http://127.0.0.1:4010 docs-refreshEach subcommand takes --url, the API's base address — the one the
orchestrator prints at its start — and presents the API's token as a bearer on
every call it makes. The token comes from --api-token, else
--api-token-file, else the SPINLOOP_API_TOKEN environment; two of the flags
at once is a refusal naming both, and a loopback API needs none.
The run's view of the items is the source of truth: the commands call the API
and report its answer. The API applies the items file's validation on an
item's fields, and it holds the file, the state, and the records the commands
would otherwise work — so a refusal reads the way the API states it. A command
that names no --url fails before it calls the API, naming the flag, and a
command that cannot reach the API fails naming the address — the cue to start
the run, or to fix the reach.
spinloop work add --url http://127.0.0.1:4010 --id fix-parser \
--instructions "fix the failing tests" --dir ./parser \
--tag gpu=a100 --priority 10The item's fields come from the flags and go to the API's add path, where the
API applies the items file's validation on them — the instructions and working
directory present, the tags well-formed key=value pairs, no key named twice —
and the file stays a valid items file after the write. An id the file already
carries is refused, naming it, and an id the state beside the file has recorded
done or failed is refused too, naming the record: an ended item is not
worked again under its own id. The API answers once the item is in the file,
and the command reports its answer: a refusal reads the way the API states it.
Piped or redirected:
spinloop work list --url http://127.0.0.1:4010
# a backlog - - -
# b running n 2026-09-14T10:00:00Z -
# c done n 2026-09-14T09:00:00Z 2026-09-14T09:30:00Z
# d failed - - 2026-09-14T08:00:00ZOn a terminal, a heading row and the columns aligned:
spinloop work list --url http://127.0.0.1:4010
# ID STATE NODE STARTED ENDED
# a backlog - - -
# b running n 2026-09-14T10:00:00Z -
# c done n 2026-09-14T09:00:00Z 2026-09-14T09:30:00Z
# d failed - - 2026-09-14T08:00:00ZEvery item in the work list with its record, in the file's order: the id, its
state — backlog, running, done or failed — the node a running item is
on, and when it started and ended. Piped or redirected, one plain line per
item, a dash where a value is absent, so a program can split the columns; on a
terminal, the columns line up as a table instead, each as wide as its widest
value — the heading included — and the state in its colour. An item with no
record is backlog. The list reads the work list API the orchestrator serves
— the run's view of the items, the source of truth. spinloop work ls is the
same list.
spinloop work abort --url http://127.0.0.1:4010 fix-parserStops a running item through the API's abort path: the item's agent stopped the way a clean interrupt stops it — the polite signal, the grace, then the hard end — and its record removed. The item is back in the backlog, and the run's next pass admits it again.
Only a running item can be aborted: an id the file does not carry is refused,
naming it, and an item the run records backlog, done or failed is refused
too, naming the item and its state. The API answers once the item is stopped,
and the command reports its answer: a refusal reads the way the API states it.
spinloop work remove --url http://127.0.0.1:4010 docs-refreshTakes an item out of the work list through the API's remove path: the item out of the items file, its record out of the state beside it, and its kept output from the logs beside it — the file a valid items file after the removal.
A running item cannot be removed: the refusal names it and the abort that goes first. An id the file does not carry is refused, naming it. The API answers once the item is out, and the command reports its answer.
- It reads no file and writes no file: the commands never touch the items file, the state, or the logs directly, and every mutation goes through the API the run owns.
- It never runs an agent, and never starts or stops one: an abort asks the run to stop its agent, and the run's own grace bounds the stop.
- It does not re-run an ended item. A
doneorfailedrecord stands against the id's re-add, the way the orchestrator's does. - An abort is a stop, not a cancel of the work: the item goes back to the backlog and is worked again on a later pass. To keep it out, remove it.
| Flag | Meaning |
|---|---|
--url <address> |
The work list API's base address — add, list, abort, remove |
--api-token <value> |
The work list API's bearer token — every subcommand |
--api-token-file <path> |
The file the work list API's bearer token stands in — every subcommand |
--id <id> |
The item's id — add |
--instructions <text> |
The instructions the item's agent is given — add |
--dir <path> |
The directory the agent works in — add |
--tag <key=value> |
A tag the item carries; repeatable — add |
--priority <n> |
The item's priority, higher first — add |
Where neither token flag is given, the token comes from the
SPINLOOP_API_TOKEN environment, and a loopback API needs none at all.
- Working a backlog against the fleet — the feature this command family drives
spinloop orchestrator— the run the commands talk to, and the work list API they call