Skip to content

Interface Concepts

Buffers and Modes

Majutsu uses several specialized buffer types to provide a rich interface.

Log Buffer

The primary interface for Majutsu. It displays the revision graph, working copy status, and active workspaces. It uses majutsu-log-mode, derived from magit-section-mode.

Diff Buffer

Displays changes between revisions or within the working copy. It supports Magit-style hunk and file sections, word-level refinement, and interactive patching.

Blob Buffer

Allows viewing the contents of a file at a specific revision. You can navigate through the file's history using n and p within the blob buffer.

Process Buffer

Vanilla: Press $ in a Majutsu buffer to inspect the current repository's recent synchronous and asynchronous jj commands, including failures and long-running remote operations.

Evil: Press ` in Normal state for the same per-repository command history, without taking over Evil's $ motion.

JJ description Buffer

JJ descriptions are edited in an edit session. In the background, jj waits for the editor, usually emacsclient via with-editor, to save the description file and return. If the editor exits with a non-zero status, then jj aborts the operation. The most important commands are therefore those for finishing or canceling the edit session.

Key: C-c C-c (with-editor-finish)

Finish the current edit session successfully. jj then uses the description found in the file.

Key: C-c C-k (with-editor-cancel)

Cancel the current edit session with a non-zero editor status, causing jj to abort the operation. Majutsu saves the current text to its in-session description history before canceling.

JJ-generated comment blocks are highlighted using commit-message faces. Lines beginning with JJ: are treated as comments, and JJ: ignore-rest marks the remainder of the buffer as comment. You can customize majutsu-jjdescription-major-mode, majutsu-jjdescription-comment-prefix, majutsu-jjdescription-change-id-face, and global-majutsu-jjdescription-mode. Jujutsu currently does not support changing the comment prefix; the option exists for future compatibility.

Descriptions are also stored in a ring that lives for the duration of the Emacs session. Majutsu saves the current description when an edit session starts, and again when it finishes or is canceled, so older descriptions can be recovered easily.

Key: C-c M-s (majutsu-jjdescription-save-message)

Save the current buffer contents to the description ring.

Key: M-p (majutsu-jjdescription-prev-message)

Cycle backward through the description ring, after saving the current description to the ring. With a numeric prefix ARG, go back ARG entries.

Key: M-n (majutsu-jjdescription-next-message)

Cycle forward through the description ring, after saving the current description to the ring. With a numeric prefix ARG, go forward ARG entries.

Key: C-c M-p (majutsu-jjdescription-search-message-backward)

Search backward through the description ring for a substring match.

Key: C-c M-n (majutsu-jjdescription-search-message-forward)

Search forward through the description ring for a substring match.

Key: C-c C-d (majutsu-jjdescription-show-diff)

Show the diff for the described change. If the buffer contains a JJ: Change ID: line, then use that revision; otherwise fall back to @.

Sections

Majutsu organizes information into collapsible sections. TAB toggles the section at point, such as a revision description in the log or a file in a diff.

Vanilla: n and p move forward and backward through sections.

Evil: C-j and C-k move forward and backward through sections in Normal, Visual, and Motion states; g j and g k move between siblings.

Transient Menus

Commands in Majutsu are grouped into "transient" menus. These popups allow you to select options and flags before executing a command. For example, pressing r opens the Rebase transient.

Primary action entries, such as executing a rebase, squash, split, or upload, also use majutsu-transient-default-action (default RET). When a primary action has its own command-specific key, the transient displays the command key and the default action key on the same row and either key invokes the action.

Some transients support saved defaults. Global defaults follow Transient's normal storage; repository-local defaults use jj's secure repo config-id as the stable project key, so they survive moving the workspace. Where available, W saves the current transient arguments as defaults for the current jj repository only. This is intended for project-shaped UI policy such as log filters, diff format, and Git sync remotes, not for one-off destructive targets.

Visual Selection System

For commands like Rebase, Squash, or Absorb, Majutsu uses a visual selection system. You can mark "source" and "destination" revisions directly in the log buffer, and they will be highlighted with distinct colors until the operation is executed or cleared.

Selection entries that support both manual input and point toggling show both keys on one row, for example -r/r: press the option key to read a revset manually, or the unprefixed key to toggle the revision at point. Majutsu runs these readers, point toggles, and primary actions in the buffer that opened the transient, so repository context, point defaults, and buffer-local selections stay consistent while the transient popup has focus.

Completion and Confirmation

Majutsu integrates with Emacs' completion system (like Vertico or Ivy) for selecting bookmarks, remotes, and revsets. Revset completion candidates are annotated with source labels (pseudo/workspace/bookmark/tag) to make ambiguous names easier to identify. Relation navigation keeps revision ids as the actual candidates and shows descriptions as annotations; structured-row field selection likewise keeps field names canonical while showing value previews as annotations. Destructive operations like abandon or undo will prompt for confirmation.

Running JJ

Majutsu records command output in a process buffer for each repository. Git push/fetch, Gerrit upload, diffedit, and commands waiting for with-editor run asynchronously. Log/diff rendering and most ordinary local mutations wait for jj to finish before the initiating Emacs command returns; the synchronous side-effect runner still services subprocesses such as an Emacs-based GPG pinentry while it waits.