User guide

JayJay User Guide

A practical reference for JayJay's jj workflows: opening repositories, navigating history, reviewing diffs and rich file previews, managing bookmarks, creating stacked pull requests, resolving conflicts, and configuring tools.

Open a Repository #

  • Open a repository with Cmd+O, the app menu, the Dock menu (recent repositories and Repository List…), or the CLI launcher: jayjay /path/to/repo.
  • Open the current terminal directory with jayjay . after installing the bundled CLI launcher. A path inside a jj workspace opens its enclosing workspace, including when you launch from a nested source folder.
  • Choose Clone… on the welcome screen or File > Clone Repository… to clone a Git repository into a new jj checkout. Paste its URL, adjust the suggested name and location, and choose Clone. Cancel stops an in-flight clone; the repository opens when it finishes.
  • Onboarding offers Set Up… when your jj author identity is missing. Enter the name and email that jj should record on new changes, or set them later in Settings > Jujutsu.
  • The Repository List separates persistent Pinned repositories from shell-local Recent Repositories. Use the pin button to keep a repository in the list; clearing Recent does not remove pins, and unpinning returns a repository to Recent. Recent Repositories sit in a side panel that opens with your first recent repository, closes when the last one is removed, and toggles from the sidebar button in between. Drag the panel's divider to size it; the width and the list's window size persist across launches, and workspace rows show their path under the name. Pins are shared between the SwiftUI and GPUI shells.
  • Click the repository title in an open window to switch repositories. The menu activates an already-open repository without duplicating its window, opens a closed pinned repository in a new window, or returns to the full Repository List. Its rows can pin or unpin a repository or workspace from their context menu.
  • Onboarding, the Repository List, and each repository open in their own windows. Closing the last repository window returns to the Repository List automatically, and every window kind remembers its position and size across launches.
  • If you open a folder that is not a jj repository, JayJay shows an onboarding view with a jj git init path.
  • JayJay watches the repository and working tree, then refreshes visible working-copy details after jj operations or file edits. A refresh waits while an editor, review-note composer, or confirmation sheet holds unfinished input.
Clone a Git repository with a chosen name and location Clone a Git repository with a chosen name and location
Clone a Git repository into a new jj checkout.

Remote Repositories #

  • Choose File > Open Remote Repository… or search the command palette for Open Remote Repository to work on a jj repository on another machine over SSH. Pick a host from your SSH config or a recent one, or type a host or config alias, then browse to the repository folder and choose Connect. A folder that is not a repository yet offers jj git init.
  • JayJay uses your OpenSSH configuration without prompting, so the host must accept key or agent authentication and already be in known_hosts. Agent, X11, and port forwarding stay off.
  • macOS, Linux, and Windows hosts are supported. JayJay runs a small helper on the host, which it installs under ~/.local/share/jayjay/helpers (%LOCALAPPDATA%\JayJay\helpers on Windows) on first connect. Release builds download the helper for the host's platform from the matching GitHub release and check it against the hash the app ships with.
  • The status bar shows the host, its platform, and the connection state; click it for Disconnect and Reconnect. While disconnected the repository stays on screen, and JayJay never retries a write on its own: if a write may have completed, reconnect and refresh before trying again.
  • Remote working copies refresh on their own, like local ones. Review marks and notes stay on this machine; notes are matched against the host's diffs here, so their text never goes to the host. Finder, editor, terminal, and external merge-editor actions are unavailable for remote repositories.
  • Remote repositories are available in the macOS app, on Linux, and on Windows.

Main Window #

  • The title bar holds the sidebar toggle, refresh, pull, and push, then the repository title, with the revset bar in the center and editor, terminal, and Settings buttons on the right.
  • The left graph shows jj changes as a DAG with lanes for forks, merges, bookmarks, tags, conflicts, divergent changes, and working-copy state. Each row shows bookmark and tag chips, name@ chips for other workspaces’ working copies, the author avatar, the committer’s relative timestamp, and the shortest unique change-id prefix highlighted. Conflicted bookmarks (name?? in jj log) use an orange warning chip on every target change. As in jj log, immutable changes are drawn as diamonds and mutable ones as circles.
  • The detail header shows the selected change, description, author, status, bookmarks, PR state, and available actions. Co-authors named in description trailers and a distinct committer appear beside the author, with duplicate identities combined. The change-id and commit-id are shown with their shortest unique prefix in bold. A short description body takes only the lines it needs; a long one shows its first 80 points and scrolls; Expand shows up to 320 points while the file list and diff stay visible, and the bold summary with its Edit button stays put while the body scrolls.
  • The file column lists changed files in flat or tree form and shows review status, conflicts, renames, and file-level actions. On macOS, hide or show the history sidebar with the toolbar button, View menu, or Control-Command-S. Drag the dividers to size the sidebar and file column; JayJay keeps those widths across launches and shrinks them in a smaller window so the diff pane keeps its room.
  • The diff pane shows the selected file with unified or side-by-side layout, syntax highlighting, word-level changes, collapsed context, and rich previews for supported formats.
  • Syntax highlighting includes PowerShell, Batch, INI, CMake, XML-family, and Fluent (.ftl) files, alongside the existing source-code formats.
  • The status bar surfaces repository state, selected bookmark PR links/checks, and useful workspace context.
  • Press Tab to move keyboard focus through the window: graph, file list and its controls, description, diff layout, edit buttons, toolbar, and the commit fields, wrapping at the end; Shift+Tab reverses. Space or Return activates the focused control, Esc returns to the pane, and the active pane draws a stronger selection.
JayJay main window — DAG graph and unified diff JayJay main window — DAG graph and unified diff
DAG with highlighted change-ids, bookmark and tag chips, author avatars, and the diff pane.

