# shelbi issue

Manage the project's Kanban issue board — add, list, move, assign, start, and resume issues from the CLI.

```text
shelbi 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.

<Callout type="note" title="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`.

</Callout>

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

```text
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. When omitted, 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). |

## list

```text
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

```text
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

```text
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

```text
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 (or a custom status with no backing column) errors with the
list of reachable statuses, and the issue stays put. Matching is case- and
punctuation-insensitive (`InProgress` matches `in_progress`); an issue pinned to a
workflow with no YAML on disk falls back to the built-in `default`, so
projects keep moving while the workflows directory is empty.

| 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. |

## assign

```text
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.

| Flag | Type | Default | Description |
| --- | --- | --- | --- |
| `--to <WORKSPACE>` | string | — | Workspace name (required). |

## unassign

```text
shelbi issue unassign <ID>
```

Clear an issue's `assigned_to` field. The issue stays in its current column.

## start

```text
shelbi issue start [OPTIONS] <ID>
```

Launch the assigned workspace on this issue. Three things happen in one shot:

1. The workspace's worktree is checked out to the issue's branch (generated
   from workflow config, project config, or your GitHub username when unset).
2. Any existing pane for that workspace is killed. Context is wiped clean.
3. 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`. |

## resume

```text
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 tmux session, a wedged pane, 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). `start` wipes
the agent's context (kills the pane and re-checks-out a clean branch): right
for a fresh dispatch, wrong for recovery. `resume` instead preserves the
in-flight state:

1. 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.)
2. The runner pane 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 pane comes up.
3. For a **claude** runner the pane 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`. |

## prio

```text
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. |

## edit

```text
shelbi issue edit <ID> [OPTIONS]
```

With no flags, opens the issue's markdown file in `$EDITOR` for free-form
edits. 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. |
| `--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`.

```bash
# 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.
EOF
```

## rm

```text
shelbi issue rm <ID>
```

Delete an issue file.

<Callout type="warning" title="Irreversible">

`shelbi issue rm` deletes the issue's markdown file outright. There's no
trash and no undo. To take a card off the board without destroying its
history, move it back to `backlog` instead.

</Callout>

## Examples

Triage a new request into the backlog with a dependency on existing work:

```bash
shelbi issue add "Wire up changelog page" \
    --depends-on docs-write-getting-started-section
```

Promote a triaged issue to `todo`, and the orchestrator picks it up:

```bash
shelbi issue move docs-write-cli-reference-pages --to todo
```

Reorder ready work so a specific issue is dispatched first:

```bash
shelbi issue prio fix-sidebar-clamp --top
```

Manually dispatch an explicit workspace (overrides the orchestrator's routing):

```bash
shelbi issue start docs-write-changelog-page --workspace delta
```

Recover a stalled worker without losing its in-flight work, relaunching the pane
and resuming the conversation on the same issue:

```bash
shelbi issue resume docs-write-changelog-page
```

## See also

- [Workflows](/docs/guides/getting-started/workflows) — the schema behind `--workflow`,
  what `--to` is validated against on `issue move`, and the default
  workflow's lifecycle (who moves an issue between which statuses).
- [`shelbi workflow`](/docs/cli/workflow) — list, show, scaffold, and
  edit the workflow YAMLs issues run under.
- [Workspaces](/docs/concepts/workspaces) — the pool model that `assign` /
  `start` route into.
- [Orchestrator](/docs/concepts/orchestrator) — how `--reason` tags get
  parsed by the scheduler.
