10 releases
Uses new Rust 2024
| 0.0.1-alpha.11 | Jan 30, 2026 |
|---|---|
| 0.0.1-alpha.9 | Jan 10, 2026 |
| 0.0.1-alpha.3 | Dec 24, 2025 |
#586 in Authentication
255KB
5.5K
SLoC
jj-ryu
Stacked PRs for Jujutsu. Push bookmark stacks to GitHub and GitLab as chained pull requests.
What it does
[feat-c]
@ mzpwwxkq a1b2c3d4 Add logout --> PR #3: feat-c -> feat-b
|
[feat-b]
o yskvutnz e5f6a7b8 Add sessions --> PR #2: feat-b -> feat-a
|
[feat-a]
o kpqvunts 9d8c7b6a Add auth --> PR #1: feat-a -> main
|
trunk()
Each bookmark becomes a PR targeting the previous bookmark (or trunk). When you update your stack, ryu updates the PRs.
Install
# npm (prebuilt binaries)
npm install -g jj-ryu
# cargo
cargo install jj-ryu
Binary name is ryu.
Quick start
# View your current stack
ryu
# Track bookmarks for submission
ryu track --all
# Submit tracked bookmarks as PRs
ryu submit
# Sync stack with remote
ryu sync
Authentication
GitHub
Uses (in order):
gh auth token(GitHub CLI)GITHUB_TOKENenv varGH_TOKENenv var
For GitHub Enterprise: export GH_HOST=github.mycompany.com
GitLab
Uses (in order):
glab auth token(GitLab CLI)GITLAB_TOKENenv varGL_TOKENenv var
For self-hosted: export GITLAB_HOST=gitlab.mycompany.com
Test authentication
ryu auth github test
ryu auth gitlab test
Usage
Viewing your stack
Running ryu with no arguments shows the current stack (bookmarks between trunk and working copy):
$ ryu
Stack: feat-c
[feat-c]
@ yskvutnz e5f6a7b8 Add logout endpoint
|
[feat-b] ^
o mzwwxrlq a1b2c3d4 Add session management
|
[feat-a] *
o kpqvunts 7d3a1b2c Add user authentication
|
trunk()
3 bookmarks
Legend: * = synced, ^ = needs push, @ = working copy
Tracking bookmarks
Before submitting, bookmarks must be tracked. This gives you control over which bookmarks become PRs:
# Interactive selection (opens multi-select picker)
ryu track
# Track specific bookmarks
ryu track feat-a feat-b
# Track all bookmarks in trunk()..@
ryu track --all
# Untrack a bookmark
ryu untrack feat-a
Tracking state is stored in .jj/ryu/tracking.json per workspace.
Submitting
ryu submit
This pushes all tracked bookmarks in the current stack, creates PRs for any without one, updates PR base branches, and adds stack navigation comments. Untracked bookmarks are skipped with a warning.
Each PR gets a comment showing the full stack:
* #13
* **#12 👈**
* #11
---
This stack of pull requests is managed by jj-ryu.
Syncing
ryu sync
This fetches from remote and syncs the current stack.
Workflow example
# Start a feature
jj new main
jj bookmark create feat-auth
# Work on it
jj commit -m "Add user model"
# Stack another change on top
jj bookmark create feat-session
jj commit -m "Add session handling"
# View the stack
ryu
# Track bookmarks for submission
ryu track --all
# Submit both as PRs (feat-session -> feat-auth -> main)
ryu submit
# Make changes, then update PRs
jj commit -m "Address review feedback"
ryu submit
# After feat-auth merges, rebase and re-submit
jj rebase -d main
ryu submit
Advanced options
Preview and confirmation
ryu submit feat-c --dry-run # Preview without making changes
ryu submit feat-c --confirm # Preview and prompt before executing
Controlling submission scope
# Submit only up to a specific bookmark (excludes descendants)
ryu submit feat-c --upto feat-b
# Submit only one bookmark (parent must already have a PR)
ryu submit feat-b --only
# Include all descendants in submission
ryu submit feat-a --stack
# Only update existing PRs, don't create new ones
ryu submit feat-c --update-only
# Interactively select which bookmarks to submit
ryu submit feat-c --select
Draft PRs
# Create new PRs as drafts
ryu submit feat-c --draft
# Publish draft PRs (mark as ready for review)
ryu submit feat-c --publish
CLI reference
ryu [OPTIONS] [COMMAND]
Commands:
submit Submit tracked bookmarks as PRs
track Track bookmarks for submission
untrack Stop tracking bookmarks
sync Sync all stacks with remote
auth Authentication management
Options:
-p, --path <PATH> Path to jj repository
-h, --help Print help
-V, --version Print version
submit
ryu submit [OPTIONS]
Options:
--dry-run Preview without making changes
-c, --confirm Preview and prompt for confirmation
--upto <BOOKMARK> Submit only up to this bookmark
--only <BOOKMARK> Submit only this bookmark (parent must have PR)
--update-only Only update existing PRs
-s, --stack Include all descendants in submission
--draft Create new PRs as drafts
--publish Publish draft PRs
-i, --select Interactively select bookmarks
--remote <REMOTE> Git remote (default: origin)
track
ryu track [BOOKMARKS]... [OPTIONS]
Options:
-a, --all Track all bookmarks in trunk()..@
-f, --force Re-track already-tracked bookmarks
--remote <REMOTE> Associate with specific remote
untrack
ryu untrack <BOOKMARKS>...
Options:
-a, --all Untrack all bookmarks
sync
ryu sync [OPTIONS]
Options:
--dry-run Preview without making changes
-c, --confirm Preview and prompt for confirmation
--stack <BOOKMARK> Only sync this stack
--remote <REMOTE> Git remote (default: origin)
auth
ryu auth github test # Test GitHub auth
ryu auth github setup # Show setup instructions
ryu auth gitlab test # Test GitLab auth
ryu auth gitlab setup # Show setup instructions
Coming from Graphite?
Ryu's CLI is inspired by Graphite. Here's how commands map:
| Graphite | Ryu |
|---|---|
gt track |
ryu track |
gt submit |
ryu submit |
gt submit --stack |
ryu submit --stack |
gt submit --only |
ryu submit --only <bookmark> |
gt submit --draft |
ryu submit --draft |
gt submit --publish |
ryu submit --publish |
gt submit --confirm |
ryu submit --confirm |
gt sync |
ryu sync |
gt branch create |
jj bookmark create |
gt restack |
jj rebase |
Key differences:
- Ryu requires explicit tracking before submit (
ryu track) - Stack management uses jj commands (
jj bookmark,jj rebase), not ryu ryu sync --stack <bookmark>syncs a single stack (Graphite syncs all)
License
MIT
Dependencies
~52–75MB
~1.5M SLoC