shelbi issue
View as markdownshelbi issue <SUBCOMMAND> [OPTIONS]shelbi issue is the CLI face of the Kanban board. Each card is a file under
~/.shelbi/projects/<project>/tasks/; each column transition appends a line to
~/.shelbi/events.log. The TUI's issues pane and this command are two views on
the same files. The orchestrator drives the board through it, and it's where
scripting, automation, and one-off fixes live.
Renamed from `shelbi task`
This command was called shelbi task in earlier releases. shelbi task still
works as a deprecated alias (it prints a notice and forwards to shelbi issue)
so existing scripts keep running, but it will be removed in a future release.
Prefer shelbi issue.
Works against either backend
The file paths above describe the default file system backend. When a project
sets issue_tracker.backend: github, each card is a GitHub issue instead and
these same subcommands drive it (move relabels the issue, comment posts a
native issue comment, and so on). See the
GitHub Issues backend, and
shelbi issue-store migrate to move a board between
backends.
A board mid-flight, with one issue promoted to TO DO, one dispatched to a
workspace, and one already DONE:
Every subcommand accepts the global -p / --project <PROJECT> flag: it targets
the named project, otherwise $SHELBI_PROJECT or the registered project whose
work_dir contains the current directory. It's omitted from the per-subcommand
tables below.
add
shelbi issue add [OPTIONS] <TITLE>Create a new issue. Lands in backlog by default, your inbox for triage.
Pass --status todo to skip triage when you're already sure.
| Flag | Type | Default | Description |
|---|---|---|---|
<TITLE> | string | — | Human-readable title (positional, required). |
--id <ID> | string | slug of title | Override the auto-generated id. |
--status <STATUS> | string | backlog | Initial status. |
-d, --description <DESCRIPTION> | string | the title | Issue body. May instead be piped on stdin (shelbi issue add "Title" <<EOF … EOF); passing both is an error. When neither is given, the body defaults to the title; use shelbi issue edit to fill it in later. |
--depends-on <ID> | string (repeatable) | — | Block this issue on another. Repeat for multiple deps. |
--prefers-machine <NAME> | string | — | Hint for the orchestrator to route this issue to a workspace on a specific machine. |
--workflow <NAME> | string | project default | Workflow this issue runs under. Names a file in workflows/<NAME>.yaml. Omit to inherit the project's default workflow. |
--branch <BRANCH> | string | generated at dispatch | Pre-fill the issue's branch: frontmatter field. Omit to let the orchestrator generate <prefix>/<task-id> from workflow config, project config, or your GitHub username; supply a value to point the issue at an existing branch (the release issue pattern). |
--top | flag | off | Land the new issue at the top of its status's queue instead of the end. |
list
shelbi issue list [OPTIONS]Print every issue grouped by column, in priority order within each column. Use
--status <NAME> to scope to one status, or --ready to see only unblocked
todo items in dispatch order. That's the orchestrator's view of "what
should I assign next." --workflow <NAME> narrows either view to a single
workflow.
| Flag | Type | Default | Description |
|---|---|---|---|
--status <STATUS> | string | — | Restrict to a single status. |
--ready | flag | off | Show only unblocked todo items, in priority order. Mutually exclusive with --status. |
--workflow <NAME> | string | — | Restrict to issues resolved to the named workflow. Issues with no explicit workflow: field inherit the project's default_workflow, or default when unset. Composes with --status and --ready. |
show
shelbi issue show <ID>Print an issue's frontmatter and body, plus the resolved status of each
depends_on entry. The same view the orchestrator reads before deciding
whether an issue is ready to dispatch.
depends
shelbi issue depends [OPTIONS] <ID>Edit an issue's dependency list without opening the file.
| Flag | Type | Default | Description |
|---|---|---|---|
--add <DEP> | string (repeatable) | — | Dependency id to add. |
--remove <DEP> | string (repeatable) | — | Dependency id to remove. |
move
shelbi issue move --to <STATUS> [OPTIONS] <ID>Move an issue between statuses. Promoting to todo is the orchestrator's start
signal. It picks a free workspace and runs issue start itself.
The destination is validated against the issue's workflow. A status the
workflow doesn't declare errors with the list of statuses it does declare, and
the issue stays put. The core statuses accept friendly spellings in any case
(InProgress, wip, to-do, cancelled, completed, …); a custom status id
must match exactly. An issue pinned to a workflow with no YAML on disk falls
back to the built-in default (with a warning), so projects keep moving while
the workflows directory is empty.
Moving across an edge that declares
transition actions runs them. A merge
action is gated: the branch is merged before the card moves, and a failed merge
leaves the issue where it was. A move into in_progress also cuts the issue's
branch on the hub first.
| Flag | Type | Default | Description |
|---|---|---|---|
--to <STATUS> | string | — | Destination status (required). Must be a status declared by the issue's workflow. |
--reason <REASON> | string | user:cli | Reason tag recorded in ~/.shelbi/events.log. The orchestrator parses this to tell auto-dispatches apart from user actions. |
--skip-transition-actions | flag | off | Recovery escape hatch: advance the card without running the destination transition's actions (merge, push_branch, open_pr, …). Use only when the git work already happened out of band, such as a PR merged by hand. The move is stamped actions=skipped in the event log. |
assign
shelbi issue assign --to <WORKSPACE> <ID>Set the issue's assigned_to field without launching the workspace. Use
this when you want to pre-allocate before promoting to todo. The
workspace must be declared in the project YAML. A workspace already running a
different in_progress issue is refused.
| Flag | Type | Default | Description |
|---|---|---|---|
--to <WORKSPACE> | string | — | Workspace name (required). |
--force | flag | off | Assign onto a review-tagged workspace anyway (refused by default; review slots load handed-off branches through the review queue). The override is recorded in ~/.shelbi/events.log. |
unassign
shelbi issue unassign <ID>Clear an issue's assigned_to field. The issue stays in its current column.
start
shelbi issue start [OPTIONS] <ID>Launch the assigned workspace on this issue. Three things happen in one shot:
- The workspace's worktree is checked out to the issue's branch (generated from workflow config, project config, or your GitHub username when unset).
- Any existing session for that workspace is ended. Context is wiped clean.
- The runner relaunches with the issue prompt and the column transitions
into
in_progress.
Pass --workspace to assign and launch in one call. This is the command
the orchestrator runs when an issue hits todo.
| Flag | Type | Default | Description |
|---|---|---|---|
--workspace <WORKSPACE> | string | issue's assigned_to | Assign and launch in one call. |
--branch <BRANCH> | string | generated | Override the default branch name. |
--reason <REASON> | string | user:cli:start | Reason tag recorded in ~/.shelbi/events.log when the column transitions to in_progress. |
--force | flag | off | Launch on a review-tagged workspace anyway (refused by default). Recorded in ~/.shelbi/events.log. |
--take | flag | off | On a remote issue tracker (e.g. GitHub), assign the issue to you on the tracker before starting. Needed for an unassigned issue or one you're taking over; Shelbi only starts issues assigned to you there. The orchestrator never passes it. |
resume
shelbi issue resume [OPTIONS] <ID>Relaunch the assigned workspace on the issue it is already working, without throwing away progress. Use it when a worker stalls or its session dies (a killed or wedged session, an agent that stopped mid-issue) and you want it going again on the same issue with its work intact.
resume is the recovery counterpart to start. start wipes
the agent's context (ends the session and re-checks-out a clean branch): right
for a fresh dispatch, wrong for recovery. resume instead preserves the
in-flight state:
- The workspace's worktree is left as-is: its branch, commits, and uncommitted changes stay exactly where the worker left them. The branch is never reset or re-checked-out. (If the worktree was torn down entirely, it's recreated on the issue's existing branch.)
- The runner session is recreated or reclaimed: a killed session is stood back up, and a stale or wedged one (the duplicate-session case) is torn down before the fresh session comes up.
- For a claude runner the session relaunches with
--continue, so the worker reloads its prior conversation and picks up mid-thought with full context. Other runners fall back to re-injecting the issue prompt. The agent continues by reading its own prior work in the worktree. Either way the prompt is auto-submitted.
If the card has drifted out of in_progress (a killed worker whose issue
someone moved back), resume restores it.
| Flag | Type | Default | Description |
|---|---|---|---|
--workspace <WORKSPACE> | string | issue's assigned_to | Workspace whose worktree holds the in-flight work. |
--reason <REASON> | string | user:cli:resume | Reason tag recorded in ~/.shelbi/events.log if the resume has to move the card back into in_progress. |
--take | flag | off | Claim the issue on a remote issue tracker before resuming it (see start --take). |
prio
shelbi issue prio [OPTIONS] <ID>Re-order an issue within its column. The orchestrator picks the top-most ready
issue when dispatching, so prio is how you steer "what's next" without
opening the TUI.
| Flag | Type | Default | Description |
|---|---|---|---|
--up | flag | — | Move up one slot. |
--down | flag | — | Move down one slot. |
--top | flag | — | Move to the top of the column. |
--bottom | flag | — | Move to the bottom of the column. |
--set <N> | integer | — | Move to a specific 0-based slot. |
Pass exactly one of these flags.
edit
shelbi issue edit <ID> [OPTIONS]With no flags, opens the issue's frontmatter and body in $EDITOR for
free-form edits. On the file_system backend that's the issue's markdown file.
On a remote tracker such as GitHub it's a local copy of the same document, and
saving writes back what you changed: the title, the body, and the metadata
block. A field someone else changed while the editor was open is kept unless
you changed it too, in which case nothing is saved. The column, priority,
and assigned_to fields have dedicated commands, so an edit to them on a remote
tracker is refused. When a save can't land, the error says where your edits were
kept.
Any field flag switches to non-interactive mode, the path for the
orchestrator, CI, or a script to revise an issue after creation. A
non-interactive edit bumps updated_at, validates the touched fields
before writing, and emits an edited event so the change is visible to
the board and the activity feed. Fields that already have a dedicated
command (move, prio, assign, depends) are out of scope; use those.
| Flag | Type | Description |
|---|---|---|
--title <TITLE> | string | Change the display title. The issue's id stays stable (never re-slugged). |
--body <TEXT> | string | Replace the body with this text. |
--body-file <PATH> | path | Replace the body with a file's contents. |
| (stdin) | pipe | Pipe the body: shelbi issue edit <id> <<EOF … EOF. |
--append | flag | Append the body source to the existing body instead of replacing it. |
--workflow <NAME> | string | Set the workflow. Must name an existing workflows/<NAME>.yaml. |
--branch <BRANCH> | string | Set the branch: override. |
--prefers-machine <NAME> | string | Set the machine-affinity hint. |
--no-prefers-machine | flag | Clear the machine-affinity hint. |
--param <KEY=VALUE> | string | Set a workflow param, a free-form frontmatter key a workflow reads as {{KEY}}, such as a subtask's task. The value is stored as a string. Repeatable. Works on every backend. |
--no-param <KEY> | string | Clear a workflow param. Repeatable. Works on every backend. |
--sub <OLD> <NEW> | 2× string | Literal in-place body substitution. Repeatable. |
--sub-regex <PATTERN> <REPLACEMENT> | 2× string | Regex body substitution; REPLACEMENT may reference capture groups ($1). Repeatable. |
--allow-no-match | flag | Permit a substitution that matches zero occurrences (default: error, writing nothing). |
--reason <REASON> | string | Annotation recorded in the emitted edited event. Defaults to user:cli. |
The body sources (--body, --body-file, stdin) are mutually exclusive
with each other and with the substitution flags. Substitutions replace
all occurrences of each match and report a per-substitution count;
multiple --sub/--sub-regex apply in command-line order, each operating
on the previous one's output. Editing an issue whose column is an active
status (e.g. in_progress) prints a warning: the running worker won't see
the change until the issue is re-dispatched with shelbi issue start.
# Fix a stale path and swap a value in place, before dispatch.
shelbi issue edit fix-login-flow \
--sub "src/old_auth.rs" "src/auth.rs" \
--sub-regex "timeout=([0-9]+)" "timeout=30"
# Append a late acceptance criterion without rewriting the body.
shelbi issue edit fix-login-flow --append <<'EOF'
- [ ] Session cookies are cleared on logout.
EOFrm
shelbi issue rm <ID>Delete an issue. On the file_system backend this removes its markdown file;
on a github board it closes the GitHub issue as not planned (GitHub can't
delete issues). Either way the column's priorities are renumbered.
Irreversible
On the file system backend shelbi issue rm deletes the markdown file
outright. There's no trash and no undo. To take a card off the board without
destroying its history, move it to canceled instead.
comment
shelbi issue comment <ID> <TEXT>Post a comment on an issue. It works against whichever backend the project is
configured for: on the default file_system board the comment is a local
markdown file; on a github board it is a native GitHub issue comment. See the
GitHub Issues backend.
issue-store migrate
shelbi issue-store migrate --to <BACKEND> [--dry-run] [--pace-secs <SECS>]issue-store is a sibling top-level command that operates on the backend itself.
Its one subcommand, migrate, moves the project's issues between the
file_system and github backends, matched on the stable Shelbi id so a re-run
never duplicates an already-migrated card. The source is the other live backend:
--to github reads the on-disk board and creates issues; --to file_system reads
GitHub issues and writes markdown files.
| Flag | Type | Default | Description |
|---|---|---|---|
--to <BACKEND> | github | file_system | — | Backend to migrate into (required). |
--dry-run | flag | off | Preview the plan without writing anything to the target. |
--pace-secs <SECS> | float | 7.5 | Seconds between successive creates on a --to github run, to stay under GitHub's secondary content-creation limit (80/min, 500/hr). 0 disables pacing. Ignored for --to file_system. |
After the migration completes, switch the project's issue_tracker.backend to the
new backend. See GitHub Issues backend.
Examples
Triage a new request into the backlog with a dependency on existing work:
shelbi issue add "Wire up changelog page" \
--depends-on docs-write-getting-started-sectionPromote a triaged issue to todo, and the orchestrator picks it up:
shelbi issue move docs-write-cli-reference-pages --to todoReorder ready work so a specific issue is dispatched first:
shelbi issue prio fix-sidebar-clamp --topManually dispatch an explicit workspace (overrides the orchestrator's routing):
shelbi issue start docs-write-changelog-page --workspace deltaRecover a stalled worker without losing its in-flight work, relaunching the pane and resuming the conversation on the same issue:
shelbi issue resume docs-write-changelog-pageSee also
- Workflows — the schema behind
--workflow, what--tois validated against onissue move, and the default workflow's lifecycle (who moves an issue between which statuses). shelbi workflow— list, show, scaffold, and edit the workflow YAMLs issues run under.- Workspaces — the pool model that
assign/startroute into. - Orchestrator — how
--reasontags get parsed by the scheduler. - GitHub Issues backend: how these subcommands behave when the board is GitHub issues rather than local markdown.