Diff Reviewer
An IDE-like /diff for the terminal — a stacked file tree and diff on Local Changes, a side-by-side commit graph and diff on Log.
Overview
/diff is a two-tab reviewer — stacked sections on Local Changes, a side-by-side graph and diff on Log when the terminal is wide enough:
- Local Changes — file tree stacked above the diff of the selected file, each section a titled rule rather than a boxed pane, collapsed to the changed lines with incremental expand of unchanged context.
- Log — the git graph/tree (left) | files changed in the selected commit (right).
┌ Diff ─────────────────────────────────────────────────────────┐
│ Local Changes Log (Tab to switch) │
│ source: working tree ▾ │
│ ─ Files 2 files changed ───────────────────────── +16 -7 ──── │
│ › src/foo.ts +12 -3 │
│ README.md +4 -4 │
│ ─ Diff: foo.ts ────────────────────────────────────────────── │
│ 12 export function foo() { │
│ ··· 8 lines ───────────────────────────────────────────────── │
│ -18 const x = old() │
│ +18 const x = new() │
│ Tab tabs · ↑/↓ move · → diff · ← back · ctrl+↑/↓ section · r refresh · Esc close│
└────────────────────────────────────────────────────────────────┘
File tree (Local Changes)
The file list sits above the diff, as a collapsible folder tree rather than a flat list. Files nest under their directories; folders sort first, then files; single-child directory chains compact into one row (like VS Code's compact folders). Folder rows show a caret plus an open/closed icon; file rows show the basename with its per-file +/− stat. When more than one repo is in scope, a per-repo group header sits above its files — collapsible too, so you can fold an entire repo's changes out of the way while keeping its header visible.
Keys: ↑/↓ move, Enter toggles a folder or opens a file, → expands a folder or focuses the diff, ← collapses a folder or focuses the list.
The four sources
The source selector on Local Changes cycles with [/] across three kinds, all feeding the same file-list + diff panes:
- Working tree — uncommitted changes vs
HEAD(the default). - Per-turn — one entry per agent turn in the current session.
- Stash —
stash@{0}…stash@{n}fromgit stash list.
Multi-repo / monorepo grouping
When more than one git repo is in scope, the file list groups per project with a colored swatch, the repo name, file count, and branch:
web 2 files changed · main
src/foo.ts +12 -3
README.md +4 -4
api 1 file changed · dev
src/bar.ts +1 -0
Scope is the cwd's repo, every /add-dir workspace directory, and nested child repos discovered underneath them — the common monorepo shape where sibling folders each carry their own .git and the parent's git status never sees their changes. Discovery is bounded (max depth 3, max 1 500 directories scanned) and skips node_modules/dist/vendor-style noise. A single repo in scope shows no header at all — the flat list you already know.
Collapse & expand
The diff pane shows only changed lines plus 3 lines of context; unchanged stretches collapse to a ··· N lines marker. Activating a marker reveals ±10 more lines, GitHub-style, pulled from the working-tree file. Untracked files no longer show a placeholder — they render as an all-green synthesized diff, syntax-highlighted like any other file.
Nerd-Font file icons
When your terminal font supports it, a per-file-type icon sits next to every filename in both tabs' file lists. On terminals without Nerd Font glyphs, it falls back to plain ASCII markers — no raw glyph is ever emitted unconditionally. Override with CLAUDIN_NERD_FONT=on / off.
Log tab
The left rail is the real branch/merge topology (git log --graph), not a flat list of commits — authors get stable colors, tags render green, branches/HEAD render amber. In a monorepo, [/] cycle which repo's log is shown. The right pane lists the selected commit's changed files with per-file stats and the commit-wide total; drilling into a file (Enter/→) shows its diff at the third level, through the same rendering path as Local Changes, so theme colors and syntax highlighting match exactly.
┌ Diff ─────────────────────────────────────────────────────────┐
│ Local Changes Log (Tab to switch) │
│ ┌ Log ───────────────────────┐┌ Files in dca77a5 ───────────┐ │
│ │ ○ feat: @-mention nav main ││ src/components/x.tsx +20 -4│ │
│ │ ● chore: bump deps ││ src/hooks/y.ts +3 -1│ │
│ │ ├─╮ Merge branch 'fix' ││ │ │
│ │ │ ● fix(ink): vacated rows ││ │ │
│ │ ●─╯ feat(bridge): remote ││ │ │
│ └────────────────────────────┘└──────────────────────────────┘ │
│ main ⟳ ⊗0 ⚠12 Tab tabs · ↑/↓ commits · → files · Esc close │
└────────────────────────────────────────────────────────────────┘
Navigation
| Key | Action |
|---|---|
Tab | switch tabs (Local Changes ↔ Log) |
↑/↓ | move selection in the list, or scroll the diff when it's focused |
←/→ | move focus between the file/commit list and the diff — side by side on Log (≥96 cols), stacked above/below on Local Changes; also collapses/expands a folder on Local Changes |
ctrl+↑ / ctrl+↓ | move focus between the stacked sections on Local Changes, without collapsing or expanding a folder |
[ / ] | cycle the source (Local Changes) or the project (Log, monorepo) |
Enter | open a file / toggle a folder (list focus); grow the next collapsed gap (content focus) |
v | (diff focused) anchor a visual line selection; ↑/↓ extend it, Enter attaches @path#La-Lb to the prompt, Esc cancels |
| mouse drag over the diff | attaches the dragged lines the same way, on release |
a | expand the whole file (Local Changes) |
u / d, g/G | page / jump to ends (content focused, split layout) |
r | manual refresh |
ctrl+g | toggle the reviewer open/closed from anywhere, including from inside the panel |
ctrl+→ / ctrl+← | step focus into the panel / back out to the prompt |
Esc | close (from content focus, returns to the list first) |
Entry points
/diff stays the canonical command. ctrl+g toggles the same overlay open and closed from anywhere, including from inside the panel — it replaced the older gg chord (a g then a quick second g on an empty prompt).
Local Changes stacks its sections at any terminal width. Log keeps its side-by-side graph/files split down to 96 usable columns; below that it falls back to the same one-at-a-time list-then-detail path, so both tabs stay usable everywhere.