Diff Reviewer
An IDE-like /diff — two tabs, a collapsible file tree, and a side-by-side diff pane, without leaving the terminal.
Overview
/diff is a two-tab, side-by-side reviewer:
- Local Changes — file tree (left) | diff of the selected file (right), 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 ▾ (←/→ when focus on list, only here) │
│ ┌ Files ─────────────┐┌ Diff: src/foo.ts ───────────────────┐ │
│ │ web 2 files · main ││ 12 export function foo() { │ │
│ │› src/foo.ts +12 -3 ││ ··· 8 lines ─────────────────────── │ │
│ │ README.md +4 -4 ││ -18 const x = old() │ │
│ │ api 1 file · dev ││ +18 const x = new() │ │
│ │ src/bar.ts +1 -0 ││ │ │
│ └────────────────────┘└─────────────────────────────────────┘ │
│ Tab tabs · ↑/↓ files · → diff · ← back · r refresh · Esc close│
└────────────────────────────────────────────────────────────────┘
File tree (Local Changes)
The left pane is a collapsible folder tree, not 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 left list, or scroll the diff when it's focused |
←/→ | move focus between the left list and the right pane (also collapses/expands a folder on Local Changes) |
[ / ] | 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) |
a | expand the whole file (Local Changes) |
u / d, g/G | page / jump to ends (content focused, split layout) |
r | manual refresh |
Esc | close (from content focus, returns to the list first) |
Entry points
/diff stays the canonical command. gg opens the same overlay too — but only when the prompt is empty (vim-style), so it never fires mid-typing.
On narrow terminals (under 100 columns) or outside a fullscreen-capable environment, the reviewer falls back to a stacked list-then-detail layout instead of the side-by-side split, so it stays usable everywhere.