Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Keybindings

Margin is keyboard-first with a vim grammar. Press ? in the app for this list. Keybindings are a stability surface (ADR-0021): they only change with a deprecation cycle. The key set is fixed — there is no custom-keymap surface yet.

KeyAction
j / k, Down / Upmove down / up one row
J / Knext / previous hunk
] / [, Tab / Shift-Tabnext / previous file
gg / Gjump to top / bottom
Ctrl-d / Ctrl-u, PgDn / PgUphalf page down / up
/search (regex, smart-case: capitals make it case-sensitive)
n / Nnext / previous match (wrapping)
ffuzzy file picker (type to filter, Up/Down or Ctrl-n/Ctrl-p, Enter jumps, Esc closes)

View

KeyAction
vswitch unified / side-by-side (pins your choice over the width-based auto layout)
wtoggle line wrap (off clips long lines; wrapped rows scroll as one unit)
za / zAcollapse the cursor’s file / everything (vim folds). Lockfiles and generated bundles fold automatically; the collapse config globs extend the list. Collapsed files show a ▸ header with counts; navigation skips their bodies.
btoggle the file sidebar
?toggle help
Escclose help, then clear the active search

The layout defaults to auto: side-by-side when the diff pane is at least 120 columns wide, unified below that. The status bar shows [split] when side-by-side is active, and [wrap] when line wrap is on.

Act on the diff

KeyAction
s / ustage / unstage the hunk under the cursor (index-only; ADR-0013). Refusals report in the status bar. Available in git worktree and --staged reviews.
xdiscard the hunk from the working tree (ADR-0014) — Margin’s only destructive action. Opens a prompt; only typing yes and Enter applies it, Esc cancels. A backup patch lands in .git/margin/trash/ first (margin undo restores). Worktree reviews only. Pass --discard-without-backup to skip the recovery copy for one invocation (ADR-0017); the prompt says so.
mmark the cursor’s file viewed: sidebar checkmark + the file folds (za reopens it without unmarking). Marks persist per review in the data dir ($XDG_DATA_HOME/margin, $MARGIN_DATA overrides) keyed by content digest — a changed file un-views itself, so a rebase keeps only untouched files marked. Patch/pager reviews keep marks session-only.
cnote on the hunk under the cursor (issue #23): a one-line remark shown inline on the hunk header with a ✎ count in the sidebar. Enter saves, empty input deletes, Esc cancels; reopening an annotated hunk pre-fills the text for editing. Notes persist per review beside viewed marks, keyed by a digest of that hunk — an edited hunk drops its note rather than mislabeling new code. Export them with margin --notes (Markdown, with path:line anchors).
rreload the diff from its source (also refreshes the sidebar’s staged markers). With -w this happens automatically after changes, waiting while a discard prompt, the file picker, or the note editor is open; notes and the cursor stay with their hunk

In worktree reviews the sidebar marks files that have staged content with a ● dot, so partial staging is visible at a glance.

Session

KeyAction
q, Ctrl-cquit

Mouse

Strictly additive (issue #26) — everything above works without it. mouse = false in config or --no-mouse disables capture and keeps the terminal’s own text selection.

InputAction
wheelmove the cursor three rows
left click (diff)place the cursor on the clicked row
left click (sidebar)jump to that file
left click (help open)close the help overlay