Run a multi-workspace dispatch loop

View as markdown
Instructions for

One 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 dev workspaces declared. If you only have one, add more with shelbi workspace add bravo (repeat as needed; pass --machine <name> to put one on a remote box), or edit the project YAML (~/.shelbi/projects/<name>.yaml, or <repo>/.shelbi/project.yaml in-repo) and run shelbi reload. The starter review slot a new project ships with doesn't count: it never takes dev dispatch and only serves finished branches (see review workspaces).

Confirm the pool

From the orchestrator pane (or any shell):

shelbi workspace list
NAME      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   idle

Every 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 (click 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-copy

The CLI does the same thing in a loop if you'd rather script it:

shelbi issue add "Add CSV export to the reports page" --id add-csv-export-to-reports
shelbi issue add "Fix cookie-domain bug on Safari SSO"
shelbi issue add "Tighten the rate-limit error copy" --id tighten-rate-limit-error-copy

Without --id, the id is the full slugified title (Add CSV export to the reports page becomes add-csv-export-to-the-reports-page), so the --id flags keep the ids short and match the commands below. 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 devbox

The 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-rename

The dependent card carries a lock icon and a "blocked by" line on its board card until every id in its depends_on list reaches done, and Zen Mode's auto-promote scan skips it. The badge itself doesn't gate dispatch: once the dependency is in progress, a promoted card is dispatched with its branch stacked on the dependency's branch. Starting it is only refused while a dependency hasn't started yet (or was canceled). If you want the dependent card to wait for the dependency to land, leave it in backlog. 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 board: open Issues (⌘I), then drag each card into To Do and drag within the column to set the order (or H/L and K/J on the keyboard). 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 a dot to a green ▶ 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:

myapp
Orchestrator⌘O
Issues⌘I
Changelog⌘L
Workspaces
hub
alphaDeveloper⌘1
bravoDeveloper⌘2
charlieDeveloper⌘3
devbox
deltaIdle
echoIdle
foxtrotIdle
Zen mode off
Filter:WorkflowsWorkspacesboard 2sSearchNew issue
BACKLOG0
TO DO0
IN PROGRESS3
Add CSV export to the reports page
taskyou/add-csv-export-to-reports
Fix cookie-domain bug on Safari SSO
taskyou/fix-cookie-domain-bug-on-safari-sso
Tighten the rate-limit error copy
taskyou/tighten-rate-limit-error-copy
REVIEW0
DONE0
CANCELED0
h/l column k/j card ↵ open ⇧h/⇧l move ⇧k/⇧j reorder drag to move or reorder s start a assign e edit E editor n new

The orchestrator's chat shows the same thing in prose:

Orchestrator: ✓ dispatched 3:
              - add-csv-export → alpha
              - fix-cookie-domain → bravo
              - tighten-rate-limit → charlie

To see the raw stream, open a second pane and tail the log:

shelbi events tail --follow

You'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_agent=developer 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_agent=developer from_category=ready to_category=active
…

Jump between workspace panes any time. Clicking bravo (or its ⌘1–⌘9 shortcut) drops you straight into its session to watch the Safari fix happen live. Pop back to the orchestrator with Orchestrator in the sidebar (or ⌘O) 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:

  1. The hub poller moves the issue from in_progress to review and clears the marker. The workflow's in-progress → review transition pushes the branch and opens a PR.
  2. The workspace's badge drops back to idle and the issue appears in the sidebar under Queued for Review.
  3. The orchestrator, watching the event stream, sees the workspace free up and immediately dispatches the next ready todo card 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.

If the project has a free review-tagged workspace (a new project ships one), the hub loads the queued issue onto it automatically. The Review agent checks the branch out in that slot's own worktree and serves it, and the row moves to Ready for Review with a cyan check:

Clicking the row opens the review panel, where you can talk to the Review agent, view the diff, and (once the workflow has a review: serve recipe) run the change. Set up review workspaces covers the review slot and the panel in detail. Without a review slot, the card stays queued: read the diff on the PR or locally instead.

Accept when you're ready: click Approve in the review panel, or move the card to done (drag it to Done on the board, or shelbi issue move <id> --to done). The workflow's review → done transition merges the branch, so don't also ask an agent to merge it. The card is yours; the orchestrator only takes the review → done step itself when Zen Mode is on and the project has no review workspace.

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 waiting on you. A card still in backlog never dispatches, including a 🔒 card you're holding back until its depends_on lands. Promote it to todo when it's ready.
  • The card prefers a machine and no workspace on it is free. The orchestrator parks it in todo rather than mis-routing. Free a workspace on the target machine (kill another issue, or remove the preference).
  • A workspace keeps crashing. Shelbi restarts a crashed pane and re-dispatches its issue on its own (supervision=restart). After repeated crashes it gives up (supervision=gave-up reason=crash-loop) and the orchestrator tells you. Investigate, or run shelbi workspace stop <name> to release the in-flight issue back to todo.
  • 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, in projects without a review workspace, auto-merge finished branches that clear a project-defined confidence bar.