Author a custom Shelbi workflow
View as markdownThe orchestrator is your runner (claude, codex, …) booted with a
system prompt that explains the board, the workspaces, and the loop. That
prompt is the workflow: the contract for who initiates what, how
dispatch is decided, and how the agent reports back. Shelbi ships a
sensible default and seeds it into every project as an editable file.
This page customizes the orchestrator's prompt, encodes three concrete tweaks, and applies them. The underlying machinery lives in the orchestrator concept page; this is the practical version.
Where the prompt lives
The orchestrator is a project-local agent with shipped defaults.
Its prompt is composed from two files, both under the project's agents/
directory (~/.shelbi/projects/<name>/agents/ in the default
global mode, or <repo>/.shelbi/agents/
in in-repo mode):
agents/orchestrator/instructions.md— the orchestrator-specific system prompt. Seeded with the shipped default on first load; your edits stay put on upgrade.agents/_shared/preamble.md— project-wide context prepended to every agent (developer, qa, orchestrator…). Put the repo layout, house style, and test command here so you write it once instead of pasting it into four prompts.
On every shelbi reload (and at session start) Shelbi composes
preamble.md + instructions.md and writes the rendered output to
~/.shelbi/projects/<name>/CLAUDE.md,
which is state, so it lives under ~/.shelbi/ in both modes. The
orchestrator launches in that directory and auto-loads the rendered
prompt. No flags, no env vars, no MCP.
Don't hand-edit CLAUDE.md
CLAUDE.md is a rendered artifact. Put project-wide bits in
_shared/preamble.md and orchestrator-specific bits in
agents/orchestrator/instructions.md. Every shelbi reload overwrites
CLAUDE.md, so hand-edits are silently lost.
Start from the default
Don't rewrite from a blank file. The default prompt encodes load-bearing contracts (bootstrap, reaction rules, reason strings) that the rest of Shelbi expects the orchestrator to honor. Open the seeded default and edit in place:
shelbi agent edit orchestratorThat opens agents/orchestrator/instructions.md in $EDITOR (and
materializes the shipped default first if you haven't touched it
yet). The file is plain markdown. Read it top to bottom before changing
anything. The comments explain why each section exists.
What to keep when you fork
A handful of pieces are the contract between the orchestrator and the rest of the system. Edit them carefully, but don't delete:
- The bootstrap flow. The first reply of every session runs
shelbi task list,shelbi workspace list, startsshelbi events tail --follow, and readsshelbi zen status. Drop any of these and the orchestrator boots without state. - The reaction rules tied to specific reason strings. The
orchestrator dispatches on
user:*promotions, rolls workspaces onworkspace:ready-marker, and wakes onheartbeatlines. The rest of Shelbi emits those strings. Your prompt has to recognize them. - The "you are the scheduler" framing. Without it, the agent reverts to chatbot mode and waits to be told what to do. The whole loop falls apart.
- The Zen-Mode section (if you intend to use Zen). Replace the
judgment categories and the merge conditions if they don't fit
your project, but keep the section structure. The wrapper around
shelbi zen probereads the same primitives regardless of the prose around them.
Everything else is fair game.
Three example tweaks
A workflow override pays for itself the first time the agent stops asking a question you've answered the same way a dozen times. Three patterns worth stealing.
1. Pin certain task shapes to specific workspaces
The default scheduler picks the first free workspace in YAML
declaration order, honoring prefers_machine hints. If your project
has natural routing (infra tasks always to a beefy box, UI tasks
always somewhere with the design system pre-cached), bake it into
the workflow:
## Routing rules
In addition to the project YAML's `prefers_machine` hints, apply
these project-specific rules when picking a workspace for a `todo`
card:
- **Infra tasks** — titles containing `infra:`, `terraform`,
`helm`, `kubectl`, or paths under `infra/`. Always route to
`devbox` (the beefier remote). If no `devbox` workspace is free,
leave the card in `todo` rather than routing to the hub.
- **Docs and content** — titles containing `docs:` or paths under
`site/content/**`. Route to the first free hub workspace; these
are short, IO-light tasks that don't need the remote.
- **Migration touch-ups** — anything matching `db/migrate/**` or
`crates/shelbi-state/src/migrations/**` always goes to
`charlie` (so the same agent context accumulates across the
series). If charlie is busy, hold in `todo`.
These rules take precedence over default declaration-order
selection. The YAML's `prefers_machine` hint still overrides
everything if set explicitly on a card.The orchestrator now applies your routing on top of the default free-workspace scan. No code change.
2. Tune Zen's judgment categories for this project's reality
The bundled default's judgment categories are deliberately conservative: promote if you've routinely accepted this shape, or the user just raised the issue, or it's part of a larger body of work they kicked off. That's a sensible starting bar, but every project has its own "always safe" pattern. Encode it:
## Zen Mode
### Auto-promote judgment categories
Promote a backlog candidate to `todo` only if **at least one** is
true:
1. **Tagged `automation:` in the title.** Always in scope —
these are bot-filed PR-bumps and lint sweeps we have years of
acceptance history on.
2. **Touches only `docs/**` or `site/content/**`.** Content
edits are reversible and never reach prod. If the task body
names a file outside those globs, fall through.
3. **The user has accepted ≥3 tasks of the same shape (same
verb-prefix, same target directory) without changes in the
last week.** Track this against the `done` column via
`shelbi task list --column done`.
If none of the above, leave the card in `backlog`, emit
`reason=orchestrator:zen-decline reason-text=<short>`, and surface
it in the next reply ("I considered promoting `<task>` but wasn't
sure — want me to?").
### Merge conditions
(Inherit from the default — see the bundled template.)The Rust side (shelbi zen scan) never inspects this prose. It
just emits the mechanically-eligible candidates. Your override
decides which of those actually get promoted.
3. Change the reporting style
The default prompt errs toward terse one-line status updates ("✓ dispatched to delta. branch: shelbi/fix-login"). If you'd rather get a richer rundown (or a quieter one), say so:
## Reporting style
When dispatching, reply with:
- The card id and chosen workspace (always).
- The full first line of the task body (so the user sees what
you're about to make the workspace work on).
- An estimated complexity tag (`xs` / `s` / `m` / `l`) based on
the body and any `depends_on`. Don't overthink it — a one-token
guess is better than nothing.
When reporting a finished review:
- The card id, the workspace, and the branch.
- A two-bullet summary of what the diff changed (read it via
`git diff main..<branch> --stat`).
- Whether a relevant `done`-column precedent exists for this
shape of change.
Background sweeps (heartbeat-triggered re-checks) report nothing
unless they take action. Silence is fine when the board is quiet.This is the easiest place to start customizing. The behavior the orchestrator gives you is downstream of the prose you write here. Ask for the report you actually want.
Apply the edits
Edit the orchestrator's instructions
shelbi agent edit orchestratorOpens agents/orchestrator/instructions.md in $EDITOR.
Re-render and respawn the dashboard
shelbi reloadComposes the prompt against your edits and respawns the panes.
Verify what landed
shelbi agent show orchestratorPrints instructions.md followed by the agent's skills/.
The composed prompt (preamble + instructions) is written to
~/.shelbi/projects/<name>/CLAUDE.md on every shelbi reload. Read
that file to see exactly what the runner loads.
shelbi reload respawns the sidebar, Tasks, and Review panes against the
new config without restarting workspaces or losing chat history. It does
recycle the orchestrator pane, so its conversation context resets: the
cost of changing the system prompt mid-session. Heads up before the next
turn.
Iterate from prose, not code
The whole point of putting the workflow in markdown is that you can keep tightening it. Two practical habits:
- Treat surprises as prompt bugs. When the orchestrator does
something you didn't expect (promotes a card you'd have held,
reports in a style you find noisy, picks the wrong workspace), open
agents/orchestrator/instructions.mdand add the rule that would have produced the outcome you wanted. Reload. Try again. - Version-control the prompt. Check
agents/orchestrator/andagents/_shared/into the repo (or a dotfiles repo) and symlink them into place. These prompts are the most opinionated artifacts in your Shelbi setup, and the ones most worth preserving across machine moves and reinstalls.
What you should not do is try to encode policy in code. The
mechanical layer (the Rust CLI) is intentionally generous.
shelbi zen scan will hand the orchestrator everything that's
mechanically safe, and your prompt picks which of those to actually
run. That separation is what lets you raise or lower the bar by
editing prose.
See also
- Workflow config — the YAML field reference for the status pipeline the orchestrator runs work through.
- Orchestrator — how the prompt template is loaded, the bootstrap flow it triggers, and the reaction rules tied to specific event reason strings.
- Zen Mode — the high-confidence bar your custom judgment categories sit on top of.
- The events log — the full reason string vocabulary the orchestrator emits and your override may want to recognize or extend.
shelbi zen— the single-purpose primitives the orchestrator sequences during auto-merge, available to call by hand any time.