Status
Status values
Every issue moves through a simple lifecycle. Active statuses track work in progress; terminal statuses close the issue.
BACKLOG → PLANNED → DOING → DONE
↘ BLOCKED ↗ ↗
any active → CANCELED
any active → DUPLICATE
Active statuses:
| Status | Meaning |
|---|---|
BACKLOG | Captured but not yet spec'd or prioritized |
PLANNED | Spec'd and ready for work |
DOING | Actively in progress |
BLOCKED | Stuck on something |
Terminal statuses (issue is closed):
| Status | Meaning |
|---|---|
DONE | Shipped — counts toward velocity and burndown |
CANCELED | Won't fix, no longer relevant, or descoped |
DUPLICATE | Already covered by another issue |
Any active status can transition to any terminal status. Any terminal status can transition back to an active status (reopen).
Transition commands
xpo planned <id> # → PLANNED
xpo start <id> # → DOING (creates worktree + branch)
xpo blocked <id> # → BLOCKED
xpo done <id> # → DONE
Or set status directly:
xpo update <id> --status PLANNED
xpo update <id> --status CANCELED
xpo update <id> --status DUPLICATE
Worktrees
xpo start sets the status to DOING and creates a git worktree at .xpo/worktrees/<branch>/ with a new branch named after the issue. The primary checkout stays on main, so multiple agents or developers can work on different issues simultaneously without interfering with each other.
xpo start <id> # creates worktree + branch
xpo start <id> --force # take over (removes existing worktree)
xpo start <id> --no-wt # classic checkout instead of worktree
The worktree path is printed on success and returned by the MCP start tool, so agents can cd into it automatically.
To disable worktrees globally, set worktrees: false in .xpo/config.yaml. You can also configure a setup hook that runs after worktree creation:
worktrees: true
worktree_setup: "make deps" # runs in the new worktree directory
Merging
When the work is done, merge the branch back and close the issue in one step. With worktrees enabled, the merge runs from the hub (primary checkout on main) and the worktree is cleaned up automatically:
xpo merge <id> # squash-merge + close + remove worktree
xpo merge <id> --ff # fast-forward only
xpo merge <id> --keep-branch # keep branch (worktree still removed)
xpo merge <id> --no-wt # classic checkout-based merge
Review the diff before merging:
xpo review <id>
Blocked issues
An issue with blocked_by relationships cannot move to DOING until all blockers reach a terminal status (DONE, CANCELED, or DUPLICATE). See Relationships for details.
Status cascading
Status changes can cascade between parent and child issues through automations — for example, completing all children automatically completes the parent. See Parent & Sub-Issues for details.
In the web board
Drag issues between status columns to transition them. The board view shows issues grouped by status in a Kanban layout.