jjacks
v0.1.4
Published
Sync a jj bookmark stack with GitHub pull requests.
Downloads
648
Readme
jjacks
jjacks is a Jujutsu-backed GitHub stacking tool following a strict mental model of one "bookmark" per Pull Request.
Who's this for?
Why do we need another stacking tool? There's already Graphite and a dozen other GitHub stacking tools. While learning Jujutsu, the amend-only workflow felt underused when working with GitHub. In jjacks, if you're on a bookmark you'll see the diff at all times.
Install
jjacks is packaged as a Node CLI. Install it globally:
npm install --global jjacksFor local development from a checkout:
npm install
npm run build
npm linkShell Completions
jjacks can generate shell completion scripts:
source <(jjacks --completions zsh)
source <(jjacks --completions bash)
jjacks --completions fish | sourceRequirements:
- Node.js 22 or newer
gitjj- GitHub CLI
gh gh auth logincompleted for the target GitHub host
Setup
Use a Git repo that has been initialized for jj:
jj git init --colocatejjacks requires bookmark movement to be enabled:
jj config set --user advance-bookmarks.enabled trueStack breadcrumbs are written as PR comments by default. To write them into PR descriptions instead:
jj config set --repo jjacks.stack_comments.location descriptionNew pull requests are created with an empty description by default. To use the repo's default pull request template when jjacks sync creates PRs:
jj config set --repo jjacks.pull_requests.use_template trueCommands
jjacks doctorjjacks statusjjacks create <bookmark-name>jjacks get <branch-name>jjacks upjjacks ujjacks downjjacks djjacks logjjacks diffjjacks syncjjacks sync --dry-runjjacks sync --executejjacks merge
Getting Remote Branches
Use get when someone else pushed a branch and you want to adopt it into your local jj workspace:
jjacks get feat/coworker-branchjjacks get <branch-name> prints a plan and asks before fetching or editing local state. If a local bookmark with the same name already exists and points somewhere else, the prompt clearly says it will overwrite that bookmark and defaults to No.
Use get on the default branch when you want a fresh trunk continuation without syncing or pushing your current stack:
jjacks get mainThis fetches origin, moves the local default branch bookmark to its remote, and continues from that default branch using the same clean working-copy behavior as jjacks down.
To preview without changing local state:
jjacks get feat/coworker-branch --dry-runSync Modes
jjacks sync builds a plan, prints it, and asks before applying changes.
jjacks sync --dry-run prints the plan without changing local state or GitHub.
jjacks sync --execute applies the plan without prompting. It may fetch, move the local default bookmark, push stack bookmarks, create or edit pull requests, and update stack breadcrumbs.
Local Telemetry
jjacks can record local command timing telemetry to .jjacks/telemetry/commands.jsonl inside the repo. Telemetry is disabled by default. To enable it for a repo:
jj config set --repo jjacks.telemetry.enabled trueThe telemetry directory is gitignored and is intended for local performance analysis.
Generate a static HTML report from the collected data:
npm run telemetry:reportThe report is written to .jjacks/telemetry/report.html.
It is a static file with no build step; the browser loads Chart.js from esm.sh when you open it.
Docs
Notes
- The supported workflow is one
jjbookmark per GitHub pull request. sync --executeis intentionally direct: if a network or GitHub step fails, rerunjjacks statusandjjacks syncafter fixing the underlying issue.- Broader multi-stack management and unusual
jjtopologies are still beta territory.