Review Diffs #

  • Review your working copy like a pull request: step through the changed files and press Space to tick each one off with its review checkbox. Clicking a file's review mark or Mark Reviewed in the diff header does the same, and each moves on to the next unreviewed file after the current one, so files you skipped stay behind; in GPUI, Space marks a multi-selection and moves on too. Hide reviewed files to focus on what's left, or filter the list by name; Esc clears and closes the filter, Return keeps the query and hands the keys back to the list.
  • Toggle between unified and side-by-side diffs, and browse changed files as a flat list or a tree. The file column header puts its controls first and one count last: filter matches while filtering, review progress once a file is reviewed, otherwise the file total.
  • The diff header shows a file-type or language icon, the file's status pill and added and removed line counts next to its name. Mark Reviewed, Preview, the Unified/Side-by-side toggle, Edit Diff, and Edit File sit on the right in one borderless style and drop to icons when the pane is narrow; Tab reaches Edit File after Edit Diff.
  • Tabs occupy four visual cells when wrapping and selecting diff text; GPUI displays them as four spaces, including on Windows.
  • Moved code is marked with linked line-number badges in unified and side-by-side diffs. Click a badge to jump to the matching block in the same file; the destination is briefly highlighted.
  • Binary file sizes follow your locale; hover over a size to see the exact byte count.
  • Use Cmd+F to search within the current diff.
  • Review state is local to your machine and survives app restarts. Click a changed group's gutter stripe to review that hunk; file rows roll up unreviewed, partial, reviewed, and changed-since-review state. Marks follow uniquely matching hunks across edits and rebases, so changing one hunk does not discard review work on the others. Files whose marks came from an agent (see Review Notes) show an agent badge and are counted in the reviewed-count tooltip until you take them over.
  • Image files render as images where possible; drag the divider between the two versions to give either side more room and double-click it to reset. SVG files open rendered, and the preview button returns to the source; SVG stays on source when the file has notes or can't render. The rendered view fits the image's own size and scales down to the pane.
  • Supported rich previews include Markdown, SVG, HTML, notebooks, CSV/TSV tables, SARIF reports, and binary property lists. SVG and SARIF open rendered; other text-backed files stay raw by default so diff review still works, and the rich preview icon switches to the rendered view. Notebooks open as a text diff of their Markdown projection, with Preview and Source buttons beside it, since the rendered view hides what changed. Working-copy HTML files render inline in a sandboxed preview (scripts don't run); an external-open icon next to it still launches the file in the default app, so linked CSS and images work normally there too. Fenced mermaid blocks in rendered Markdown become diagrams offline in both shells; unsupported or oversized diagrams remain source code. On macOS, pinch to zoom the preview. Switch Preview off to read the source diff. Binary property lists open as XML with a banner, while plain XML property lists stay raw.
  • Renames, collapsed context, and ignore-whitespace behavior are reflected in the diff view. In either diff layout, use Show 10 or Show all on an unmodified-lines row to reveal nearby context without leaving the file.
  • Copying diff text excludes gutter line numbers. On macOS, select text in a side-by-side pane and press Cmd+C to copy the original source lines without extra line breaks from wrapping or blank rows used to align the panes.
  • For changed working-copy text files, right-click a line number in either diff layout and choose Edit File at Line N to open the working-copy editor at that line. When the configured external editor supports line targeting, the same menu offers an action to open it at that line.
  • For a changed regular text file in the current working copy, use Edit File in the diff header to open JayJay's syntax-highlighted editor in a large modal, leaving the diff detail intact underneath. Highlighting is ready when the editor appears, and long lines soft-wrap to the available width. Save with Cmd+S or cancel with Esc; JayJay refuses the save if that file or the working-copy change changed after the editor opened. Historical, compare-mode, conflicted, removed, projected, and image files stay read-only.
Moved-code links between matching diff blocks Moved-code links between matching diff blocks
Click a moved-code badge to jump to its matching block.
Mermaid flowchart in a rendered Markdown preview Mermaid flowchart in a rendered Markdown preview
Markdown previews render Mermaid diagrams offline in both shells.
Working-copy review with a reviewed hunk and inline note Working-copy review with a reviewed hunk and inline note
Mark individual hunks reviewed and leave notes beside the lines that need attention.

Review Notes #

  • Leave line-anchored feedback while reviewing the working copy: right-click a changed line's gutter and choose Add Review Note. The editor shows a short diff excerpt around the anchored line; save with Cmd+Return.
  • Saved notes render inline in the unified diff as an orange-outlined bubble directly below the annotated line, with an orange dot in the gutter's note column. Click the dot — or right-click the line again — to Edit, Resolve, or Delete the note.
  • Files with active notes show an orange note count in the file list, and the header note badge filters the list to noted files.
  • Notes anchor to the line's content. If the file changes underneath, the note turns stale and moves to a banner above the diff, together with orphaned notes whose anchor disappeared. Resolving a note keeps a dimmed gutter dot as a record.
  • Notes are local to your machine, shared across app windows and the jayjay CLI, and survive rebases of the change. They render in unified view; side-by-side shows the file's note count with a one-click Show in Unified.
  • Built for agent loops: review an AI agent's changes (or your own), leave notes on the lines that need work, then have the agent read them with jayjay review notes --repo . --format json and resolve each with jayjay review resolve-note <id> --repo . once addressed.
  • Agents can annotate too: jayjay review add-note --repo . --file <path> --line <n> -m "note" anchors a note to a changed line, and it appears in the diff view like any other note — a cleaner channel for review commentary than source-code comments.
  • Agents can also pre-review: jayjay review status --repo . lists every changed file with its review state and the commit it inspected, jayjay review mark --repo . --file <path> --expected-commit <id> marks a mechanical file reviewed on the agent's behalf (add --line <n> to mark one change group), and jayjay review unmark --repo . drops every agent mark again. A mark is refused if the working copy changed since the inspected commit, an agent never takes over a group you reviewed, and your own marks on a file take it back. Every subcommand answers --help.
  • Teach your coding agent these loops with the JayJay agent skill: npx skills add hewigovens/jayjay --skill jayjay installs it for Claude Code, Codex, and other agents that read Agent Skills, or copy skills/jayjay into the agent's skills folder. On macOS, turn on Settings > Integrations > Coding Agents > Integrate with coding agents to install it for Claude Code, Codex, and Cursor in your home folder; JayJay leaves a custom or edited skill in place. It needs the jayjay command on your PATH; on macOS choose JayJay ▸ Install Command Line Tool….

Compare Changes #

  • Shift-click two graph revisions: a valid direct-parent chain shows a combined diff; otherwise JayJay compares the two endpoint trees. For an explicit comparison, select one revision, right-click the other, and choose Compare with selected. When both endpoints have bookmarks, JayJay uses their names in the compare banner.
  • Use the compare direction control to switch the diff direction.
  • Bookmark diff is useful for PR-style review: compare the main bookmark or fork point against a feature bookmark.
  • Interdiff mode uses the same unified and side-by-side renderers, but hides working-copy review controls because the comparison is not a file-review session.
  • Diff divergent changes: right-click a change marked divergent and choose Compare Divergent Versions to interdiff the two commits that share its change-id — so you can see which one is safer to abandon.
  • To combine the versions instead, choose Resolve Divergent Change… on a divergent change. On macOS the sheet works like the merge editor: Keep A or Keep B takes one version whole, or decide description, contents, author, and parents card by card. Each card starts from jj’s own convergence pick, Use A / Use B (or Option-Left / Option-Right, with Option-Up / Option-Down to move between cards) overrides it, and Edit… writes your own description. The Contents card lists the files that differ with their diff, items that match in every version collapse to one line, and the sheet lists the descendants, bookmarks, and workspaces that will move. Converge creates one successor in a single undoable operation, keeps any file conflicts for the conflict workflow, and refuses to apply if the repository changed after the preview.
Interdiff between two revisions Interdiff between two revisions
Bookmark diff: compare a feature bookmark against a base change or main bookmark.
Compare divergent versions Compare divergent versions
Divergent compare shows the two commits that share a change-id before you abandon one.

Edit Diffs & Split Work #

  • Diff edit mode lets you select files, hunks, or line ranges from the working copy or another mutable change.
  • Each file card shows its +/− line counts and collapses in place. Large diffs start collapsed so the file list stays scannable, and Expand All / Collapse All (Cmd+Option+E / Cmd+Option+C) toggle every file at once.
  • The whole view is keyboard-driven: j / k or ↑ / ↓ move focus between file cards, ← / → collapse or expand the focused card, Return toggles it, and Space selects its changed lines.
  • Selected edits can become a child change, a parallel change, or be moved into the working copy. Working-copy edits can be discarded at selected line granularity.
  • Batch split can use reviewed files as the selection model. Split supports a parallel option when the selected edits should become a sibling instead of a child; to turn existing changes into siblings, select them and use Parallelize.
  • From the file list, split selected files directly from any mutable change or move selected historical files into the working copy. Commit File and Delete from Disk remain working-copy-only actions.
  • Topology-aware destinations preserve the intended jj graph shape when moving edits.
  • JayJay can also be a blocking CLI diff tool. jj split --tool jayjay opens the same multi-file, line-selectable editor; jj diff --tool jayjay and git difftool --dir-diff open read-only directory comparisons.
Diff edit — selecting hunks to split Diff edit — selecting hunks to split
Select files, hunks, or lines and extract them into a new change.

Change Operations #

  • Edit a change description directly, or use the commit box to describe and commit the working copy. The box prefills from the working copy's existing description and preserves a typed draft when @ moves to an empty change. The description dialog uses the same Summary and Description fields, keeps your working-copy draft, and leaves unchanged formatting and indented bodies as they are; an empty mutable change offers Add description.
  • Generate commit messages with Codex CLI, Claude CLI, or Apple Intelligence when available on macOS. On macOS, drag providers in Settings > Integrations to choose their fallback order.
  • Create new changes on top of, before, or after a revision when its topology permits it; edit an existing change; squash into a parent or selected change; rebase, merge, or parallelize selected changes; abandon, duplicate, or absorb; and revert or back out changes. Rebase onto trunk in a change's context menu, or Rebase Working Copy onto Trunk in the command palette, moves that whole line of work onto trunk(), including a workspace's working copy.
  • Run formatters (jj fix) on a change, a multi-selection, or from the command palette runs the tools in your [fix.tools] config over the selected changes and their descendants with jj's semantics for patterns, enabled, line-range-args (or the older line-range-arg), and run-tool-if-zero-line-ranges. A failing tool leaves its file unchanged and is reported, an immutable change is refused before anything runs, a run that changes nothing records no operation, and an unusable config disables the items with the reason.
  • Create a lightweight tag on a change from its context menu; a tagged change becomes immutable. A tag chip's menu copies the name, pushes a tag that exists only locally, and deletes it; once a tracked remote has the tag, Delete Tag on Remote asks for confirmation, removes it locally, pushes the deletion to every remote that tracks it, and restores the local tag if the push fails. Tags collapsed into the +N chip keep their actions in the change menu.
  • Restore files to parent content, or delete, ignore, and untrack working-copy files where applicable. Move selected files from any change into the working copy.
  • Use Undo to inspect the jj operation log and roll back recent operations. JayJay shows lightweight toasts for completed actions and keeps the rest of the window usable when possible.
JayJay undo operation log JayJay undo operation log
Undo uses jj's operation log so recent repo operations can be inspected before rolling back.

Bookmarks, Git & Pull Requests #

  • Use the Bookmark Manager (Cmd+Shift+B) to inspect bookmark stats, filter bookmarks, reveal their changes, copy names, diff them, and resolve conflicts.
  • Each bookmark shows its remote sync state per tracked remote: a green check when it matches the remote, or ahead / behind / diverged when the local bookmark and the remote ref point at different commits — hover to see where the remote sits. (The synthetic colocated @git remote is omitted as noise.)
  • Deleted bookmarks are hidden by default; toggle Show deleted to see them, then use Forget (clean up) to remove a leftover bookmark — including its colocated @git branch.
  • Use bookmark actions to create, rename, track, move forward, delete, and push bookmarks, or drag a bookmark chip in the DAG to move it onto any change. On a conflicted DAG chip, Remove from This Change drops the bookmark from that change only; Bookmark Manager and the picker still delete every target.
  • After moving a remote-tracking bookmark by drag, a one-click Push affordance appears in the sidebar so you can publish the move (it never pushes automatically).
  • The Bookmarks picker in the graph header, beside the change count, groups bookmarks as Tracked, Local Only, and Remote Only. Click a bookmark to select its change, or, when the graph does not show it, to narrow the graph to its stack and select it; choose a remote-only bookmark to browse that remote's history without creating a local bookmark. Filter by This Bookmark in a picker row’s menu or a graph bookmark chip’s context menu narrows the graph to the bookmark and its changes over trunk.
  • Push and fetch Git remotes from JayJay. Pull, Push, and bookmark tracking use the remote in git.push, else the repository's only remote, else origin, as jj does. Pull and Push leave bookmark tracking alone: pushing a specific bookmark tracks it, and other tracking stays an explicit bookmark action.
  • After a fetch or pull, a tracked bookmark whose remote branch was deleted, for example once its pull request merged, is cleaned up: its emptied changes and the bookmark go in one undoable operation. Changes with unmerged work, conflicts, or a workspace's working copy are kept, and Bookmark Manager marks the bookmark deleted on that remote.
  • Right-click a bookmark in the DAG or Bookmark Manager to open a GitHub, GitLab, Codeberg, or Cursor pull/merge request. If a matching PR or MR already exists, JayJay opens it; otherwise GitHub, GitLab, and Codeberg open their compose pages. Cursor Origin has no compose URL, so Pull Request on Cursor creates a PR through the API using the change description as its title and body, then opens it. Sign in with origin auth login first. GitHub-mirrored Origin repositories and bookmarks missing from the remote report an error.
  • The status bar shows the selected bookmark’s PR/MR link and CI checks through the forge’s API. Configure its authentication in Settings > Integrations > Forges; Cursor checks stay pending while any check run is unfinished.
  • On a Gerrit remote (gerrit.* config, a *.googlesource.com URL, or port 29418), Upload to Gerrit in the change menu runs jj gerrit upload and shows the change links Gerrit returns. Pull abandons local changes left empty because trunk carries them after submission. JayJay remembers the patch set it uploaded, refuses an upload that would replace a newer patch set made in Gerrit, and Update from Gerrit takes that patch set into the local change.
  • jayjay.upload-command and jayjay.sync-command in jj config replace Upload and Pull with your own jj commands; $revision expands to the change.
  • Remote repository URLs can be opened in the browser, including git@... URLs converted to HTTPS.
JayJay Bookmark Manager JayJay Bookmark Manager
Bookmark Manager shows bookmark sync state, cleanup actions, and PR entry points in one place.

Workspaces #

  • Create a new jj workspace from the Repository menu (New Workspace…) or the command palette: pick a destination folder and name, and JayJay runs jj workspace add so you get a second working copy backed by the same repository.
  • Choose New Workspace from Pull Request… from the Repository menu or the command palette to check out a GitHub pull request or GitLab merge request: paste its URL, review the base repository, remote, bookmark, and head commit, then adjust the workspace name and location and let JayJay fetch the head and create the workspace. It adds the fork as a remote when needed, stops if the pull request moved since the preview, and offers to open the existing workspace instead of importing the same pull request twice. GitLab uses GITLAB_TOKEN when available, then an existing glab auth login; public merge requests also work without sign-in. Codeberg links are recognized but not yet supported.
  • From a terminal, jayjay import <URL> does the same: it fetches the pull or merge request’s head into a pr-<number> workspace beside the repository, or names the workspace that already has it; --name and --dest override the workspace name and folder. jayjay workspace add <name> creates ../<name> on trunk() (-r picks another revision), and jayjay workspace prune <name>… or --all forgets and deletes workspaces whose changes are all in trunk() or empty, keeping any with pending work.
  • Click the repository title to search and switch between this repository's workspaces, other open windows, pinned repositories, and recent repositories. The picker's Overview button opens the Repo Overview.
  • Right-click a workspace in the title picker or its name@ chip in the graph and choose Filter by This Workspace to narrow the graph to that workspace. Clear the revset filter to return to the default view. Open the current checkout in Finder from the folder toolbar button, Repository > Show in Finder, or Option+Cmd+F; Windows and Linux use Show in File Manager and Ctrl+Alt+F.
  • Choosing a workspace in the title picker, or a command-palette Switch to entry, opens it in the current window, or brings its window forward if it is already open. The window keeps showing the source workspace, with the refresh indicator spinning, until the destination has loaded; if the workspace fails to open, the source stays usable and JayJay shows the error. Unsaved commit-message drafts are kept per workspace, so switching away and back restores them. Option-click a workspace (Alt-click on Linux) or choose Open in New Window from its context menu for a separate window.
  • Repo Overview (Repository menu, Cmd+Shift+O, the command palette, or the picker's Overview button) opens a window with every lane of mutable work as a tree growing from trunk; the label on trunk names each lane's base, with its commit and age beneath. Each lane card shows its title, the workspaces and bookmarks on it, and its change count and age, or what needs attention: conflicts, undescribed changes, or an empty undescribed checkout above finished work. Click a lane to open its panel with the base, a Rebase onto trunk button when it is behind, its workspaces and how far below the head each sits, its bookmarks, and every change; click a change for its description and changed files, which you can select and copy. Filter lanes with Cmd+F, move between lanes and changes with the arrow keys, press Return to show the selection in its workspace window, press Esc to step back out of a panel, and use the context menu to rebase a lane onto trunk, abandon a lane or change, copy ids, or open, reveal, or forget a workspace. Show in Graph keeps following a change after it is rewritten, for example once you resolve its conflict.
  • Workspace rows identify the current checkout and show each working copy's change-id, description, conflict state, age, and changed-file count. Other workspaces also appear as name@ chips on their working-copy changes in the DAG; right-click a chip to open that workspace in a new window, copy its name or path, or choose Rebase Lane onto trunk to move its mutable lane onto trunk.
  • Use a workspace row's context menu to open it, copy its name or path, Forget Workspace while leaving its directory intact, or Forget & Delete from Disk after confirmation; tick Don't ask again to skip it, and Settings → Workflow brings it back. JayJay closes every window for that workspace before deletion and never deletes a replacement directory that appeared at the same path. Forgetting a matching Git-backed workspace also releases its Git worktree registration so the path can be reused.
  • When another workspace rewrites this workspace's working-copy change, for example by rebasing it, the working copy is stale. JayJay keeps showing the graph, marks the @ row with a warning glyph, and badges the Refresh button; Refresh, or Update Workspace in the row's context menu, updates the working copy like jj workspace update-stale instead of snapshotting old files over the rewrite.
  • The Repository List groups recent sibling-workspace checkouts beneath their primary repository, so related working copies stay together instead of looking like unrelated repositories.
Repo Overview window with lanes of mutable work Repo Overview window with lanes of mutable work
Repo Overview: every lane of mutable work, the workspaces on it, and what needs attention.
Workspace picker context menu with Filter by This Workspace Workspace picker context menu with Filter by This Workspace
Filter the graph from a workspace row without switching checkouts.
Search workspaces by name Search workspaces by name
Search and switch between working copies from the repository title.

Stacked Pull Requests #

Turn a linear stack of changes into one PR (GitHub, Codeberg, or Cursor Origin) or MR (GitLab) per change, each targeting the one below it.

  • Right-click the tip change in the DAG and choose Create / Update Stacked PRs. Whatever change you click becomes the top of the stack; everything from just above trunk() up to it is included.
  • The preview shows one row per change — bottom-first targeting your default branch (main), each higher one targeting the bookmark below it. Each row's branch name is editable (pencil → edit → Done); when Apple Intelligence is available, Generate bookmarks suggests names from the commit messages. Existing bookmarks are reused unchanged.
  • Submit pushes every bookmark at once, then creates or updates the PRs/MRs with their dependent bases. Done opens the top PR for a linked GitHub stack, always opens the highest submitted GitLab MR, and opens each submitted PR if GitHub native linking falls back. Re-running is idempotent — bookmarks anchor on the change-id, so it updates the same PRs/MRs and stack instead of duplicating.
  • GitHub native stacks: JayJay links the stack through the GitHub API; no CLI extension is required. If GitHub Stacked PRs is not enabled for the repository or rejects the chain, the dependent PRs remain usable and the result explains that native linking was skipped.
  • GitLab stacks: GitLab detects the dependent MR chain automatically and shows a stack navigator in each MR; no separate linking request is required.
  • Codeberg stacks: set CODEBERG_TOKEN or FORGEJO_TOKEN, or use tea login add, with write access to the repository. JayJay creates or updates dependent PRs and adds links to the stack in each PR description.
  • Cursor Origin stacks: Origin is still early beta. JayJay submits dependent pull requests through its API using your origin auth login credentials.
  • Merging: for ordinary GitHub PR chains, GitLab MRs, Codeberg PRs, and Cursor Origin PRs, merge bottom-up (the one targeting main first). After each merge, run jj git fetch and Create / Update Stacked PRs again to retarget the remaining layers. If GitHub has linked the PRs into a native stack, use GitHub's stack controls; merging a PR also merges every unmerged layer below it, then GitHub rebases and retargets the remainder.
  • GitHub, GitLab, Codeberg, and Cursor Origin requests use their APIs directly. For GitHub or GitLab, sign in from Settings > Integrations > Forges, use an existing gh auth login/glab auth login, or supply GH_TOKEN/GITHUB_TOKEN or GITLAB_TOKEN. Environment tokens take precedence over JayJay sign-ins, then CLI logins. Codeberg accepts CODEBERG_TOKEN/FORGEJO_TOKEN or a tea login add login. Cursor Origin uses the login from origin auth login; the CLI supplies credentials while JayJay performs PR operations through the API. Settings shows the active authentication source. The forge is taken from the repo’s origin remote.
Create / Update Stacked PRs menu item Create / Update Stacked PRs menu item
Right-click the tip change → Create / Update Stacked PRs.
Stacked PRs preview with editable branch names Stacked PRs preview with editable branch names
The preview: one row per change, editable branch names, dependent bases.

Conflict Resolution #

  • Conflicted changes and files are marked in the graph and file list.
  • The conflict bar offers one-click Use Ours and Use Theirs actions when the file can be resolved that way.
  • Edit in JayJay opens a large, soft-wrapping, syntax-highlighted modal over the current detail. Two-sided conflicts show Base-relative, diff-highlighted Left and Right sources on top with the editable Result below, and switch the source area to a full-width Base on request. Source and result panes scroll together, with the pane you scroll leading the others, and selecting or accepting a conflict brings it into view in every pane. N-way jj conflicts remain editable through their markers, and partially resolved output can be saved when more work remains.
  • Edit in JayJay uses the same large merge view for repository and CLI tool sessions. Hunk mode shows each two-sided conflict once as a unified Left-to-Right diff, with quiet Accept Left, Accept Right, and Accept Base links, hover help, syntax-aware non-editable -/+ gutters, and Option-Left/Right shortcuts. Raw mode switches to direct marker editing.
  • The conflict banner’s resolution menu offers the merge editor configured by jj’s ui.merge-editor, Edit in JayJay for supported text conflicts, and the external editor selected in Settings. Choose Resolve in <tool> to hand off to a merge tool, save the resolution there, then return to JayJay; Open in <editor> opens the working-copy file when that editor has no merge-tool integration.
  • JayJay refreshes after resolution so the graph and file list reflect the new repo state.

To use JayJay from jj everywhere, run jayjay config for the paste-ready tool definition, or choose Copy Config in Settings > Integrations > Version control, then add it to your jj config.

Then use jj -R /path/to/repo diff --tool jayjay for a read-only comparison, jj -R /path/to/repo split --tool jayjay for interactive diff editing, or jj -R /path/to/repo resolve --tool jayjay path/to/conflicted-file for conflict resolution. jj edit selects the working-copy revision and does not accept a diff tool. The diff and split commands also work with jj's default two-path invocation, so the explicit diff-args and edit-args are optional.

On macOS, external diff session headers remain visible while files scroll. Diff and merge load failures show a readable error. Run jayjay tool --help to read the tool usage without opening a session.

JayJay also accepts Git's custom diff and merge contracts:

[diff]
    tool = jayjay
[difftool "jayjay"]
    cmd = jayjay tool diff "$LOCAL" "$REMOTE"
    prompt = false
    trustExitCode = true
[merge]
    tool = jayjay
[mergetool "jayjay"]
    cmd = jayjay tool merge "$LOCAL" "$BASE" "$REMOTE" "$MERGED"
    trustExitCode = true

Use git difftool --dir-diff for one multi-file comparison or git mergetool for conflicts.

Conflict banner with whole-file choices Conflict banner with whole-file choices
The conflict banner offers whole-file choices and an entry point to resolve the file.
Built-in merge editor Built-in merge editor
Resolve each conflict with Accept Left, Accept Right, or Accept Base; save a partial resolution when work remains.

Inspection Tools #

  • File Annotate shows blame information with a syntax-highlighted gutter and lets you navigate to the responsible change.
  • File History opens in a separate window and lists revisions that modified the selected file, with the selected revision’s diff alongside it. Choose Pin as Base, then select another revision to compare the file between them. Swap reverses the endpoints; Clear or Esc clears the base. Right-click a revision and choose Show in Graph, or double-click it, to reveal it in the repository window.
  • Find a regression with Bisect… in the command palette, Bisect from here… in a change’s context menu, or Bisect between on two selected changes. Set Good and Bad endpoints, or enter a revset Range to use as-is, then choose Start. JayJay checks out candidates and highlights the search in the graph; mark each one Good, Bad, or Skip in the bar under the toolbar.
  • The bisect bar’s Run Test… control runs a shell command for this step or to the end. Exit status 0 means Good, 125 means Skip, 127 aborts, and other failures mean Bad. The bar shows command output and the result; its close button stops bisecting and restores the original working copy, reporting any temporary changes it kept.
  • Change Evolution shows prior versions of a rewritten change with operation labels such as snapshot, describe, rebase, squash, and split. Consecutive working-copy snapshots collapse into one row, and Hide snapshots removes that noise entirely. Select one version for its diff or two versions for an interdiff.
  • Right-click an evolution entry to Restore this version, which puts that version's content back into the working copy or the change you opened the evolog for in one undoable operation, or to copy its commit id or a jj restore command for that change. Immutable changes cannot be restored.
File History comparing a pinned base and target File History comparing a pinned base and target
Pin a base and choose another revision to compare the file between them.
Bisect progress and verdict controls above the change graph Bisect progress and verdict controls above the change graph
Bisect checks out a candidate and keeps Good, Bad, Skip, and Run Test close to the graph.
Change evolution log Change evolution log
Evolog: every snapshot of a change, with operation labels and restore.

Command Palette #

  • Open the command palette with Cmd+Shift+P and search built-in actions by name.
  • With a change selected, search for Show Evolution and run it to inspect that change’s rewrite history.
  • Type help <topic>, such as help split or help stacked pr, to find local feature help from the bundled guide index.
  • Type jj <args> or ! <args> to run raw jj commands inline. Output appears inside the palette and can be copied.
  • Command history is available during the session, so repeated jj commands are easy to recall.
Command palette searching JayJay actions Command palette searching JayJay actions
Fuzzy-search actions, shortcuts, and local feature help.
Command palette raw jj command mode Command palette raw jj command mode
Type jj or ! to run raw jj commands inline.

Tools & Settings #

  • Settings is organized into Appearance, Fonts, Diff & Files, Keyboard Shortcuts, Workflow, Integrations, Jujutsu, Data & Privacy, Flock, and About pages. Flock lets GitHub sponsors unlock a keepsake feather and alternate birds for About, and on macOS alternate Dock icons. JayJay checks command availability in the background, detects supported AI providers, and offers a one-click copy of its jj diff/edit/merge tool configuration.
  • Diff & Files holds the diff layout and rendering defaults and Auto-expand descriptions, which opens an overflowing description at its expanded height as soon as a change is selected; the command palette toggles it too. Workflow holds confirmations, including the skipped Forget & Delete prompt.
  • The update channel dropdown in Settings → About switches between Stable and Beta; the Beta channel receives pre-release builds through the regular update check.
  • Anonymous build and OS statistics are enabled by default and can be disabled in Settings. No repository, file, or command data is sent, and rotating identifiers cannot link an installation across months.
  • Appearance selects separate light and dark themes: Default, One, Gruvbox, Solarized, Catppuccin, Dracula, Nord, and Tokyo Night, with a preview of the repository window. The chosen theme follows the active appearance and colors the repository window as well as diffs, editors, and syntax highlighting. On macOS, Tint window background with wallpaper color is available with Default Dark; other dark palettes use their own background.
  • In Settings > Appearance > Language, choose System, English, Japanese, Simplified Chinese, or Traditional Chinese. Most text updates immediately. On macOS, choose Relaunch after changing the language to update system menus and update dialogs.
  • Keyboard Shortcuts lists every command by context with its current shortcut. Search by name, or filter to Modified; click a shortcut and press the new keys to change it. A shortcut already in use names the command it belongs to and offers Replace; Reset restores one shortcut and Reset All every one. Menus, the command palette, and the shortcut reference follow your changes. A few navigation keys are fixed.
  • Fonts groups interface and code font families and sizes on one page. Code fonts also have line spacing and ligatures, with a live diff preview; the ligatures switch is disabled when the selected font has none. Reset Fonts restores both font configurations. Adjust both sizes together with Cmd++, Cmd+-, and Cmd+0.
  • Open files in external editors such as VS Code, VSCodium, Cursor, Zed, Xcode, or Vim. Cursor launches with --classic so it opens in editor mode rather than its agent window.
  • On macOS, open Terminal.app, iTerm2, Ghostty, or Rex at the repository path. Rex opens folders in a new tab; terminal-editor commands use Terminal.
  • Integrations holds editor, terminal, and AI commit-message providers, the jayjay/jj tools, and authentication sources for GitHub, GitLab, Codeberg, and Cursor Origin. Jujutsu reads your jj user config files directly, grouped by section with the value that wins for each key, and needs no jj binary; it shows Config not found for a missing file, or the load error and the file that failed, with an Open action.
  • In Settings > Integrations > Forges, click Sign In… beside GitHub or GitLab, then Copy Code & Open Browser. Paste the code into the forge’s page and approve access; the sheet closes when sign-in succeeds. Cancel stops waiting, and Sign Out removes the sign-in stored by JayJay. Environment tokens take precedence over JayJay sign-ins, followed by existing gh/glab logins; signing out of JayJay does not remove those other credentials.
  • Data & Privacy shows the number of stored review marks and notes, can clear them for every repository after confirmation, and holds the statistics switch.
  • Choose Help > Reveal Logs to inspect the local jayjay.log. The log rotates after 2 MiB and keeps one previous file. Enable Debug mode in Settings > Data & Privacy for snapshot and graph timings; GPUI also monitors main-thread stalls throughout the session. Beta builds enable it by default, with your saved choice taking precedence.
  • With Debug mode enabled, Help > Send Feedback attaches the log in Apple Mail when Mail is the default client on macOS. Other mail apps and GPUI open a draft asking for the log and reveal the file for you to attach. Review the draft and log before sending.
  • In Jujutsu > Identity, choose Set Up… or Edit… to save the author name and email to your jj user config. The sheet shows the file it will update; saving refreshes identity displays in open windows.
  • Commit avatars can come from GitHub or Gravatar. Multi-window mode keeps one window per repository and deduplicates URL-scheme launches.
  • The Help menu also opens the bundled JayJay Help Book, the full web user guide, jj documentation, and issue reporting.
JayJay Settings appearance panel JayJay Settings appearance panel
Appearance selects the app language, light and dark diff palettes, wallpaper tinting, and a live preview.
JayJay Settings fonts panel JayJay Settings fonts panel
Fonts groups interface and code fonts, line spacing, ligatures, and a diff preview.
JayJay Settings diff panel JayJay Settings diff panel
Diff & Files sets layout, review behavior, rendering defaults, and Auto-expand descriptions.
JayJay Settings workflow panel JayJay Settings workflow panel
Workflow holds confirmations and repository behavior.
JayJay Settings integrations panel JayJay Settings integrations panel
Integrations picks the editor, terminal, and AI providers and shows CLI availability and forge authentication sources.
JayJay Settings Coding Agents section JayJay Settings Coding Agents section
Coding Agents installs the JayJay skill for Claude Code, Codex, and Cursor.
JayJay Settings Jujutsu panel JayJay Settings Jujutsu panel
Jujutsu shows your author identity and resolved jj user config.
Set the jj author name and email Set the jj author name and email
Set the name and email jj records on your changes.
JayJay Settings data and privacy panel JayJay Settings data and privacy panel
Data & Privacy holds statistics, Debug mode, and stored review data.
JayJay Settings about panel JayJay Settings about panel
About selects the Stable or Beta update channel.

GPUI Shell #

On Debian and Ubuntu, the one-line installer installs the matching .deb with apt and resolves its dependencies. On other Linux distributions it installs the AppImage under ~/.local with a jayjay launcher and desktop entry; FUSE is required for AppImages. Both x86_64 and aarch64 are supported:

curl -fsSL https://jayjay.hewig.dev/install.sh | bash

For the newest beta when it is ahead of stable, add --beta. This installs the Debian package on apt systems and the AppImage elsewhere. Run the installer without sudo; it elevates package operations itself:

curl -fsSL https://jayjay.hewig.dev/install.sh | bash -s -- --beta

Debian and Ubuntu users can download the matching .deb (amd64 or arm64) from the same release page and install it with sudo apt install ./jayjay_<version>-1_<architecture>.deb.

Windows support is in beta. Install JayJay from the Microsoft Store and launch it from the Start menu; the Store manages installation and updates. To try a beta, download the Windows x64 portable ZIP from GitHub Releases, extract it, and run jayjay-gpui.exe. Install jj separately on PATH for either distribution. Requires Windows 10 version 1903 or later, or Windows 11. The portable ZIP has no automatic updater.

On Windows, the app menu bar includes minimize, maximize/restore, and close controls. Drag an empty title-bar area to move the window. MSIX installations include taskbar icons for light and dark appearances.

On Arch Linux (x86_64 and aarch64), install jayjay-appimage from AUR, for example with an AUR helper:

yay -S jayjay-appimage

Without a helper, review and build the AUR package as your regular user:

git clone https://aur.archlinux.org/jayjay-appimage.git
cd jayjay-appimage
makepkg -si

The custom pacman repo has been retired. If you previously added it, remove the entire [jayjay] section from /etc/pacman.conf, then install or upgrade jayjay-appimage through AUR. Your repositories and settings stay in place.

For an AppImage beta on Arch, remove an installed jayjay-appimage package with sudo pacman -R jayjay-appimage first, then run the installer with --beta. This avoids having a per-user launcher override the packaged app.

  • To build from source, run just gpui or just gpui /path/to/repo.
  • GPUI's current parity target is Linux. Its macOS build is for development and is not expected to duplicate every SwiftUI integration; the released macOS app remains SwiftUI.
  • Current GPUI coverage includes remote repositories over SSH, graph browsing, multi-change selection and batch actions, diffs, resizable image comparisons, file history with a pinned-base comparison, bisect with manual verdicts or test commands, cloning Git repositories, author identity setup, annotate, evolog with Restore this version, file and per-hunk review with notes, a Bookmark Manager and bookmark menus with rename, pull, and remote selection for tracking, the graph-header Bookmarks picker with its Remote Only section, the title-bar revset bar with its presets popup and symbol completion, creating, pushing, and deleting tags, Run formatters (jj fix), merges with a chosen first parent, drag-and-drop rebase and bookmark moves in the DAG including whole-selection drags, Rebase onto trunk, filterable repository/workspace and bookmark pickers, a grouped repository list with a collapsible, resizable Recent side panel and Forget and Forget & Delete, filesystem refresh, cancelable pull and push, command palette, raw jj commands, searchable help topics that open this guide, a platform-aware keyboard-shortcut reference window, native appearance tracking with light and dark themes tuned to the macOS app, Tab focus cycling with an accent ring on the focused control, readable jj and git errors in every window, the same Settings pages as macOS, with a resizable sidebar, Fonts, and separate light and dark diff palettes, the interface font-size setting, SVG previews, rendered Markdown previews with inline images and offline Mermaid diagrams, HTML external open, diff text selection/copy, file multi-select, workspace windows, switching workspaces in the current window (the window's Overview, Bookmark Manager, evolog, file history, and operation log windows close when it switches), New Workspace from Pull Request, editable keyboard shortcuts in Settings, the Flock page and About bird picker, a history sidebar that hides and shows from the View menu, diff-header line counts, synchronized and line-numbered conflict panes, a Linux jayjay command-line install in Settings > CLI, system default editor and terminal choices that honor $VISUAL, $EDITOR, and $TERMINAL, editable custom tool commands, a typed-path fallback when no desktop file picker is available, launching into the workspace that contains the current directory or the most recent one as a detached process (--foreground keeps it in the terminal), and desktop notifications when a fetch or push finishes in an inactive window.
  • Opening a Git-only folder in GPUI offers jj setup instead of treating it as a failed repository. A folder inside a jj workspace opens that workspace; missing folders and failed initialization still show an error. Long setup paths fit within two lines, and long notification text wraps inside its bubble.
  • GPUI starts filesystem monitoring in the background so opening a repository stays responsive. The watcher does not follow symlinks inside the checkout, avoiding repeated traversal of linked dependency trees such as pnpm’s node_modules.
  • Write coverage includes the full DAG change-operation menu (edit, squash, rebase, merge, parallelize, duplicate, absorb, revert, abandon, and new change), description-aware commit and Describe flows, AI-generated messages via the codex or claude CLIs, direct split and move-to-working-copy actions for historical files, syntax-highlighted working-copy file editing, working-copy file commit and batch actions, workspaces, review notes, conflict resolution including Use Ours and Use Theirs for submodule and other non-text conflicts, and the dedicated multi-file Diff Edit destinations.

Keyboard Shortcuts #

These are the default shortcuts on macOS; change them in Settings > Keyboard Shortcuts.

General
Cmd+OOpen repository
Cmd+Shift+PCommand palette
Cmd+RRefresh
Cmd+,Settings
Cmd+/Keyboard Shortcuts reference
Cmd+Option+FShow the repository in Finder
Return / EscConfirm or cancel the open dialog
View
Ctrl+Cmd+SHide or show the history sidebar
Cmd++ / Cmd+- / Cmd+0Zoom in, zoom out, reset zoom
Repository
Cmd+LEdit the revset filter
Cmd+Shift+BBookmark Manager
Cmd+Shift+ORepo Overview
Cmd+Shift+UUndo from the jj operation log
Graph & File List
Control+ReturnOpen the selected change or file’s context menu; Linux also accepts Menu or Shift+F10
j / k, ↓ / ↑, Ctrl+N / Ctrl+PFollow the selected graph lane, or select the next or previous file
→ / ←, l / hSwitch graph columns; use Tab / Shift+Tab to move between panes
Shift+ClickExtend the selection of changes or files; a direct-parent chain shows one combined diff
Cmd+ClickAdd or remove one change or file; changes that are not adjacent compare oldest to newest
EscReduce a multi-selection to the primary change
Tab / Shift+TabMove focus through panes and controls; Space or Return activates, Esc returns to the pane
Option+ClickOpen a workspace from the repository title picker in a new window
Revset Bar
↓ then ReturnPick and insert a completion
TabFinish the highlighted completion, or the first one
ReturnApply the revset as typed
EscCancel the edit
Review & Diffs
SpaceToggle the selected files reviewed
Cmd+FFind in diff
Return / EscFile filter: keep the query and return to the list, or clear and close it
Cmd+ReturnSave a review note
Cmd+S / EscSave or cancel an Edit File edit
Diff Edit
Cmd+Option+E / Cmd+Option+CExpand or collapse all files
j / k or ↓ / ↑Next or previous file card
← / →, h / lCollapse or expand the focused card
ReturnToggle the focused card
SpaceSelect the focused card's changed lines
EscLeave diff edit
Conflict Editor
Option+← / Option+→Hunk mode: Accept Left or Accept Right for the selected conflict
Option+↑ / Option+↓Hunk mode: previous or next conflict
Drag & Drop
ReturnConfirm a rebase or bookmark drop
EscCancel the drag
Repo Overview
Cmd+FFilter lanes
← / → / ↑ / ↓Move between lanes and their changes
ReturnShow the selection in its workspace window
EscStep back out of a lane panel
Command Palette & Pickers
↑ / ↓ or Ctrl+P / Ctrl+NMove through results
ReturnRun or choose the selected item
EscClose

On Linux, the GPUI shell uses Ctrl for Cmd and Alt for Option (for example, Ctrl+/ and Ctrl+Alt+E); the sidebar toggles with Ctrl+Alt+S, and Ctrl+Alt+F shows the repository in the file manager.

↑ Back to top