Set up review workspaces

View as markdown
Instructions for

The multi-workspace loop gets finished branches back to you. But reading a diff isn't the same as running the change. Most real review of an app or a site means booting the dev server, opening a URL, and clicking through it.

The routing that gets an issue to a review slot is assembled from generic primitives: a workspace carries a tag and a status requires that tag. On top of that, the workflow's review: block tells the Review agent how to boot the branch, and Shelbi's review interface lets you run the change and accept or reject it. This page wires them together end to end. For the model underneath, see the reference: Review workspaces.

You need a working pool first

This page assumes you already have a project with a workspace pool and can promote an issue through the board. The first task and multi-workspace pages get you there. A review workspace is an ordinary slot with a tag, not a new kind of thing.

Set up and use the review flow

New projects already have most of this: shelbi init creates a review workspace tagged review, and the shipped task workflow's review status already requires that tag and runs the review agent. For a new project, the real work is giving that slot a slot: port (step 1) and adding the review: block (step 2). The tagging steps matter for projects created earlier or with custom workflows.

1

Tag a workspace for review

Add a review tag to a slot in your project YAML (~/.shelbi/projects/<name>.yaml in global mode, <repo>/.shelbi/project.yaml in-repo). Tag one workspace directly, or tag the machine so every slot on it inherits the tag:

workspaces:
  - { name: alpha,    machine: hub }
  - { name: bravo,    machine: hub }
  - { name: review-0, machine: hub, tags: [review], slot: 3000 }

tags accepts a bare string as shorthand (tags: review). The slot: 3000 sets the numeric slot the review: recipe below resolves $PORT to, so the dev server binds :3000. A review slot that serves a review: recipe must set slot:. The recipe takes its $PORT only from an explicit slot:, and without one the Review agent stops and reports a misconfiguration instead of serving. (The declaration-order fallback applies only to $SLOT in transition run: commands.)

One review slot is plenty to start

Each review slot holds one running server bound to its port, so give a second review slot a different slot: value (3010) to avoid a collision. One is enough for a first pass.

2

Require the tag and add a review: serve recipe

In your workflow file, require the review tag on the review status so issues route to the tagged slot, then add a review: block telling the Review agent how to boot the branch:

# Excerpt: the other statuses and the `→ canceled` edges stay as they are.
statuses:
  - { id: in-progress, owner: agent, agent: developer }
  - { id: review,      owner: user,  agent: review, tags: [review] }
  - { id: done,        owner: user }
 
transitions:
  - { from: in-progress, to: review, actions: [push_branch, open_pr] }
  - { from: review,      to: done,   actions: [push_branch, merge] }
 
review:
  setup: npm install --no-audit --no-fund
  serve: npm run dev -- -p $PORT
  ready: curl -sf http://localhost:$PORT
  url: http://localhost:$PORT

Shelbi resolves $PORT (equivalently $SLOT) to the review slot's port (3000 here) and injects the recipe into the Review agent's prompt. The agent runs setup, launches serve, polls ready until the server answers, and hands back the url. Swap the npm lines for whatever your project needs: cargo run, a Makefile target, a Procfile web: line. For a monorepo, add workdir: site (or app, docs) so each workflow serves its own subdirectory on the slot's port.

These are the shipped task workflow's edges. Entering review pushes the branch and opens a PR; the review → done transition is the accept edge, and it pushes and merges the branch. Omit the review: block entirely and the Review agent falls back to a diff-only review, booting nothing.

3

Reload to pick it up

shelbi reload

The tagged slot does not show up under Workspaces. A review slot's capacity surfaces through the review sections instead, and only once an issue is routed to it.

4

Get an issue to the review status

Run an issue the way you normally would: promote a card and let a dev workspace pick it up, or dispatch one through the orchestrator. When the dev workspace finishes it writes its review-ready marker; the hub poller rebases the branch onto the base branch and moves the issue into the Review status, which pushes the branch and opens a PR.

Because that status requires tags: [review], the hub automatically loads the issue onto the first free review-tagged slot (the orchestrator never does this) and the Review agent boots the server from the review: recipe. You can also load it yourself by clicking its Queued for review row, from the palette, or from Go ▸ Reviews. If every review slot is busy the issue waits under Queued for Review until one frees; nothing is preempted.

