xiv stack
The stacked-PR feature lifecycle: init, plan, build, status, triage, preview, push, review, and amend.
xiv stack takes a whole Linear feature — a project, or a parent issue with sub-issues — and builds it as a stack of locally-committed branches: one reviewable branch per issue, each stacked on the one below it. You publish them to GitHub a few PRs at a time, and when a change lands low in the stack, Jujutsu (jj) — the rebase engine underneath the whole stack lifecycle — re-flows it up through every descendant automatically.
Everything is keyed by --feature <slug>, which names the stack map — the source of truth linking each issue to its branch, position, status, and PR. The map lives at <SMITHERS_HOME>/stacks/<feature>.json.
cd /path/to/target-repo
xiv stack init # one-time per repo: colocate jj
xiv stack plan ENG-400 --feature checkout # Linear parent/project -> ordered stack map
xiv stack build --feature checkout # build every entry locally; resumable
xiv stack status --feature checkout # positions, statuses, branches, PRs
xiv stack preview --feature checkout # checkout the tip = try the whole feature
xiv stack push --feature checkout --count 5 # publish the lowest 5 as stacked PRs
xiv stack review --feature checkout # settle open PRs against CI + human comments
xiv stack amend --feature checkout -m "rename the column" --target ENG-401The operating loop
You don't have to memorize the sequence — xiv stack triage tells you the next action every time:
- Run
xiv stack triage --feature <slug> --json. - Read the
actionfield:plan→ runplan;build→ runbuild(a crashed run also showsbuild— re-running resumes);push→ runpush;wait→ all published, nothing to do until humans review and merge;done→ every entry merged. - Run the matching command, then go back to step 1.
xiv how-to prints the authoritative runbook for this loop, and the xiv-operator skill automates it for long or overnight builds. See Stack Map & Triage for the state model behind it.
xiv stack init
One-time per repo: switch on jj in the current repo.
xiv stack initRuns jj git init --colocate, creating .jj/ next to .git/. Reversible with rm -rf .jj; GitHub, CI, and reviewers only ever see a normal git repo. Requires jj on PATH (brew install jj).
It refuses, with a specific error, when: jj isn't installed; the current directory isn't a git repo (never run it in a parent directory holding multiple repos); or a stray jj workspace in a parent directory shadows this repo. Already-colocated repos are reported as ready. For multi-repo features, run it in each repo before building.
xiv stack plan
Plan a stack: fetch a Linear project or parent issue and order its issues into a stack map — or persist a resolved plan file.
xiv stack plan <source> --feature <slug> [--base <branch>] [--repo key=path]... [--skip-acceptance-review]
xiv stack plan --feature <slug> --plan <file> [--repo key=path]...
# examples
xiv stack plan ENG-400 --feature checkout
xiv stack plan PROJ-42 --feature payments \
--repo api=/code/api --repo ledger=/code/ledger-rs
xiv stack plan --feature payments --plan /tmp/payments-plan.json --repo api=/code/apisource is a Linear project ID or a parent issue key whose sub-issues become the stack. It's required unless you pass --plan.
| Flag | Default | What it does |
|---|---|---|
--feature <slug> | required | Names the stack map file and identifies the stack across commands. |
--base <branch> | main | Trunk branch every repo's substack is based on. |
--repo key=path | current directory | Assign a repo (repeatable) for multi-repo features. Omit for a single-repo stack rooted here. |
--plan <file> | — | Persist a resolved plan file (from the stack-plan skill) instead of running the planner. Deterministic — no agent runs. |
--skip-acceptance-review | off | Record in the map that every build of this feature skips the local acceptance-review step (the feature-wide default). |
Without --plan, it launches the stack-plan workflow, which reads Linear and writes the ordered map. This step deliberately runs the most capable planning model regardless of tier — the ordering it writes is inherited by every later command, so a wrong order is a rebuild (see Model Tiers).
For interactive planning — auto-assign the obvious issues, confirm the unclear ones, exclude non-code work like "set GCP secrets" — use the stack-plan skill, which writes the resolved plan and persists it via --plan. Excluded issues are recorded in the map and shown by status, never built, never lost.
plan runs from anywhere — jj readiness is checked per repo at build/amend/push time, not here.
xiv stack build
Build entries locally, bottom to top. Resumable.
xiv stack build --feature <slug> [--repo <key> | --all-repos] [--detach] \
[--skip-acceptance-review] [--max-iterations <n>]| Flag | Default | What it does |
|---|---|---|
--feature <slug> | required | Which stack to build. |
--repo <key> | sole repo | Build only this repo's substack (a key from the stack map). Required on multi-repo stacks unless --all-repos. |
--all-repos | off | Fan out across every repo in the stack — one pinned run per repo, in parallel (each run is detached). |
--detach | off | Start the run in the background (smithers up -d) and return immediately, so you can poll with xiv stack triage. |
--skip-acceptance-review | off | Build without the local review step, this run only. ORs with the map's plan-time default — it can force skipping on, never re-enable review a plan opted out of. Validation still gates every entry. |
--max-iterations <n> | 3 | Forwarded to every entry's implement subflow: passes allowed per issue. Clamped to 1–10. |
Each entry runs through the same implement loop as xiv implement — plan, implement, validate, locally review — on a branch stacked on the previous entry's branch (or the trunk, for the first). Everything stays local; nothing is pushed.
Building is resumable: Smithers persists each completed step, so a crash mid-stack resumes by skipping already-built entries. Re-running build is the standard recovery — don't restart from scratch, and don't push to "fix" a build problem. For long or overnight builds, hand supervision to the xiv-operator skill rather than watching it yourself.
Findings the local review raised that the loop shipped anyway are recorded on the entry at build time — they become the "Known gaps" section of the PR description at push.
xiv stack status
Print the stack map, grouped by repo: positions, statuses, branches, and PRs.
xiv stack status --feature <slug>Each entry shows its position, status (pending, implementing, implemented, pushed, pr-open, merged), issue key, branch, and PR number if one exists. Each repo section ends with its tip — the branch to git checkout to see that repo's full substack. Excluded issues are listed at the bottom with their reasons.
xiv stack triage
Print a compact, structured next-action report for operating the stack. Start here whenever you're unsure what to do.
xiv stack triage --feature <slug> [--json]| Flag | Default | What it does |
|---|---|---|
--json | off | Emit the report as JSON for an operator agent to parse. |
The report is derived deterministically from the stack map alone — the same map always produces the same report — so a low-cost operator agent can match action against a fixed decision table. It contains:
action— the overall next step:plan,build,push,wait, ordone(most urgent across repos wins).- A per-repo breakdown: phase (
building,built-unpublished,has-stale,publishing,complete), the entry currently in flight, and any stale branches (open PRs an amend re-flowed that need re-syncing — those surface aspush). - A
hintwith the exact command to run next. - A dump of active Smithers runs (
smithers ps --all), so you can tell "needs building" apart from "already building".
xiv stack preview
Check out every repo at its stack tip to preview the whole feature locally.
xiv stack preview --feature <slug>Runs git checkout <tip> in each repo of the stack (skipping repos not built yet; errors if nothing is built at all). For a multi-repo feature this puts every service at feature-complete simultaneously — the way to integration-test the feature before publishing.
xiv stack push
Publish the next N built entries as stacked PRs, and re-sync re-flowed open PRs.
xiv stack push --feature <slug> [--count <n>] [--repo <key> | --all-repos] [--no-draft]| Flag | Default | What it does |
|---|---|---|
--count <n> | 5 | How many built-but-unpublished entries to publish this batch. |
--repo <key> | sole repo | Publish only this repo's substack. |
--all-repos | off | Publish across every repo in the stack. |
--draft | on | Open each PR as a draft. Pass --no-draft to open ready-for-review PRs. |
push is the only stack command that touches GitHub. For each entry it pushes the branch, opens a PR against the entry below it (or the trunk), and force-pushes any already-open PR that a later amend re-flowed (the "stale" branches triage reports).
Each PR gets a real description: an agent reads that entry's own diff (base...branch, exactly its contribution) and writes Summary, Test Plan, and Known gaps — the last fed by the unfixed review findings recorded at build time. The issue link and stack position are appended from the map, not written by the agent, so they're always correct. A failed description never blocks the PR; it opens with the plain footer.
xiv stack review
Settle the open stacked PRs against CI and human review comments. Never merges.
xiv stack review --feature <slug> [--repo <key> | --all-repos] [--detach]| Flag | Default | What it does |
|---|---|---|
--repo <key> | sole repo | Settle only this repo's substack. |
--all-repos | off | Fan out one pinned run per repo, in parallel (each detached). |
--detach | off | Run in the background. |
For each open stacked PR it reads the CI checks and human review comments, fixes what they raise in the branch that owns the code via jj — so the fix cascades up through the descendants — and pushes. Code review already happened locally during build, so nothing here waits on a review bot; this is the stacked-PR counterpart of xiv pr refine.
xiv stack amend
Apply a change to one stack entry and re-flow it through its repo's descendants.
xiv stack amend --feature <slug> -m "<change>" [--target <issue|branch>] [--repo <key>]
# examples
xiv stack amend --feature checkout -m "rename the column to created_at"
xiv stack amend --feature payments -m "guard the null case" --target ENG-402| Flag | Default | What it does |
|---|---|---|
-m, --message <text> | required | The change to apply to the located stack entry. |
--target <issue|branch> | located from the message | Explicit entry to amend (issue key or branch name). |
--repo <key> | inferred | The repo whose substack is amended. Resolved from --target's entry when omitted; required on a multi-repo stack when neither locates it. |
The workflow locates the entry (from --target, or from the message itself), applies the change there, lets jj auto-rebase every descendant branch, and re-validates. It's local-only — the re-flowed branches don't reach GitHub until the next push, which re-syncs any affected open PRs.
The jj rule: read with git, edit through the stack
The stacking is powered by jj colocated with git — underneath it's a normal git repo, and reading it any way you like (git checkout, git diff, git log, your IDE) is fine and encouraged. But:
- Edit and restack only through
xiv stack amend(or jj directly, if you know what you're doing). - Never hand-edit a pushed stacked branch with git — no
git rebase,git commit --amend, orgit push --forceon a stack branch. That bypasses jj's cascade and desyncs the stack map from the actual branches. - A jj rebase/restack conflict during build or amend is a stop-and-escalate situation; the xiv-operator skill owns the playbook.
Guardrails
- Never merge a stacked PR — merging is always the human's call.
- Prefer resuming (
buildagain) over restarting; prefertriageover guessing. pushandamendchange real state — run them deliberately, not speculatively.
Related
- Backing workflows: Stack Workflows (stack-plan, stack-build, stack-push, stack-review, stack-amend)
- The state model: Stack Map & Triage
- Planning interactively: stack-plan skill · Supervising builds: xiv-operator skill