JayJay is a native macOS and Linux GUI for Jujutsu, with reusable Rust libraries for diff and review tooling.
- macOS: native SwiftUI app.
- Linux: GPUI app. Its macOS build is for development.
- Rust libraries: diffing, review state, repository operations, and app bindings.
JayJay is a fast, keyboard-friendly GUI for people who use jj every day.
- History: a DAG of changes with bookmarks, tags, conflicts, divergent changes, and other workspaces' working copies; a revset bar with completion and presets; drag a change or a whole selection to rebase it, or drag bookmarks and
@to move them. - Diffs: unified and side-by-side with syntax highlighting, word-level changes, expandable context, and rename detection; rich previews for images, SVG, Markdown, HTML, notebooks, CSV/TSV, SARIF, and property lists; edit working-copy files in place.
- Review: file and per-hunk review marks that survive edits and rebases, line-anchored review notes, and a
jayjay reviewCLI that lets coding agents read and resolve notes or pre-mark mechanical files. - Compare and inspect: interdiff between revisions or bookmarks, divergent-version compare, annotate, file history, and change evolution (
jj evolog) with Restore this version. - Split work: select files, hunks, or line ranges and move them into a child, a sibling, or the working copy; split by review state;
jj split --tool jayjayopens the same editor. - Conflicts: a merge editor with per-conflict Accept Left, Right, or Base, a raw marker mode, one-click Use Ours and Use Theirs, and an explicit
jj resolve --toolhandoff. - Operations: new, edit, describe, squash, split, rebase (including onto trunk), merge, parallelize, duplicate, absorb, revert, abandon, push, fetch, and undo from the operation log.
- Workspaces: create, switch in the current window, and forget workspaces; check out a pull request as a new workspace; the Repo Overview window shows every lane of mutable work and what needs attention.
- Bookmarks and forges: Bookmark Manager with remote sync state and cleanup; PR/MR links and CI status for GitHub, GitLab, Codeberg, and Cursor Origin; stacked PRs and MRs.
- AI commit messages from Codex CLI, Claude CLI, or Apple Intelligence, in the order you choose.
- Keyboard friendly: a command palette that also runs raw
jjcommands and finds help topics, Tab focus cycling, and shortcuts for everyday actions. - Integrations: external editors and terminals, pinned and recent repositories, multiple windows, the Dock menu, the
jayjayCLI launcher, andjayjay configfor jj and Git diff and merge tool definitions.
See the full feature guide for screenshots and workflows.
Requires macOS 26 or later.
brew install --cask hewigovens/tap/jayjayOr download the latest .zip from GitHub Releases, unzip it, and move JayJay to Applications. JayJay updates itself through Sparkle; choose JayJay → Check for Updates to check now.
Beta builds: set the update channel to Beta in Settings → About, then check for updates. To install a beta directly, download its .zip from its pre-release page.
The Linux app is built for x86_64 and aarch64. The install script puts the AppImage in ~/.local/share/jayjay and links jayjay into ~/.local/bin:
curl -fsSL https://jayjay.hewig.dev/install.sh | bashOn Arch Linux, use the signed pacman repo instead, so stable upgrades arrive with pacman -Syu:
curl -fsSL https://jayjay.hewig.dev/install.sh | bash -s -- --pacman-repoThe guide has the reviewable manual steps.
Debian/Ubuntu packages for amd64 and arm64 are also attached to each release. Download the matching .deb and install it with sudo apt install ./jayjay_<version>-1_<architecture>.deb.
Download the Windows x64 portable alpha ZIP from GitHub Releases, extract it, and run jayjay-gpui.exe. Requires Windows 10 version 1903 or later, or Windows 11, with jj installed separately on PATH. The alpha has no installer or automatic updater; Windows desktop behavior is still experimental.
Join the JayJay Discord community to ask questions, share workflows, and give feedback.
Found a bug or want a feature? Open an issue on GitHub.
Follow Contributing to install prerequisites, then:
just run # Build and launch the SwiftUI macOS app
just install-cli # Install the jayjay launcher to ~/.local/bin
jayjay . # Open the current repo
just gpui # Build and launch the GPUI app
just gpui-appimage # Build the Linux AppImageThe Rust workspace keeps diff rendering, review state, and shared domain types independent of jj-lib.
| Crate | Role | jj-lib? |
|---|---|---|
jj-diff |
Standalone diff engine: histogram line diff, word diff, syntax highlighting, context collapse, side-by-side rows | No |
jayjay-primitives |
Shared jj-lib-free domain and review identity types | No |
jayjay-review |
Local review marks, notes, and reconciliation | No |
jayjay-markdown |
Safe Markdown-to-HTML renderer for rich previews | No |
jayjay-network |
Platform-neutral HTTP request handling with an optional blocking client | No |
jayjay-core |
App-facing repo operations, jj data access, mutations, and format projections | Yes |
jayjay-uniffi |
UniFFI bindings for the SwiftUI app and WASM consumers | Indirect |
jayjay-cli |
Thin app launcher; command-line subcommands are served by the bundled macOS app, or the GPUI app on Linux and Windows | No |
Rule of thumb: jj-lib belongs in jayjay-core. Diff rendering, review state, and shared domain types stay below that boundary so they can be reused without embedding jj's repo model.
flowchart LR
swiftui["SwiftUI app (macOS)"] --> uniffi[jayjay-uniffi]
uniffi --> core["jayjay-core (jj-lib)"]
gpui["GPUI app (Linux, Windows)"] --> core
cli[jayjay-cli]
subgraph portable [No jj-lib]
review[jayjay-review]
diff[jj-diff]
primitives[jayjay-primitives]
network[jayjay-network]
markdown[jayjay-markdown]
end
core --> review
core --> network
review --> diff
review --> primitives
cli --> primitives
uniffi --> markdown
gpui --> markdown
classDef app fill:#E3F2FD,stroke:#1E88E5,color:#0D47A1;
classDef ffi fill:#E8F5E9,stroke:#43A047,color:#1B5E20;
classDef core fill:#FFF8E1,stroke:#FB8C00,color:#E65100;
classDef lib fill:#ECEFF1,stroke:#546E7A,color:#263238;
class swiftui,gpui,cli app;
class uniffi ffi;
class core core;
class review,diff,primitives,network,markdown lib;
Arrows point from a crate to the crates it depends on.
jj-diff is the standalone diff engine behind JayJay, available on crates.io. It has zero dependency on jj-lib.
[dependencies]
jj-diff = "0.1.1"use jj_diff::{collapse_context_with_mapping, compute_file_diff};
let diff = compute_file_diff("main.rs", &old_content, &new_content, false);
let collapsed = collapse_context_with_mapping(&diff);
for line in &collapsed.diff.lines {
// render line.style and line.spans in your UI
}Features:
- Histogram line diff via
similar. - Word-level highlighting within changed lines.
- tree-sitter syntax highlighting for common source formats.
- Context collapsing with display-to-full line index mapping.
- Side-by-side row building for two-column renderers.
- Placeholder detection for Git LFS, submodules, and binary content.
See crates/jj-diff/README.md for the full API.
- User Guide - shipped features and workflows (
docs/guide.html). - Keyboard Shortcuts - every shortcut, grouped by area; Cmd+/ opens a quick reference in the app.
- Issues - planned work and known gaps.
- Contributing - setup, development checks, testing, and pull request policy.
- Agent instructions - repository constraints and focused engineering guides.
- DeepWiki - indexed codebase reference.
- FAQ - install, licensing, platform support, and common feature questions.
- Blog - notes on Jujutsu, collaboration, and the tools around them.
- Rust crates (
crates/): Apache-2.0 - Apps and everything else (
shell/, docs, packaging): BSL 1.1 - free to use, modify, and redistribute; paid app store distribution requires permission. Converts to Apache-2.0 on 2030-03-23.