Run a multi-workspace dispatch loop
View as markdownOne issue at a time is the on-ramp. The reason Shelbi exists is the other direction: half a dozen workspaces all running in their own worktrees, the orchestrator keeping every free slot loaded with the next ready card. This page walks the loop end-to-end.
You should already have a project with at least two workspaces declared.
If you only have one, edit ~/.shelbi/projects/<name>.yaml, bump the
pool, and run shelbi reload before you start.
Confirm the pool
From the orchestrator pane (or any shell):
shelbi workspace listNAME HOST AGENT INTEG STATE
alpha hub - conventional idle
bravo hub - conventional idle
charlie hub - conventional idle
delta devbox - conventional idle
echo devbox - conventional idle
foxtrot devbox - conventional idleEvery row should show idle under STATE and - under AGENT. A slot no
longer selects a runner: which runner (and model) each dispatch launches is
resolved from the agent that runs there. Nothing
is loaded yet. If a pane is dead, jump
to the workspace (Enter on its sidebar row): the session may have
stalled on a permission dialog, and resolving it puts the workspace back
in the rotation.
You want at least three free slots to see the loop do its job. Two cards on a one-slot pool is a queue, not a loop.
Queue up a stack of work
The fastest way to fill the backlog is to talk to the orchestrator in batches:
you: add three issues:
1. add CSV export to the reports page
2. fix the cookie-domain bug on Safari SSO
3. tighten the rate-limit error copy
Orchestrator: ✓ added 3 to backlog:
- add-csv-export-to-reports
- fix-cookie-domain-bug-on-safari-sso
- tighten-rate-limit-error-copyThe CLI does the same thing in a loop if you'd rather script it:
shelbi issue add "Add CSV export to the reports page"
shelbi issue add "Fix cookie-domain bug on Safari SSO"
shelbi issue add "Tighten the rate-limit error copy"Each lands in backlog as its own markdown card under
~/.shelbi/projects/<name>/tasks/. Nothing dispatches yet. The
backlog is still your triage queue.
Route an issue to a specific machine
When an issue is RAM-heavy, latency-sensitive, or you just want to keep
it off the hub, hint where it should run with --prefers-machine:
shelbi issue add "Re-encode the marketing video assets" \
--prefers-machine devboxThe orchestrator's dispatcher honors the hint when at least one
workspace on that machine is free. If devbox is fully busy when the
issue becomes ready, the card stays in todo.
A machine preference is never overridden silently
Shelbi will not re-route a --prefers-machine issue to the hub just because
the preferred machine is busy. It parks the card in todo and waits. Free
a workspace on that machine, or drop the preference, to get it moving.
Block one issue on another
If issue B reads files issue A is about to rewrite, declare the order explicitly:
shelbi issue add "Rename the auth_v1 module to auth" --id auth-rename
shelbi issue add "Update the OpenAPI spec for the new auth module" \
--depends-on auth-renameThe dependent card carries a 🔒 badge in the Kanban view and the
orchestrator skips it during dispatch until every id in its
depends_on list reaches done. See
dependent issues
for the full state model.
Promote everything to todo
Promotion is the start signal. Move all three cards into todo in the order you want them picked up:
-
From the Kanban view —
Ctrl+P→ Issues, thenH/Lto walk cards into the next column.K/Jto reorder withintodo. The orchestrator dispatches from the top. -
From the orchestrator — just ask:
you: promote all three. -
From the CLI — one move per card:
shelbi issue move add-csv-export-to-reports --to todo shelbi issue move fix-cookie-domain-bug-on-safari-sso --to todo shelbi issue move tighten-rate-limit-error-copy --to todo
The orchestrator is already tailing ~/.shelbi/events.log. Each
promotion arrives as a project=<p> task=<id> workflow=<name> backlog -> todo reason=user:* from_category=backlog to_category=ready line and
triggers an immediate dispatch attempt.
Watch the loop in action
Within a second or two, the sidebar lights up. Workspace badges flip
from · to ⏵ in YAML declaration order: alpha, then bravo,
then charlie, until either the todo column is empty or every
workspace is busy. The sidebar groups slots under the machine they're
pinned to, and each busy row shows the agent it's running:
The orchestrator's chat shows the same thing in prose:
Orchestrator: ✓ dispatched 3:
- add-csv-export → alpha
- fix-cookie-domain → bravo
- tighten-rate-limit → charlieTo see the raw stream, open a second pane and tail the log:
shelbi events tail --followYou'll see the column moves and the workspace state changes interleaved, exactly what the orchestrator is reacting to:
2026-06-22T14:11:02+00:00 project=myapp task=add-csv-export-to-reports workflow=task backlog -> todo reason=user:cli from_category=backlog to_category=ready
2026-06-22T14:11:02+00:00 project=myapp task=add-csv-export-to-reports workflow=task todo -> in_progress reason=orchestrator:auto-dispatch_workspace=alpha from_category=ready to_category=active
2026-06-22T14:11:03+00:00 project=myapp workspace=alpha none -> working
2026-06-22T14:11:04+00:00 project=myapp task=fix-cookie-domain-bug-on-safari-sso workflow=task backlog -> todo reason=user:cli from_category=backlog to_category=ready
2026-06-22T14:11:04+00:00 project=myapp task=fix-cookie-domain-bug-on-safari-sso workflow=task todo -> in_progress reason=orchestrator:auto-dispatch_workspace=bravo from_category=ready to_category=active
…Jump between workspace panes any time. Enter on bravo drops you
straight into its pane to watch the Safari fix happen live. Pop back
to the orchestrator with Ctrl+P → Chat when you're done.
Review one branch while the others keep running
Workspaces finish at their own pace. When the first one writes its review-ready marker, three things happen at once:
- The hub poller moves the issue from
in_progresstoreviewand clears the marker. - The workspace's badge drops from
⏵back to idle (·) and a✓row appears in the sidebar's Ready for Review section. - The orchestrator, watching the event stream, sees the workspace free
up and immediately dispatches the next ready
todocard to that slot (if any).
That last step is the loop. You don't have to ask. The workspace that just handed off a finished branch is already on its next issue by the time you've clicked into the review pane.
Open the review:
✓ add-csv-export alpha ← EnterShelbi checks the branch out into the project's working directory on the machine that ran the issue and spawns a fresh agent session pointed at the diff. Ask it to walk you through the change, run tests, or request edits. The workspace that produced the branch is busy on something else, but the review pane is its own conversation in the same worktree.
Accept when you're ready:
you: merge it.Then move the card from review to done (L in the kanban view,
or shelbi issue move <id> --to done). The card is yours; the
orchestrator only takes the review → done step when you've
explicitly authorized it as part of Zen
Mode.
While you've been reviewing, the orchestrator has been working the backlog. By the time you finish accepting one branch, two more may be in review. The board state is the single source of truth: the sidebar mirrors it, the events log records every move, and the orchestrator keeps every free slot loaded.
When the loop stalls
A few things stop the dispatcher from filling a free slot, in intentional ways. They're worth recognizing so you don't mistake intent for breakage:
- The card is blocked. Anything in
depends_onis not yetdone. The card renders with🔒in the kanban view. Land the dependency first. - The card prefers a machine and no workspace on it is free. The
orchestrator parks it in
todorather than mis-routing. Free a workspace on the target machine (kill another issue, or remove the preference). - The workspace's pane died. The orchestrator surfaces it
(
workspace=<name> pane_alive=false) and waits for you. Re-launch withEnteron the workspace row, orshelbi workspace stop <name>to release the in-flight issue back totodo. - The mid-conversation guard. If you're actively chatting with the orchestrator about a specific issue, it holds off on back-to-back dispatches that would talk over you. The next event resumes the loop.
Everything else (diff size, branch contents, file ownership) is the orchestrator's job to figure out from the prompt. Move the card and move on.
Next
The orchestrator is now keeping every workspace fed without your involvement past triage and review. Reviewing a diff is one thing. The next step is running the change: set up review workspaces to load a finished branch onto a live dev server and click through it before you accept. After that, enable Zen Mode to let the orchestrator auto-promote eligible backlog cards and auto-merge finished branches that clear a project-defined confidence bar.