A code-review sidebar for herdr. Your agent writes the code; you read its diff in a pane beside the chat, leave comments on the lines, and send the notes back — without leaving the terminal.
What you get, in one persistent pane pointed at a git worktree:
- A diff to review — the agent's changed files, syntax-highlighted, scoped to uncommitted, branch, or last turn.
- Line comments that stay put — select a range, write a note; it renders as a card under the code instead of hiding behind a marker.
- One keystroke back to the agent — Send drops every comment into the agent's input as
path:start-end — comment, ready for you to add context and hit enter. - More when you need it — browse the whole worktree, not just the diff, and read the branch's open pull request without switching windows.
- Themed to match your terminal — 18 named palettes (Catppuccin, Dracula, Nord, Gruvbox, Tokyo Night, Rosé Pine, Solarized, and more, in dark and light), one config line away.
It never edits your worktree and sends nothing on its own. Its only write to git is a private
last-turn baseline ref under refs/reviewr/. The PR tab reads GitHub but never posts there.
- herdr ≥ 0.7.0 (the plugin system).
- git on
PATH. - A truecolor (24-bit) terminal with Unicode box-drawing support; a light or dark theme to match it (see Theme).
- macOS or Linux.
gh(the GitHub CLI), authenticated — optional, only for the PR tab. Everything else works without it.
From the herdr marketplace — a prebuilt binary, no Rust toolchain:
herdr plugin install persiyanov/herdr-reviewrThe sidebar auto-opens for a newly created worktree — installing the plugin is enough. It can
also stay hidden until asked, with auto_open = false (see Configuration). To
toggle it on demand, bind a key to the reviewr: toggle sidebar action in your herdr config
(keybindings live in user config, not the plugin manifest):
[[keys.command]]
key = "cmd+r"
type = "plugin_action"
command = "persiyanov.reviewr.toggle" # <plugin_id>.<action_id> — note the id, not the namecmd+… chords reach herdr; macOS swallows alt+…. With no key bound, run it once with
herdr plugin action invoke toggle --plugin persiyanov.reviewr.
Beside toggle there are two explicit actions, made for scripts and layout plugins. open opens
the sidebar and does nothing when one is already open. close closes it and does nothing when none
is. Both are bindable and invokable the same way, as persiyanov.reviewr.open and
persiyanov.reviewr.close. See Auto-open and layout plugins for
the layout recipe.
The core loop takes five keys. Open the sidebar next to your agent and:
- Pick a file. The agent's changed files are in the right pane.
j/kmoves the cursor; the diff opens on the left as you go. - Focus the diff. Press
Tabto move from the file list into the diff. - Select the lines. Press
v, thenj/kto extend the selection (or click-drag). - Comment. Press
c, type your note,Enterto save. It stays on screen as a card under the line. - Send. When you're done, press
s. Every comment lands in the agent's input aspath:start-end — comment— you add context and send.
The footer always shows the keys that work right now, so you can learn it by using it. The tables below are the full reference.
Getting around
| Key | Action |
|---|---|
1 2 3 |
Switch tab — Changes / All files / PR |
u b t |
Switch scope — uncommitted / branch / last turn |
j k · ↑ ↓ |
Move the cursor in the focused pane |
PageUp PageDown |
Move a page · Ctrl+U Ctrl+D move a half-page |
Tab |
Switch focus between the file list and the diff |
→ ← |
Expand / collapse a directory or expand a fold; otherwise scroll the diff sideways |
w |
Toggle line wrap |
] [ |
Widen / narrow the file list |
r |
Refresh now |
q |
Quit |
Reviewing (in the diff)
| Key | Action |
|---|---|
v |
Start a line selection, then j / k to extend (or click-drag) |
c |
Comment on the selection — or on the current line |
e d |
Edit / delete the comment under the cursor |
n N |
Jump to the next / previous comment |
l |
List every comment |
s |
Send all comments to the agent |
y |
Copy all comments to the clipboard |
esc |
Clear the selection |
In the comment box
| Key | Action |
|---|---|
Enter |
Save · Esc cancel |
Shift+Enter · Alt+Enter · Ctrl+J |
Insert a newline |
Plus the usual caret moves: arrows, Home / End, Ctrl+A / Ctrl+E, word-jump with
Alt+b / Alt+f, and Ctrl+W / Ctrl+U / Ctrl+K to delete by word or to the line edge.
PR tab (read-only)
| Key | Action |
|---|---|
j k |
Move through checks and comments |
PageUp PageDown |
Scroll the selected comment |
o |
Open the PR in your browser |
r |
Refresh |
herdr is mouse-native, so clicking a file, dragging to select lines, clicking a tab or the Send
button, and the scroll wheel all work too.
- Changes — the changed files for the active scope, with
+/-stats; pick a file to read its syntax-highlighted diff. This is where you review and comment. - All files — browse the whole worktree tree, not only what changed; the diff pane renders any
file's current content. Git-ignored paths show too, dimmed — a wholly-ignored directory
(
target/,node_modules/) is one collapsed row that loads its contents only when you expand it. You can comment here as well. - PR — a read-only mirror of the branch's open pull request, read from GitHub via
gh: its state (draft / open / merged / closed, mergeability, unpushed-commit sync), its checks with a pass/fail rollup, and its comments (reviews, inline findings, plain comments, newest first, withresolved/outdatedmarkers).oopens it in the browser. It only reads GitHub — never posts, resolves, re-runs, or merges.
- uncommitted — the working tree vs
HEAD(staged, unstaged, and untracked). - branch — the working tree vs the merge-base with the base branch (
origin/main→origin/master→main→masterby default, set viabase_branchesor--base). A superset of uncommitted that adds the branch's committed work. - last turn — only what the agent changed since its most recent turn started (see Limitations).
Every scope respects .gitignore, so build output never clutters Changes. To review a file,
track it in git — an ignored-but-intentional file (a plan, a sample env) belongs in the repo,
where it shows as a change and ages out once committed. All files can still browse any ignored
path, dimmed, even untracked ones.
CLI flags on the pane command:
| Flag | Default | Meaning |
|---|---|---|
--poll <ms> |
2000 |
worktree poll interval (min 200) |
--base <ref> |
auto | base branch for branch scope, overrides base_branches |
--theme <name> |
catppuccin |
UI + syntax theme (see below) |
--wrap <on|off> |
on |
soft-wrap long diff lines (w toggles at runtime) |
Everything else is set in reviewr's own config file:
~/.config/herdr/plugins/config/persiyanov.reviewr/config.toml
Create the file if it does not exist yet. herdr hands this directory to the plugin as
$HERDR_PLUGIN_CONFIG_DIR, but the path above is where it lives on disk. Note that this is
reviewr's file, not herdr's — settings added to herdr's own ~/.config/herdr/config.toml are
never read by reviewr.
One theme colors the whole UI — chrome and syntax together. Set it in reviewr's config file (re-read on refresh, so editing it and refreshing re-themes without relaunch):
# ~/.config/herdr/plugins/config/persiyanov.reviewr/config.toml
theme = "tokyo-night"--theme overrides the config file (handy for a dev run). Use a name your terminal's light/dark
matches — a light theme on a dark terminal (or the reverse) reads poorly, since the pane keeps
the terminal's background. Available:
- Dark:
catppuccin,catppuccin-frappe,catppuccin-macchiato,dracula,nord,gruvbox,one-dark,solarized,monokai,tokyo-night,rose-pine. - Light:
catppuccin-latte,gruvbox-light,one-light,solarized-light,github-light,tokyo-night-day,rose-pine-dawn.
Names match herdr's where both ship a palette. An unknown name falls back to catppuccin.
The branch scope diffs against the merge-base with a base branch. reviewr tries an ordered
list of candidates and uses the first that exists in your repo, so one setting works across repos
with different trunks. The default is origin/main, then origin/master, main, master.
To review against a different base — a develop trunk, say — set base_branches in the same
config file (re-read on refresh, so editing it and pressing r re-bases without relaunch):
# ~/.config/herdr/plugins/config/persiyanov.reviewr/config.toml
base_branches = ["origin/develop", "origin/main", "main", "master"]reviewr picks the first entry that exists in the repo. A --base <ref> flag still wins when it
names an existing ref. A missing or malformed config falls back to the default list.
By default the toggle opens reviewr as a split to the right of your agent. You can change how it
opens by setting toggle_placement in the same config file. reviewr re-reads the file on every
toggle, so a change takes effect the next time you press the key.
# ~/.config/herdr/plugins/config/persiyanov.reviewr/config.toml
toggle_placement = "overlay" # split | overlay | zoomed | tab (default: split)
toggle_direction = "down" # right | down — split only (default: right)splitsits next to your agent and leaves the keyboard with it. Settoggle_directionto put reviewr on the right (the default) or below.overlaycovers the whole tab with reviewr and hands it the keyboard. Toggle again to drop back to your agent.zoomedfills the tab the same way as overlay and hands reviewr the keyboard.tabopens reviewr in its own tab and hands it the keyboard.
When you create a new worktree, reviewr auto-opens only for split and tab. With overlay or
zoomed it stays out of the way until you press the toggle yourself. Any value it does not
recognize falls back to the default. You can also turn the auto-open off entirely — see below.
reviewr auto-opens for every new worktree by default. To make it wait for the toggle key instead,
set auto_open = false in the same config file:
# ~/.config/herdr/plugins/config/persiyanov.reviewr/config.toml
auto_open = false # default: trueDo this when another plugin arranges your new worktrees — for example
herdr-plus worktree layouts. Both plugins react to the
same worktree event and race each other, and either can lose: the layout may be skipped entirely,
or reviewr may land as a split in the middle of it. With auto_open = false reviewr leaves fresh
workspaces alone, the layout builds undisturbed, and the toggle key opens reviewr on top of it in
whatever placement you configured.
A layout can also open reviewr itself, deterministically, once its panes are in place:
herdr plugin action invoke open --plugin persiyanov.reviewr
open ignores auto_open — an explicit call is you asking. It opens with your configured
placement and does nothing when a sidebar is already open, so a layout can run it on every pass.
Two things to know. The action opens reviewr in the focused workspace, so invoke it while the
new workspace has focus. And it opens reviewr as its own new pane — a layout pane whose command
is the invoke will exit once the invoke returns, so run it as a one-shot command from your layout
hook, not as a pane that should stay.
This is a focused, young tool. The known constraints, honestly:
Terminal & theme
- Truecolor required — colors are 24-bit RGB with no 256/8-color fallback; basic terminals render wrong.
- Theme must match the terminal — the pane keeps the terminal's background, so a light theme on a dark terminal (or the reverse) reads poorly. There's no auto light/dark detection yet, so you set the theme to match by hand.
- Add / remove are red / green — no secondary cue for colorblind users yet.
- Unicode box-drawing glyphs are required (no Nerd Font needed).
Platform
- macOS and Linux only — no Windows.
- Clipboard export uses
pbcopy(macOS) orwl-copy/xclip/xsel(Linux); if none is installed it says so and you use Send instead. (OSC 52 and Windows are roadmap.)
herdr coupling
- Send needs a resolvable agent pane — the agent in your tab, or the sole agent in the workspace; otherwise it no-ops and keeps your comments. Browsing and diffing need no herdr.
- last turn is poll-based (2 s default): a turn that starts and finishes inside one poll is never snapshotted on its own, so the scope shows everything since the last observed turn start — never lines the agent didn't write, but possibly more than one turn.
PR tab (GitHub)
- GitHub-only and read-only — needs an authenticated
ghand a GitHub remote; without either it shows one remediation line and the rest of the app (Changes, All files) is unaffected. - Mirrors only the branch's open PR — a merged or closed PR shows as history; comment
surfaces are capped at one page (100 rows each), with a
+more on GitHub ↗marker when there's more.
Review model
- Comments are in-memory and single-session — closing the pane loses any you haven't sent or copied out.
- Bulk only, consume-on-success — Send (or copy-to-clipboard) delivers the whole set and clears it: no duplicates, no per-comment send. A failure leaves everything in place.
- No line-number rebasing — a comment's diff snippet, not its line number, keeps it locatable; stale comments are flagged, never silently dropped.
- One sidebar per worktree — two on the same worktree race the baseline ref, last writer wins.
Budgets
- Files over 2 MB or 50,000 lines show a "too large" notice; binary files aren't diffed.
For contributors. herdr plugin link skips the download build step, so place a locally built
binary where the pane command looks for it — $HERDR_PLUGIN_ROOT/bin/herdr-reviewr:
git clone https://github.com/persiyanov/herdr-reviewr
cd herdr-reviewr
just install # build release → bin/herdr-reviewr, ad-hoc re-signed on macOS
herdr plugin link .just install replaces the binary with a fresh file and ad-hoc re-signs it. On Apple Silicon that
matters: overwriting a code-signed binary in place invalidates its signature, and macOS then
SIGKILLs it at launch — so a plain cp target/release/herdr-reviewr bin/ makes the pane open and
close instantly.
The dev loop after the first link:
- Edit the code.
just install— rebuilds and re-signs the binary underbin/.- Relaunch the sidebar — toggle it off and back on with your keybind. The open pane keeps running the old process until you relaunch it, so a rebuild alone changes nothing on screen.
This works only while the plugin is linked, not installed from the marketplace. Check with
herdr plugin list: a github:… source means the pane runs a downloaded binary under
~/.config/herdr/plugins/github/, so local rebuilds never appear no matter how often you
just install. Switch a GitHub install to a dev link:
herdr plugin uninstall persiyanov.reviewr # config is keyed by id and survives
herdr plugin link .Customizable keybindings, structured (JSON) export, in-diff search, a side-by-side split view,
mark-file-reviewed, OSC light/dark theme autodetect, more themes (kanagawa, vesper,
everforest, ayu, a dark github), a terminal-following palette, and OSC 52 clipboard.
The living design lives in specs/ — one concept per doc, always current.
MIT. Syntax highlighting via syntect and two-face; most themes' syntax colors come from two-face's bundled set.
Bundled .tmTheme syntax files in assets/, each under its own license:
- Catppuccin Mocha — MIT.
- Tokyo Night (
tokyo-night,tokyo-night-day) — Apache-2.0. - Rosé Pine (
rose-pine,rose-pine-dawn) — MIT.
