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.
jjthen 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
jjto 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.