Usage
jj-stack [--help] [--repository ] [--config ] [--config-file ] [--debug] [--color ] [--time-output] [--version] [ ...]Create and update stacked GitHub pull requests from your jj changes.
Edit and rearrange changes with jj, then run jj-stack submit to update their PRs. Running jj-stack with no command shows the current stack and its PR status.
Use jj-stack merge when the PRs at the bottom are ready; it waits for GitHub and then updates your local stack. Run jj-stack sync only after a merge it did not wait for.
Core commands
submit- Create or update PRs for a jj stackAliases:
sub view- Check the PR status of one or more jj stacksAliases:
status,st,v list- List the stacks jj-stack is tracking in this repoAliases:
ls merge- Merge pull requests at the bottom of a stack
sync- Update a local stack after GitHub merges or rebases it
Support commands
unstack- Remove a GitHub stack without closing its pull requests
cleanup- Remove unused PR branches, stack overview comments, and saved links
checkout- Check out an existing stack of pull requests
doctor- Check repo setup and GitHub connectivity
in-use- Check whether this repo uses jj-stack
Advanced repair
relink- Reconnect a change to its pull request
Configuration
completion- Print shell completion setup for bash, zsh, or fish
Help
help- Show top-level help, or help for one command
Global options
-h, --help- Show help
--repository REPO- Workspace path to operate on; defaults to the current directory
--config NAME=VALUE- Set a
jjconfig value for this command, such asui.color=always; repeat for several values --config-file PATH- Additional
jjconfig file to load; repeat for several --debug- Enable debug logging
--color WHEN- When to colorize output; possible values:
always,never,debug,auto --time-output- Prefix each output line with elapsed seconds
--version- Show the
jj-stackversion and exit
Commands
Core commands
submit
Aliases: sub
jj-stack submit [--base ] [--dry-run] [--describe | --describe-with ] [--edit | --resume-edit ] [--draft | --open] [--label ] [--reviewers ] [--team-reviewers ] [--re-request] []Create or update GitHub pull requests for the selected stack of changes.
Push the selected changes and create or update one PR per change, in local parent order. Existing PRs stay linked to their changes. Resolve any conflicts before submitting.
The --label, --reviewers, and --team-reviewers flags accept comma-separated values and may be repeated. When passed, they override the corresponding configured defaults for this run.
Common examples:
jj-stack submit --dry-runpreviews the current stack.jj-stack submitcreates or refreshes its pull requests.jj-stack submitselects another stack explicitly.jj-stack submit --basesubmits only the changes after an open parent pull request. Repeat--basewhenever you refresh the child stack.
Positional arguments
revset- Stack head to submit; defaults to
@when the working-copy change is described and nonempty, otherwise@-
Options
--base REVSET- Submit changes above this submitted ancestor, using its PR branch as the base; repeat this option on later submits of the dependent stack
--dry-run- Preview submission without pushing branches or changing pull requests
--describe TARGET=FILE- Read a PR body from
FILE;TARGETis a change ID, orstackfor an overview comment on the head PR --describe-with HELPER- Generate pull request titles, bodies, and the stack overview with
HELPER --edit- Open planned pull request titles, bodies, and draft states in your editor before submitting
--resume-edit FILE- Reopen a saved editor file instead of generating a new one
--draft- Create new PRs as drafts; use
--draft=to make existing PRs drafts too --open- Mark submitted PRs ready for review, including existing drafts
--label LABELS- Add labels to the selected PRs; comma-separated or repeat the option
--reviewers USERS- Request reviews by GitHub username; comma-separated or repeat the option
--team-reviewers TEAMS- Request reviews by team slug; comma-separated or repeat the option
--re-request- Request another review from users who last approved or requested changes on an existing pull request
Supplying descriptions
A pull request title comes from a change's subject line, and its body from the rest of the description. When a description has no body, jj-stack uses the repo's pull request template (.github/PULL_REQUEST_TEMPLATE.md, PULL_REQUEST_TEMPLATE.md, or docs/PULL_REQUEST_TEMPLATE.md), or repeats the subject line if no template exists.
Later submits refresh the title and body from the change description, provided both still match the defaults for the last submitted version. Editing either field on GitHub preserves both.
Use --describe to read a PR body from a Markdown file, or --describe to add an overview comment to the head PR of a stack with several changes. Relative paths are resolved from the directory where you run jj-stack.
Use --edit to edit the planned titles, bodies, and draft states before anything is pushed. Save and close the editor to continue. Invalid text or an editor error stops submission before any branches or PRs change. If submission fails, the editor file is kept. Retry the same command with --resume-edit instead of --edit. The file must still name exactly the selected changes.
The editor comes from jj's ui.editor, then $VISUAL, then $EDITOR. Neither --edit nor --resume-edit can be combined with --describe-with.
With --describe-with , jj-stack runs helper --pr once per PR and helper --stack once for a stack with several changes. Each call must print a JSON object with string title and body fields.
view
Aliases: status, st, v
jj-stack view [--pull-request ] [--json] [--verbose] [ ...]Compare the local and GitHub state of the selected jj stacks.
Show submitted and unsubmitted changes with their current PR state. Long stacks are summarized; use --verbose to show every change, plus unresolved review threads and failed or pending checks with links.
PR state comes from GitHub and stack order comes from local history. This command does not fetch. Run jj git fetch first if you need to update local trunk(). Pass several revsets or repeat --pull-request to inspect several stacks in one run.
Common examples:
jj-stack viewinspects the stack ending at@when the working-copy change is described and nonempty, otherwise@-.jj-stack view --pull-requestfinds the full local stack containing that PR.jj-stack viewfinds the full local stack containing that change.
In terminals with hyperlink support, click a PR label to open it on GitHub. The PR in the "Submitted stack" heading links to the topmost submitted PR.
Positional arguments
revset- Select a stack by its head revset or by any change ID it contains. Combine either with
--pull-request; defaults to the current stack
Options
-p, --pull-request PR- Inspect the full stack containing this PR number or URL; repeat to inspect several stacks
--json- Output stack status as JSON
-v, --verbose- Show every change, plus unresolved review threads and check results with links
list
Aliases: ls
jj-stack list [--json]List the stacks jj-stack is tracking in this local repo.
Each row shows the head change ID, stack size, PR state, and head description. Stacks without any submitted changes and stacks that exist only on GitHub are not listed.
Orphaned PRs are listed separately: their local changes are no longer in any stack. The orphan rows show saved PR links without checking their current GitHub state. To close them and remove their unused branches, stack overview comments, and saved links, use jj-stack cleanup --pull-request --close.
For local stacks, PR state comes from GitHub and stack order comes from local history. This command does not fetch. Run jj git fetch first if you need to update local trunk().
In terminals with hyperlink support, click the PR label in a row to open it on GitHub. A count such as 5 PRs links to the topmost PR in that stack.
Options
--json- Output tracked stacks and orphaned PRs as JSON
merge
jj-stack merge [--dry-run] [--no-wait] [--pull-request ] [--method ] []Ask GitHub to merge pull requests at the bottom of a stack.
Starting at the bottom of the stack, jj-stack selects consecutive open, non-draft pull requests. Each must still match the commit that was last submitted; GitHub decides whether reviews, checks, conflicts, and repo rules allow the merge.
The command waits for GitHub to finish, including through a merge queue. It then fetches trunk, removes the merged changes from the local stack, rebases any remaining changes onto the updated trunk, and updates their existing pull requests.
Use --no-wait to return once GitHub accepts the request, or press Ctrl-C to stop waiting; neither cancels the request. After GitHub finishes, run jj-stack sync .
For a direct merge, one that GitHub performs without a merge queue, --method chooses among the merge methods the repo allows. Without it, the command uses jj-stack.merge_method from your jj config, or the repo's only allowed method, and otherwise prefers rebase, then squash, then a merge commit. If several methods are allowed and the stack contains signed commits, choose one explicitly: merging can discard signatures. A merge queue chooses its own method and ignores --method.
Common examples:
jj-stack merge --dry-runpreviews the merge without changing GitHub.jj-stack mergeasks GitHub to merge the ready PRs at the bottom of the stack.jj-stack merge --pull-request --methodselects PR 123 as the last PR to merge and chooses the merge method explicitly.
Positional arguments
revset- Stack head to merge; defaults to
@when the working-copy change is described and nonempty, otherwise@-. To merge only the bottom portion, use--pull-requestinstead
Options
--dry-run- Preview the merge without asking GitHub to merge anything
--no-wait- Return after GitHub accepts the merge request; run jj-stack sync after it merges
-p, --pull-request PR- Merge this PR and all PRs below it; the PRs above it stay open and are updated after the merge
--method METHOD- GitHub merge method for a direct merge:
merge,rebase, orsquash
sync
jj-stack sync [--dry-run] [--pull-request ] [--all] []Update a local stack after GitHub merges or rebases its pull requests.
jj-stack sync fetches trunk, removes obsolete local copies of merged changes, rebases the remaining changes, updates their existing pull requests, and cleans up unused PR branches, stack overview comments, and saved links. It never creates pull requests.
Run it after GitHub's Rebase stack action, or after a merge that jj-stack merge did not wait for finishes on GitHub; when merge waits, it performs this update itself. While a selected PR is still queued, sync leaves the stack unchanged.
After a Rebase stack action, sync checks that the PR order and contents match, rebases your original changes, and updates the PR branches with commits that retain their jj change IDs.
Sync stops if it would discard local edits or cannot determine which local changes and PRs to update. The error explains what needs attention. If a rebase produces conflicts, the local rebase stays in place but the affected PRs are not updated. Resolve the conflicts with jj, then run jj-stack submit .
jj-stack sync --all updates every local stack affected by a completed merge and cleans up merged PRs whose local changes are gone. A blocked stack does not prevent it from syncing independent stacks. It does not handle Rebase stack actions; use jj-stack sync for those.
Use plain jj rebase when trunk merely advanced and GitHub did not rewrite the commits.
Positional arguments
revset- Stack head to sync; defaults to
@when the working-copy change is described and nonempty, otherwise@-; cannot be combined with--pull-request
Options
--dry-run- Preview the sync without changing your local stack, PRs, branches, or saved links
-p, --pull-request PR- Sync the complete local stack containing this pull request number or URL
-a, --all- Sync every stack affected by a completed merge, including merged PRs whose local changes are gone; cannot be combined with a selector
Support commands
unstack
jj-stack unstack [--dry-run] [--local] [--pull-request ] [--stack ] []Remove a GitHub stack without closing its pull requests.
The PRs keep their base branches and dependencies. Local changes and saved pull request links stay in place. Submitting the same local stack again recreates the GitHub stack.
With a revset or pull request, unstack uses the matching local stack. Use --stack when the GitHub stack no longer corresponds to a single local stack.
--local only forgets jj-stack's saved pull request links. It does not change GitHub, close pull requests, delete PR branches, or modify local changes.
Positional arguments
revset- Stack head to unstack; defaults to
@when the working-copy change is described and nonempty, otherwise@-; cannot be combined with--pull-requestor--stack
Options
--dry-run- Preview separating the GitHub stack or forgetting saved links locally
--local- Only forget saved pull request links; do not change GitHub
-p, --pull-request PR- Select the local stack linked to this pull request number or URL
--stack NUMBER- Separate this GitHub stack even when no matching local stack is available
cleanup
jj-stack cleanup [--dry-run] [--close] [--pull-request ] []Clean up closed or merged pull requests.
This removes unused PR branches, stack overview comments, and saved pull request links. It keeps your local changes and other comments on GitHub. For merged PRs, run jj-stack sync first to update the local stack.
With no selector, it checks the whole repo. A revset limits cleanup to one local stack; --pull-request selects one tracked pull request, and --pull-request selects every tracked pull request whose local change is gone. Add --close to a --pull-request selection to retarget those open pull requests to trunk and close them before cleanup. To close a whole stack, first run jj-stack unstack, then close each PR from the top of the stack downward.
Without --close, open pull requests are left alone.
Cleanup keeps a branch while another PR still uses it as its base (an open PR, or a closed PR that GitHub could still reopen), or while an unmerged PR in a GitHub stack needs it. The message names the PR or stack to update before retrying cleanup.
Positional arguments
revset- Revset selecting the stack to clean up; omit it to check every tracked pull request; cannot be combined with
--pull-request
Options
--dry-run- Preview cleanup without closing PRs or removing anything
--close- Close selected open pull requests before cleanup; requires
--pull-request -p, --pull-request PR- Clean up this tracked pull request, or use
orphansfor every tracked pull request whose local change is gone
checkout
jj-stack checkout [--pull-request | --revset | --pick]Check out an existing stack of pull requests submitted with jj-stack.
Use this command to continue work you submitted from another machine or checkout. It fetches any missing commits, saves their pull request links, and runs jj edit on the selected change. If a PR's version differs from your local version, checkout keeps both and explains how to resolve the difference.
Use --pull-request to bring in a PR and the PRs below it. Select the top PR to check out the whole stack. Use --pick to choose from local and GitHub stacks in an interactive list. Use --revset to edit the head of a stack this checkout already tracks; it confirms that every change has a saved pull request link and does not contact GitHub.
The PRs and their head branches must belong to the repo selected by your Git remote. PR branches must use jj-stack's branch naming scheme with this checkout's configured prefix, normally jj-stack/. If the original checkout used a custom prefix, set the same jj-stack.branch_prefix here first. PRs with head branches in another repository, such as a contributor's fork, are not supported.
Checkout does not rebase changes or modify GitHub. To start a new change on top, run jj new afterward.
In terminals with hyperlink support, the PR beside "Top" in each GitHub stack's --pick entry is a clickable link. Open it to inspect that stack on GitHub before choosing an entry.
Options
-p, --pull-request PR- Pull request to check out, by number or URL
--revset REVSET- Edit the head of a locally tracked stack without contacting GitHub; defaults to
@when the working-copy change is described and nonempty, otherwise@- --pick- Interactively choose a local or GitHub stack to check out
doctor
jj-stack doctor [--fix]Check repo setup and GitHub access.
Checks the Git remote, authentication, GitHub access, your permission to push to the repo, stacked pull request support, and GitHub's default branch. It also reports PR bookmarks imported by a fetch and leftovers from an interrupted checkout or sync.
Run jj-stack doctor --fix to configure fetches to skip PR branches, forget untracked PR bookmarks imported by a fetch, and remove checkout or sync leftovers. These repairs affect only this local repo.
The command exits 1 if a check fails and 0 otherwise. Warnings and problems repaired by --fix do not count as failures. The report includes recovery commands where available.
Options
--fix- Apply safe local repairs instead of only reporting problems
in-use
jj-stack in-useCheck whether this repo contains valid jj-stack tracking data.
Use this in scripts to check whether jj-stack has been set up in this repo. It exits silently with 0 when valid tracking data exists, or 1 when there is none. Repo or tracking errors produce a diagnostic and exit 11. The command does not contact GitHub or change local state.
Advanced repair
relink
jj-stack relink [--replace-remote] Reconnect a change to its pull request.
Use jj-stack relink in these situations:
- You ran
jj-stack unstack --localand now want to use those PRs again. That command removes the local links between changes and PRs, but leaves the PRs open on GitHub. Runjj-stack relinkfor each PR to restore its link. The same repair applies if you deleted jj-stack's local tracking file. - Someone pushed another version to your PR branch, and you want to replace it with your local version.
jj-stack submitstops to avoid overwriting their work. After checking the changes on GitHub, runjj-stack relink --replace-remoteso the nextjj-stack submitcan overwrite that version. To keep their work instead, bring it into your repo withjj-stack checkout --pull-request.
After relinking, run jj-stack submit to update the stack's PRs. Use the change ID for each PR when relinking, and the top change's ID when submitting the stack. The existing PRs keep their numbers and discussions.
jj-stack relink itself only updates local tracking. jj-stack submit changes GitHub. jj-stack relink reconnects an open PR in this repo to the change it was created from. It cannot transfer a PR to a different change ID, even with --replace-remote.
Positional arguments
PR- Pull request number or URL
REVSET- Local change to link to the pull request
Options
--replace-remote- Link even if the PR branch has changed unexpectedly; the next
jj-stack submitoverwrites it with the local change
Configuration
completion
jj-stack completion [--jj-alias ] Print a shell completion script. Load it from your shell's startup file after any existing completion setup. For zsh, run it after compinit.
If you use a jj stack alias, include --jj-alias to complete commands and options after both jj-stack and jj stack. For example:
- Bash:
eval "$(jj-stack completion bash --jj-alias - Zsh:
eval "$(jj-stack completion zsh --jj-alias - Fish:
jj-stack completion fish --jj-alias | source
Omit --jj-alias if you only use the standalone jj-stack command.
Positional arguments
shell- Shell to generate completion support for
Options
--jj-alias NAME- Also complete an existing
jjalias that runsjj-stack, such asstack
Help
help
jj-stack help [--all] []Show top-level help or the detailed help for one command. Use --all to show every command and global option in top-level help.
Positional arguments
command- Command to describe
Options
--all- Show every command and global option in top-level help