The finishing dev workspace closes its own session and returns to idle. Its work is now waiting to be run, not edited.

5

Open the review interface and click through

The issue appears in the sidebar under Ready for review with a cyan check. Click it (or press its ⌘1–⌘9 shortcut) to open the review view: the review panel takes the sidebar's column (a back button at the top returns you to the board, and Esc does the same) and the swappable review content fills the main area.

myapp
Orchestrator⌘O
Issues⌘I
Changelog⌘L
Workspaces
alphaIdle
bravoIdle
Ready for review1
Polish dark-mode toggle⌘1
you/dark-mode-toggle-polish
Zen mode off
Filter:WorkflowsWorkspacesboard 2sSearchNew issue
BACKLOG0
TO DO0
IN PROGRESS0
REVIEW1
Polish dark-mode toggle
taskyou/dark-mode-toggle-polish
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

From the review panel you can:

The views are numbered, so ⌘1, ⌘2, and so on switch between them while the review is open.

  • Reviewer: talk to the Review agent (the default view).
  • View Diff: read the review branch's changes in Shelbi's own diff view, in the main area. Press ? there for its keys. Enter comments on a line, and gY starts a reject with your comments as its reason. To open another tool instead, see Using another diff tool below.
  • Edit in <editor>: open the review worktree in your configured editor: inside Shelbi for a command, in the editor app for an app.
  • Web Browser: open the served url in your browser. It reads "loading…" until the server is up, and only appears when the workflow declares a review URL.
  • Shell: a shell in the review worktree, beside the content.

The worktree's folder sits above the views; Open reveals it in Finder. On a remote review slot, Edit is hidden, and View Diff is offered only for Shelbi's own view, which reads a worktree on any machine.

The built-in review agent's charter is narrow: load and serve, don't code. It won't modify the branch or move the card. Point agent: at an agent you've authored to change what runs there.

6

Approve or reject

You own the decision, and you make it from the Approve and Reject buttons under Actions in the review panel (or the issue's submenu under Go ▸ Reviews):

  • Approve: moves the card one column forward (review → done), firing that edge's actions: per the workflow above, it pushes and merges the branch. The interface tears down and focus returns to the dashboard.
  • Reject: opens a type-the-reason dialog (Ctrl-D submits). On submit, the reason is appended to the issue body and the card bounces back to the ready status for another pass. An empty reason can't submit.

Either decision frees the review slot for the next issue routed for review, if any.

Using another diff tool

View Diff opens Shelbi's own diff view unless you choose otherwise. There are two ways to choose:

  • diff_tool in ~/.shelbi/config.yaml, or the Diff tool picker in Settings ▸ General, picks a tool for every project. diff_tool: git runs git's own difftool (diff.guitool, else diff.tool). A command runs in the main pane, and an app opens in the app.
  • review.diff_command in project.yaml runs a command of your own for one project, and takes precedence over diff_tool.

Use review.diff_command for a tool that reviews a revision range rather than a pair of files or folders (skim <base> <head>, for example). It runs in the review worktree, with three placeholders substituted:

  • {worktree}: the review workspace worktree,
  • {base}: merge-base(<base branch>, HEAD), the fork point, and
  • {head}: HEAD.

{base} and {head} are the same range the built-in view shows:

review:
  diff_command: skim {base} {head}

A diff tool that exits without rendering leaves a short message in the pane rather than only git warnings.

Next

Routing an issue to a review workspace is the human path: the whole point is human eyes on the running app. Keeping merge on the accept edge and off the enter-review edge means a review issue waits for you rather than merging on arrival, and while a project has a review workspace, Zen Mode never auto-merges a handoff either. When you're ready to hand the orchestrator the cases it can judge on its own, enable Zen Mode to auto-promote backlog, and (in a project without review workspaces) auto-merge finished branches that clear a confidence bar you define.

See also

  • Review workspaces: the full model: tags, status-tag routing, the review: serve recipe, the review sidebar, and the review interface.
  • Workflow config: status tags, the review: block, and the transition command fields.
  • Project config: machine and workspace tags, and workspace slot.
  • Global config: the hub-wide editor the "Edit in <editor>" view launches.