Set up review workspaces
View as markdownThe 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
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. Leave slot: out and it defaults to the slot's
zero-based index among the machine's workspaces, which is why an explicit,
port-shaped value is worth setting on a review slot.
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.
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:
statuses:
- { id: in-progress, owner: agent, agent: developer }
- { id: review, owner: user, agent: review, tags: [review] }
- { id: done, owner: user }
transitions:
- from: review, to: done, actions: [merge, delete_branch]
review:
setup: npm install --no-audit --no-fund
serve: npm run dev -- -p $PORT
ready: curl -sf http://localhost:$PORT
url: http://localhost:$PORTShelbi 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.
The review → done transition is the accept edge: it merges the branch and
deletes it. Omit the review: block entirely and the Review agent falls back
to a diff-only review, booting nothing.
Reload to pick it up
shelbi reloadThe 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.
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.
Because that status requires tags: [review], the orchestrator routes the issue
onto a free review-tagged slot (preferring the one it ran on) and the Review
agent boots the server from the review: recipe. If every matching 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.
Open the review interface and click through
The issue appears in the sidebar under Ready for Review (✓) with a
machine:workspace badge showing the slot it's loaded on. Select it (or press
Enter on its row) to open the review interface: a two-column layout with
the review panel on the left (its own navigation, with a back button at the
top that returns you to the dashboard) and the swappable review content on the
right.
From the review panel you can:
- 🤓 Chat with Reviewer — talk to the Review agent (the default view).
- 🔀 View Diff — open your system diff tool over the review branch's
changes in the main pane. By default this uses git's configured diff tool
(
diff.tool, ordiff.guitoolfor a GUI tool) in directory-diff mode; if none is configured the panel shows a short error instead of launching. A diff tool that reviews a revision range rather than two directory trees (such asskim) cannot read the directory pair directory-diff mode hands it, so setreview.diff_commandinproject.yamlto run it directly instead. See Review diff command below. - ✍️ Edit in
<editor>— open the review worktree in your configured editor. - 🌐 Open Browser — open the served
urlin your system browser. This action only appears when the workflow declares a review URL.
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.
Approve or reject
You own the decision, and you make it from the review panel's Actions:
- ✅ Approve — moves the card one column forward (
review → done), firing that edge'sactions: per the workflow above, it merges the branch and deletes it. The interface tears down and focus returns to the dashboard. - ❌ Reject — opens a type-the-reason dialog. 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.
Review diff command
View Diff defaults to git difftool -d -y <base> HEAD — git's
directory-diff mode, which builds two temp trees and hands your diff.tool
two directory paths. Most terminal and GUI diff tools understand that.
Some tools instead review a revision range (skim <base> <head>,
for example): given two directory paths they render nothing and leak git
warnings into the pane.
For those, set a review.diff_command in project.yaml. It replaces the
default git difftool -d invocation with a command of your own, run 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 exactly the range shelbi diff reports, so the
override reviews the same changeset the default path does:
review:
diff_command: skim {base} {head}Leave review.diff_command unset (the default) and View Diff keeps using
git difftool -d -y, so existing setups are unchanged. Either way, 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 the orchestrator holds a review issue for you rather
than auto-merging it. When you're ready to hand the orchestrator the cases it
can judge on its own,
enable Zen Mode to auto-promote
backlog and 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, thereview:block, and the transition command fields. - Project config — machine and workspace
tags, and workspaceslot. - Global config — the hub-wide
editorthe "Edit in<editor>" view launches.