Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

status

jjpr status (and bare jjpr) shows the stack containing your working copy and its PR/MR state, down to your default branch — including a coworker’s branch you’ve stacked on. It’s read-only. It fetches the latest state but doesn’t push or modify anything.

jjpr                                  # current stack (inferred from working copy)
jjpr status                           # same
jjpr st                               # same, using the short alias
jjpr status profile                   # scope to the stack containing 'profile'
jjpr status --all                     # show every local stack

st is a short alias for status, matching jj’s own jj st.

The default scope matches submit, merge, and watch: the stack inferred from the working copy. Pass a bookmark to scope to a specific stack, or --all to see every local stack at once.

Flags

FlagEffect
--allShow every local stack instead of only the current one. Mutually exclusive with a positional bookmark.
--no-fetchSkip git fetch before reporting

Output

Each segment shows its bookmark, a direct link to the PR, and the PR’s mergeability, CI status, and review state:

  auth (1 change, PR open, push up to date)
    https://github.com/o/r/pull/42
    ✓ mergeable  ✓ CI passing  ✓ 1 approval
  profile (2 changes, PR open, push needs updating)
    https://github.com/o/r/pull/43
    ✗ conflicts  ✗ CI failing  ⚠ changes requested  ✗ 0 approvals

Draft PRs show just the link. Their CI and review detail stays hidden until the PR is marked ready:

  payments (1 change, PR draft, push up to date)
    https://github.com/o/r/pull/44

A segment you haven’t submitted yet has no PR:

  cleanup (2 changes, not pushed yet)
    no PR yet — run `jjpr submit`

With --all, multiple independent stacks are labeled:

Stack 1:
  auth (1 change, PR open, push up to date)
    https://github.com/o/r/pull/42
    ✓ mergeable  ✓ CI passing  ✓ 1 approval
  profile (2 changes, PR open, push up to date)
    https://github.com/o/r/pull/43
    ✓ mergeable  ✓ CI passing  ✓ 1 approval

Stack 2:
  payments (1 change, PR draft, push up to date)
    https://github.com/o/r/pull/44
  checkout (3 changes, PR open, push needs updating)
    https://github.com/o/r/pull/45
    ✗ CI pending  ✗ 0 approvals

Approvals at risk from a squash landing

When the base branch resets approvals on push (GitHub’s “dismiss stale reviews”, GitLab’s “reset approvals on push”, Forgejo’s “dismiss stale approvals”) and one of your approved PRs is stacked on top of another open PR, a squash landing of the lower PR force-pushes a fresh commit onto yours and drops its approvals. status warns ahead of time:

  api (2 changes, PR open, push up to date)
    https://github.com/o/r/pull/124
    ✓ mergeable  ✓ CI passing  ✓ 2 approvals
    ⚠ a squash-landing of #123 would dismiss 2 approvals

The note is conditional on how the lower PR lands: a merge-commit landing keeps your approval, because jjpr skips the needless rebase in that case (see merge).

PRs in a GitHub native stack

A PR registered as a member of a GitHub native stack cannot be merged by jjpr, because GitHub refuses the merge endpoint for stacked PRs. Status flags those, so the mergeability line above it is not read as an invitation to run jjpr merge:

  auth (1 change, PR open, push up to date)
    https://github.com/owner/repo/pull/345
    ✓ mergeable  ✗ 0 approvals
    ⚠ in native stack #348 (1 of 3), so jjpr cannot merge it; `gh stack merge 345` lands it

The position is 1-based from the bottom of the stack, and the note says what the command would land, because merging a stacked PR lands every PR below it too. At position 1 that is one PR; at position 3 the note reads lands it and the 2 below.

This reads the stack membership GitHub embeds in the PR data jjpr already fetches, so it costs no extra request. See GitHub native stacks for the ways to land such a stack, and Reshaping a native stack for what submit can and cannot do with one.

Divergent changes

When two commits carry the same change ID — a divergent change, which jj marks ?? — the segment carrying it is flagged:

  feat-a (1 change, #41 open)
  feat-b (1 change, #42 open)  ?? divergent

Status always shows the stack, even when it is in this state; it is where you look to find out which segment to fix. jjpr submit, jjpr watch and jjpr merge all refuse while a divergent change is in the stack — see submit.

Resolve with jj abandon <commit> to drop one copy, or jj duplicate to give it its own change ID.

Branches that aren’t yours

status shows the whole stack down to your default branch, including a coworker’s branch you’ve stacked on. Those segments are attributed to their author, show the base’s mergeability, and are marked so you know submit, watch, and merge leave them alone (only status shows them; the mutating commands act only on your own bookmarks):

  auth-ui (1 change, PR draft, push up to date)
    https://github.com/o/r/pull/205
  auth-api (2 changes, PR open, push needs updating)
    https://github.com/o/r/pull/204
    ✓ mergeable  ✓ CI passing  ✓ 1 approval
  platform-refactor (3 changes, PR open by @dana, jjpr won't submit or merge it)
    https://github.com/o/r/pull/198
    ✓ mergeable

The rich segment above appears when you have a local bookmark at the coworker’s commit. If instead you rebased straight onto their remote branch (jj rebase -d their-branch@origin, no local bookmark), it shows up as an attributed base footer:

  my-feature (2 changes, PR open, push up to date)
    https://github.com/o/r/pull/210
  (based on their-branch — PR open by @dana)
    https://github.com/o/r/pull/198

When a branch has already merged, its segment says so and — if the remote branch is gone but the local bookmark lingers — points you at the cleanup:

  cycle-events (1 change, PR merged by @dana)
    https://github.com/o/r/pull/512
    ✓ merged on 2026-04-20; remote branch deleted, local bookmark is stale
       clean up: jj bookmark forget cycle-events

If the stack you’re on is entirely someone else’s — you’re sitting on their branch with nothing of your own yet — status recognizes that instead of pretending there’s a stack to act on:

On cycle-events — someone else's merged branch:

  cycle-events (1 change, PR merged by @dana)
    https://github.com/o/r/pull/512
    ✓ merged on 2026-04-20; remote branch deleted, local bookmark is stale
       clean up: jj bookmark forget cycle-events

Nothing of yours to submit here.

Glossary

FieldMeaning
push up to date / push needs updating / not pushed yetWhether your local commits are reflected on the pushed PR branch: matching, pushed but since changed, or never pushed
PR link (https://.../pull/42)Direct link to the PR or MR on the forge
PR open / PR draftThe PR’s state on the forge
no PR yetThis segment has not been submitted; run jjpr submit
PR open by @user / PR merged by @userSomeone else’s PR — the author is named. Only status shows these; the mutating commands ignore them
jjpr won't submit or merge itThis segment is someone else’s; submit/watch/merge leave it alone
✓ merged … local bookmark is staleThe PR merged and its remote branch is gone, but a local bookmark remains; the line below shows how to remove it
✓ mergeable / ✗ conflictsWhether the forge reports the PR can merge without conflicts
✓ CI passing / ✗ CI pending / ✗ CI failingAggregate check status for the head commit
✓ N approvals / ✗ 0 approvalsCount of approving reviews (the required threshold comes from config)
⚠ changes requestedAt least one reviewer has requested changes
⚠ a squash-landing of #N would dismiss …A lower PR’s squash landing would force-push this approved PR and drop its approvals
⚠ in native stack #N …This PR belongs to a GitHub native stack, which jjpr cannot merge; the note names the command that can and what it would land