A fast, minimal desktop app for reviewing and landing changes in Jujutsu colocated repos. Tauri 2 + Rust + Lit. jj-native from day one: no staging axis, change-id identity, stack review.
- No staging axis. The working copy is a commit. The loop is
edit → review
@→ describe → new; partial commits are squash and split, notgit add -p. - Change ids are identity. Viewed flags, review comments and walkthroughs
key on the change id, so they survive
describe,squashand rebases. Structurally impossible in git; trivial in jj. - Review the stack, not just a diff. A sidebar over
trunk()..@, per-change review, "what changed since I last reviewed" interdiffs, and moving files or hunks between changes.
Review. Live working-copy diff (the filesystem vs @-, never a snapshot)
or any revset; split or unified; word-level intra-line spans; whitespace
toggle; expand-context; images side by side and rendered markdown. Virtualized
and keyboard-first — j/k files, n/p hunks, v viewed, ⌘F to find.
Press ? for the full list.
Act. Describe (with generated messages), new, edit, squash and split by file or by hunk, absorb, rebase from a picker or by drag, backout, duplicate, abandon, restore. Bookmarks, fetch, push, ahead/behind. The operation log is a first-class tab and every mutation reports what it did with an Undo that reverts exactly that operation. Conflicts are navigable by region and resolvable in-app.
Walkthroughs. One click turns a change into a guided review: an agent CLI
(claude, codex, opencode or pi) writes a reading order over the diff plus an
overview document — impacted systems, changed contracts, new state and
effects — with steps that filter the diff to their hunks. Agents can also
author walkthroughs headlessly via --print-hunks and --walkthrough-file.
Pull requests. jjdiff pr 75 fetches the head and reviews it like any
other change: reviewers, merge state and CI checks above the diff, the
conversation alongside it, and the inline comments you accumulated submitted
back as the review. Driven by gh — jjdiff never handles tokens, and your
own branch's PR surfaces itself when its checks change. GitHub only.
And the rest. jj workspaces (create one for a change without leaving the tree you're in), one window per repo, nineteen named themes plus light/dark, a command bar mirrored into the native menu, open-in-editor, and a CLI that is the same binary as the app.
Prebuilt, signed and notarized macOS builds (universal: Apple Silicon and Intel) are on the releases page. Linux builds from source below — CI keeps that compile green. Windows is untested.
From source, with Rust (stable), Node 20+, pnpm and jj ≥ 0.33:
pnpm install
pnpm tauri buildEither way, put jjdiff on PATH with the in-app menu item or
jjdiff --install-terminal-helper.
jjdiff # the repo you're in
jjdiff -R /path/to/repo # another repo
jjdiff 'trunk()..@-' # open on a revset
jjdiff -w # ... and generate a walkthrough
jjdiff pr 75 # review a GitHub pull request
jjdiff --diff @ # headless: the structured diff as JSON
jjdiff --print-hunks # headless: hunk ids, for agents~/.config/jjdiff/config.toml, same convention as jj itself:
[ui]
diff-style = "split" # or "unified"
theme = "system" # "light" / "dark" / any palette in the theme picker
[keymap]
command-bar = "Mod+k" # Mod is Cmd on macOS, Ctrl elsewhere
[editor]
# Placeholders: {file} (absolute), {line}, {repo}. No shell — split on spaces.
command = "zed {file}:{line}"Settings (⌘,) writes to this file one key at a time; your comments and key
order survive.
pnpm install
pnpm tauri dev # app against the cwd repo
pnpm tauri dev -- -- -R /path/to/repo # against another repo
pnpm dev # UI only, in a browser, on mock data
cargo test --workspace
cargo clippy --workspace --all-targets -- -D warnings
pnpm build # typecheck + bundle the UIpnpm build must precede any cargo command in a clean checkout.
pnpm release bumps the version, updates the changelog, tags and pushes;
the tag triggers the signed release build. See CLAUDE.md for the
rules of the codebase and PLAN.md for how it got here.
crates/vcs— the only place that shells out tojj(read/mutate discipline, JSONL templates)crates/diff— patch parsing and filesystem-vs-tree diffingcrates/watch— op-head and working-copy watchers (change detection without polling)src-tauri— app shell, IPC commands, headless CLIui— Lit frontend (light-DOM code pane)
