install · quick start · controls · scopes · configuration · limitations · changelog
A code-review pane for herdr. Your agent writes the code. You read its diff in a pane beside the chat, comment on the lines, and send the notes back. You never leave the terminal.

One persistent pane, pointed at a git worktree:
.md file between source and rendered view.It never edits your worktree and sends nothing on its own. The PR tab reads GitHub, GitLab, or Azure DevOps and never posts.
PATH.gh (GitHub), glab (GitLab), or az (Azure DevOps, with the azure-devops extension), authenticated. Only the PR tab needs one.Prebuilt binaries, no Rust toolchain needed:
herdr plugin install persiyanov/herdr-reviewr
Open it in the current workspace:
herdr plugin action invoke open --plugin persiyanov.reviewr
reviewr auto-opens when herdr creates a workspace for a worktree, whether the checkout is new or
opened from disk. auto_open = false keeps it hidden until you ask
(Configuration).
To update, reinstall. Your config is keyed by plugin id and survives:
herdr plugin uninstall persiyanov.reviewr && herdr plugin install persiyanov/herdr-reviewr
Without herdr, reviewr runs as a plain terminal app. Grab a release binary and point it at a repo:
herdr-reviewr ~/some/repo
Everything works except Send and the last turn scope. Those need herdr around.
Open reviewr next to your agent:
j / k moves, the diff follows. Or
] walks the changes hunk by hunk, file after file.Tab switches panes.v, then j / k to extend (or click or drag the gutter).c, type, Enter.s sends every comment to the agent's input.The footer shows the next step. Press ? for every key that works right now.
For a shortcut, bind a key to the toggle in your herdr config (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 name
cmd+… chords reach herdr. Many macOS terminals swallow alt+… themselves.
The keys below are defaults. You can rebind every action, even to several keys at once (Keybindings).
Getting around
| Key | Action |
|---|---|
1 2 3 | Switch tab — Changes / All files / PR |
u b t g | Switch scope — uncommitted / branch / last turn / commits |
B | Pick the base branch |
G | Pick the commits to review |
j k · ↑ ↓ | Move cursor |
] [ | Jump to next / previous hunk |
f F | Jump to next / previous file |
PageUp PageDown | Move a page |
Ctrl+U Ctrl+D | Move a half-page |
Tab | Switch focus |
→ ← | Expand / collapse, or scroll sideways |
/ | Search files and code |
Ctrl+F | Find in file |
w | Toggle line wrap |
m | Preview markdown file |
p | Rotate navigator |
z | Hide / show navigator |
< > | Grow / shrink navigator |
r | Refresh |
? | Open shortcuts helper |
q | Quit |
Reviewing (in the diff)
| Key | Action |
|---|---|
v | Select lines |
c | Comment on line or selection |
e | Edit the comment under the cursor, or open the file in your editor |
d | Delete comment |
n N | Jump to next / previous comment |
l | List all comments |
s | Send comments to agent |
y | Copy comments to clipboard |
esc | Clear selection |
In the comment box
| Key | Action |
|---|---|
Enter | Save comment |
Esc | Cancel |
Shift+Enter · Alt+Enter · Ctrl+J | Insert newline |
Plus the usual caret moves: arrows, Home / End, Ctrl+A / Ctrl+E, Alt+b / Alt+f word
jumps, and Ctrl+W / Ctrl+U / Ctrl+K deletes.
PR tab (read-only)
| Key | Action |
|---|---|
j k | Move through description and comments |
PageUp PageDown | Scroll focused pane |
o | Open PR in browser |
r | Refresh |
The mouse works too. Drag over any text to select and copy it, double-click a word, triple-click a line. Click or drag the line-number gutter to comment. Click files, tabs, and links, and scroll with the wheel.
+/- stats and totals in the header.HEAD (staged, unstaged, and untracked).B (Base branch).G. Read what the agent
committed one step at a time, without its unsaved edits mixed in.reviewr starts in uncommitted. default_scope changes that. Switching with u/b/t/g
wins for the rest of the session. g without a pick opens the picker.
Every scope respects .gitignore, so build output never clutters Changes. To review a file,
track it. All files still browses any ignored path.
CLI flags on the pane command:
| Flag | Default | Meaning |
|---|---|---|
--poll <ms> | 2000 | worktree poll interval (min 200) |
--base <ref> | auto | base for branch scope, any rev, overrides the pick |
--theme <name> | catppuccin | UI + syntax theme (see below) |
--wrap <on|off> | on | soft-wrap long diff lines (w toggles at runtime) |
Everything else lives in reviewr's config file:
~/.config/herdr/plugins/config/persiyanov.reviewr/config.toml
Create it if missing. It is reviewr's file. Settings in herdr's ~/.config/herdr/config.toml
never reach it. reviewr re-reads it on every refresh and toggle, so edits apply without a
relaunch.
The file accepts these keys:
theme = "tokyo-night"
default_scope = "branch"
navigator_position = "right"
toggle_placement = "overlay"
toggle_direction = "down"
auto_open = false
github_host = "github.example.com"
editor = "code -g {file}:{line}"
[keybindings]
comment = ["c", "ㅊ"]
select = ["v", "ㅍ"]
A missing file or omitted key uses its default. An invalid file is rejected whole — the pane shows the error and recovers on the next refresh after you fix it.
One theme colors the whole UI, chrome and syntax together:
theme = "tokyo-night"
--theme overrides the file. Match your terminal's light or dark background. Available:
catppuccin, catppuccin-frappe, catppuccin-macchiato, dracula, nord,
gruvbox, one-dark, solarized, monokai, tokyo-night, rose-pine.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.
The navigator starts on the right. Set navigator_position to right, bottom, left, or
top, or press p to cycle clockwise:
navigator_position = "bottom"
< grows, > shrinks, or drag the divider. z hides the navigator altogether and brings it
back.
The branch scope diffs against the merge-base with your repo's default branch, the one
origin/HEAD names. The header shows the resolved base, vs main.
When the trunk is something else, or you review a stacked branch, press B (or click the
base name) and pick the branch. The pick is stored for this worktree and holds until you
pick again. Other worktrees on the same clone keep their own pick. Choosing the default
branch records that name.
You can also type any revision, like HEAD~2, a tag, or a SHA prefix. The header shows what
resolved: vs HEAD~2 (a1b2c3d).
--base <ref> sets the base for this pane. It wins over the pick and disables the picker.
e opens the file at the line you're on, or the navigator's selected file. On a line you have
already commented, e edits the comment instead.
Set $EDITOR (or $VISUAL) and reviewr opens it at the right line. It knows vim, neovim,
helix, emacs, nano, VS Code and its forks, Zed, Sublime Text, JetBrains, and the rest of the
usual set.
A terminal editor takes the pane, and reviewr refreshes when you quit it. A window editor opens its own window, so the diff stays up and your save turns up in it on the next poll.
Write the command yourself when you need to. {file} and {line} are reviewr's, everything
else is your editor's:
editor = "code -g {file}:{line}"
[keybindings] maps an action name to an array of keys. The array replaces that action's
defaults, actions you don't mention keep theirs, and hints show the first key:
[keybindings]
comment = ["c", "ㅊ"]
select = ["v", "ㅍ"]
Several keys per action serves CJK input sources — bind the character your layout produces on the same physical key.
The action names and their defaults:
| Action | Default |
|---|---|
down / up | j / k |
next-hunk / prev-hunk | ] / [ |
next-file / prev-file | f / F |
scope-uncommitted / scope-branch / scope-last-turn / scope-commits | u / b / t / g |
base-pick / commit-pick | B / G |
tab-changes / tab-all-files / tab-pr | 1 / 2 / 3 |
wrap | w |
preview | m |
navigator-position | p |
navigator-hide | z |
navigator-grow / navigator-shrink | < / > |
select | v |
comment | c |
edit / delete | e / d |
next-comment / prev-comment | n / N |
comments | l |
search | / |
find | ctrl+f |
keys | ? |
send | s, S |
copy | y, Y |
open-pr | o |
refresh | r |
quit | q |
A key is one printable character, or a ctrl+/alt+ chord like ctrl+f. Tab, Esc, and
Enter are fixed. Keys still type normally in the comment box.
The PR tab reads upstream when you have one, otherwise origin. A standard fork clone works
without setup.
GitHub.com, GitLab.com, dev.azure.com, and the *.visualstudio.com organization hosts work
without configuration. For one self-hosted instance per forge, set its bare hostname:
github_host = "github.example.com"
gitlab_host = "git.corp.example"
azure_devops_host = "tfs.corp.example"
Matching is exact. reviewr does not infer SSH aliases like github.com-work — use a
canonical-host remote or an insteadOf rewrite. Authenticate with
gh auth login --hostname github.example.com, glab auth login --hostname git.corp.example,
or az login.
The toggle opens reviewr as a split to the right of your agent. toggle_placement changes the
shape:
toggle_placement = "overlay" # split | overlay | zoomed | tab (default: split)
toggle_direction = "down" # right | down — split only (default: right)
split sits next to your agent. toggle_direction puts reviewr on the right (default) or below.overlay covers the tab. Toggle again to drop back.zoomed fills the tab.tab opens its own tab.Every placement takes the keyboard on toggle. New worktree workspaces auto-open only split and
tab, and never steal focus.
reviewr auto-opens when herdr creates a workspace for a new or existing worktree checkout. Opening
an already-live workspace does not resurrect a reviewr pane you closed there. auto_open = false
makes it wait for the toggle:
auto_open = false # default: true
A layout places reviewr like any other program. Give one pane the command:
command = "herdr-reviewr"
That pane is a full reviewr pane. The install links the binary at ~/.local/bin/herdr-reviewr
and at ~/.local/state/herdr/plugins/persiyanov.reviewr/bin/herdr-reviewr. Use the long path
if ~/.local/bin is not on your PATH.
A layout hook can also invoke the actions, once its panes are in place:
herdr plugin action invoke open --plugin persiyanov.reviewr
open ignores auto_open, and both actions are safe to repeat. They target the focused
workspace. Put herdr-reviewr itself in a layout pane, never the invoke.
The known constraints:
Terminal & theme
Platform
pbcopy, wl-copy, xclip, or xsel. With none installed it
says so, and Send still works.herdr coupling
PR tab (GitHub, GitLab, and Azure DevOps)
gh, glab, or az) and a
recognized upstream or origin. Without either it tells you what to fix, and the other
tabs keep working. Other forges are not supported.upstream is
authoritative, otherwise origin. Clones that target different parent repositories stay
separate.+more marker naming the forge when there is
more.Review model
Budgets
For the dev setup, tests, and benchmarks, see CONTRIBUTING.md. To run your
own build inside herdr panes, link the checkout. herdr plugin link runs the binary you build
at 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 .
After every just install, toggle the reviewr pane off and on. An open pane keeps running the old
process. The loop only works while the plugin is linked: a github:… source in
herdr plugin list runs a downloaded binary that local rebuilds never touch. Switch with:
herdr plugin uninstall persiyanov.reviewr # config is keyed by id and survives
herdr plugin link .
Structured (JSON) export, a side-by-side split view, mark-file-reviewed,
named-key notation for keybindings, OSC light/dark theme autodetect, more themes
(kanagawa, vesper, everforest, ayu, a dark github), a terminal-following palette,
and OSC 52 clipboard.
Change specs live in docs/specs/, one folder per change.
MIT. Syntax highlighting comes from 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:
tokyo-night, tokyo-night-day) — Apache-2.0.rose-pine, rose-pine-dawn) — MIT.Rust
96.9%
Python
1.7%
Shell
1.2%
install · quick start · controls · scopes · configuration · limitations · changelog
A code-review pane for herdr. Your agent writes the code. You read its diff in a pane beside the chat, comment on the lines, and send the notes back. You never leave the terminal.

One persistent pane, pointed at a git worktree:
.md file between source and rendered view.It never edits your worktree and sends nothing on its own. The PR tab reads GitHub, GitLab, or Azure DevOps and never posts.
PATH.gh (GitHub), glab (GitLab), or az (Azure DevOps, with the azure-devops extension), authenticated. Only the PR tab needs one.Prebuilt binaries, no Rust toolchain needed:
herdr plugin install persiyanov/herdr-reviewr
Open it in the current workspace:
herdr plugin action invoke open --plugin persiyanov.reviewr
reviewr auto-opens when herdr creates a workspace for a worktree, whether the checkout is new or
opened from disk. auto_open = false keeps it hidden until you ask
(Configuration).
To update, reinstall. Your config is keyed by plugin id and survives:
herdr plugin uninstall persiyanov.reviewr && herdr plugin install persiyanov/herdr-reviewr
Without herdr, reviewr runs as a plain terminal app. Grab a release binary and point it at a repo:
herdr-reviewr ~/some/repo
Everything works except Send and the last turn scope. Those need herdr around.
Open reviewr next to your agent:
j / k moves, the diff follows. Or
] walks the changes hunk by hunk, file after file.Tab switches panes.v, then j / k to extend (or click or drag the gutter).c, type, Enter.s sends every comment to the agent's input.The footer shows the next step. Press ? for every key that works right now.
For a shortcut, bind a key to the toggle in your herdr config (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 name
cmd+… chords reach herdr. Many macOS terminals swallow alt+… themselves.
The keys below are defaults. You can rebind every action, even to several keys at once (Keybindings).
Getting around
| Key | Action |
|---|---|
1 2 3 | Switch tab — Changes / All files / PR |
u b t g | Switch scope — uncommitted / branch / last turn / commits |
B | Pick the base branch |
G | Pick the commits to review |
j k · ↑ ↓ | Move cursor |
] [ | Jump to next / previous hunk |
f F | Jump to next / previous file |
PageUp PageDown | Move a page |
Ctrl+U Ctrl+D | Move a half-page |
Tab | Switch focus |
→ ← | Expand / collapse, or scroll sideways |
/ | Search files and code |
Ctrl+F | Find in file |
w | Toggle line wrap |
m | Preview markdown file |
p | Rotate navigator |
z | Hide / show navigator |
< > | Grow / shrink navigator |
r | Refresh |
? | Open shortcuts helper |
q | Quit |
Reviewing (in the diff)
| Key | Action |
|---|---|
v | Select lines |
c | Comment on line or selection |
e | Edit the comment under the cursor, or open the file in your editor |
d | Delete comment |
n N | Jump to next / previous comment |
l | List all comments |
s | Send comments to agent |
y | Copy comments to clipboard |
esc | Clear selection |
In the comment box
| Key | Action |
|---|---|
Enter | Save comment |
Esc | Cancel |
Shift+Enter · Alt+Enter · Ctrl+J | Insert newline |
Plus the usual caret moves: arrows, Home / End, Ctrl+A / Ctrl+E, Alt+b / Alt+f word
jumps, and Ctrl+W / Ctrl+U / Ctrl+K deletes.
PR tab (read-only)
| Key | Action |
|---|---|
j k | Move through description and comments |
PageUp PageDown | Scroll focused pane |
o | Open PR in browser |
r | Refresh |
The mouse works too. Drag over any text to select and copy it, double-click a word, triple-click a line. Click or drag the line-number gutter to comment. Click files, tabs, and links, and scroll with the wheel.
+/- stats and totals in the header.HEAD (staged, unstaged, and untracked).B (Base branch).G. Read what the agent
committed one step at a time, without its unsaved edits mixed in.reviewr starts in uncommitted. default_scope changes that. Switching with u/b/t/g
wins for the rest of the session. g without a pick opens the picker.
Every scope respects .gitignore, so build output never clutters Changes. To review a file,
track it. All files still browses any ignored path.
CLI flags on the pane command:
| Flag | Default | Meaning |
|---|---|---|
--poll <ms> | 2000 | worktree poll interval (min 200) |
--base <ref> | auto | base for branch scope, any rev, overrides the pick |
--theme <name> | catppuccin | UI + syntax theme (see below) |
--wrap <on|off> | on | soft-wrap long diff lines (w toggles at runtime) |
Everything else lives in reviewr's config file:
~/.config/herdr/plugins/config/persiyanov.reviewr/config.toml
Create it if missing. It is reviewr's file. Settings in herdr's ~/.config/herdr/config.toml
never reach it. reviewr re-reads it on every refresh and toggle, so edits apply without a
relaunch.
The file accepts these keys:
theme = "tokyo-night"
default_scope = "branch"
navigator_position = "right"
toggle_placement = "overlay"
toggle_direction = "down"
auto_open = false
github_host = "github.example.com"
editor = "code -g {file}:{line}"
[keybindings]
comment = ["c", "ㅊ"]
select = ["v", "ㅍ"]
A missing file or omitted key uses its default. An invalid file is rejected whole — the pane shows the error and recovers on the next refresh after you fix it.
One theme colors the whole UI, chrome and syntax together:
theme = "tokyo-night"
--theme overrides the file. Match your terminal's light or dark background. Available:
catppuccin, catppuccin-frappe, catppuccin-macchiato, dracula, nord,
gruvbox, one-dark, solarized, monokai, tokyo-night, rose-pine.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.
The navigator starts on the right. Set navigator_position to right, bottom, left, or
top, or press p to cycle clockwise:
navigator_position = "bottom"
< grows, > shrinks, or drag the divider. z hides the navigator altogether and brings it
back.
The branch scope diffs against the merge-base with your repo's default branch, the one
origin/HEAD names. The header shows the resolved base, vs main.
When the trunk is something else, or you review a stacked branch, press B (or click the
base name) and pick the branch. The pick is stored for this worktree and holds until you
pick again. Other worktrees on the same clone keep their own pick. Choosing the default
branch records that name.
You can also type any revision, like HEAD~2, a tag, or a SHA prefix. The header shows what
resolved: vs HEAD~2 (a1b2c3d).
--base <ref> sets the base for this pane. It wins over the pick and disables the picker.
e opens the file at the line you're on, or the navigator's selected file. On a line you have
already commented, e edits the comment instead.
Set $EDITOR (or $VISUAL) and reviewr opens it at the right line. It knows vim, neovim,
helix, emacs, nano, VS Code and its forks, Zed, Sublime Text, JetBrains, and the rest of the
usual set.
A terminal editor takes the pane, and reviewr refreshes when you quit it. A window editor opens its own window, so the diff stays up and your save turns up in it on the next poll.
Write the command yourself when you need to. {file} and {line} are reviewr's, everything
else is your editor's:
editor = "code -g {file}:{line}"
[keybindings] maps an action name to an array of keys. The array replaces that action's
defaults, actions you don't mention keep theirs, and hints show the first key:
[keybindings]
comment = ["c", "ㅊ"]
select = ["v", "ㅍ"]
Several keys per action serves CJK input sources — bind the character your layout produces on the same physical key.
The action names and their defaults:
| Action | Default |
|---|---|
down / up | j / k |
next-hunk / prev-hunk | ] / [ |
next-file / prev-file | f / F |
scope-uncommitted / scope-branch / scope-last-turn / scope-commits | u / b / t / g |
base-pick / commit-pick | B / G |
tab-changes / tab-all-files / tab-pr | 1 / 2 / 3 |
wrap | w |
preview | m |
navigator-position | p |
navigator-hide | z |
navigator-grow / navigator-shrink | < / > |
select | v |
comment | c |
edit / delete | e / d |
next-comment / prev-comment | n / N |
comments | l |
search | / |
find | ctrl+f |
keys | ? |
send | s, S |
copy | y, Y |
open-pr | o |
refresh | r |
quit | q |
A key is one printable character, or a ctrl+/alt+ chord like ctrl+f. Tab, Esc, and
Enter are fixed. Keys still type normally in the comment box.
The PR tab reads upstream when you have one, otherwise origin. A standard fork clone works
without setup.
GitHub.com, GitLab.com, dev.azure.com, and the *.visualstudio.com organization hosts work
without configuration. For one self-hosted instance per forge, set its bare hostname:
github_host = "github.example.com"
gitlab_host = "git.corp.example"
azure_devops_host = "tfs.corp.example"
Matching is exact. reviewr does not infer SSH aliases like github.com-work — use a
canonical-host remote or an insteadOf rewrite. Authenticate with
gh auth login --hostname github.example.com, glab auth login --hostname git.corp.example,
or az login.
The toggle opens reviewr as a split to the right of your agent. toggle_placement changes the
shape:
toggle_placement = "overlay" # split | overlay | zoomed | tab (default: split)
toggle_direction = "down" # right | down — split only (default: right)
split sits next to your agent. toggle_direction puts reviewr on the right (default) or below.overlay covers the tab. Toggle again to drop back.zoomed fills the tab.tab opens its own tab.Every placement takes the keyboard on toggle. New worktree workspaces auto-open only split and
tab, and never steal focus.
reviewr auto-opens when herdr creates a workspace for a new or existing worktree checkout. Opening
an already-live workspace does not resurrect a reviewr pane you closed there. auto_open = false
makes it wait for the toggle:
auto_open = false # default: true
A layout places reviewr like any other program. Give one pane the command:
command = "herdr-reviewr"
That pane is a full reviewr pane. The install links the binary at ~/.local/bin/herdr-reviewr
and at ~/.local/state/herdr/plugins/persiyanov.reviewr/bin/herdr-reviewr. Use the long path
if ~/.local/bin is not on your PATH.
A layout hook can also invoke the actions, once its panes are in place:
herdr plugin action invoke open --plugin persiyanov.reviewr
open ignores auto_open, and both actions are safe to repeat. They target the focused
workspace. Put herdr-reviewr itself in a layout pane, never the invoke.
The known constraints:
Terminal & theme
Platform
pbcopy, wl-copy, xclip, or xsel. With none installed it
says so, and Send still works.herdr coupling
PR tab (GitHub, GitLab, and Azure DevOps)
gh, glab, or az) and a
recognized upstream or origin. Without either it tells you what to fix, and the other
tabs keep working. Other forges are not supported.upstream is
authoritative, otherwise origin. Clones that target different parent repositories stay
separate.+more marker naming the forge when there is
more.Review model
Budgets
For the dev setup, tests, and benchmarks, see CONTRIBUTING.md. To run your
own build inside herdr panes, link the checkout. herdr plugin link runs the binary you build
at 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 .
After every just install, toggle the reviewr pane off and on. An open pane keeps running the old
process. The loop only works while the plugin is linked: a github:… source in
herdr plugin list runs a downloaded binary that local rebuilds never touch. Switch with:
herdr plugin uninstall persiyanov.reviewr # config is keyed by id and survives
herdr plugin link .
Structured (JSON) export, a side-by-side split view, mark-file-reviewed,
named-key notation for keybindings, OSC light/dark theme autodetect, more themes
(kanagawa, vesper, everforest, ayu, a dark github), a terminal-following palette,
and OSC 52 clipboard.
Change specs live in docs/specs/, one folder per change.
MIT. Syntax highlighting comes from 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:
tokyo-night, tokyo-night-day) — Apache-2.0.rose-pine, rose-pine-dawn) — MIT.Rust
96.9%
Python
1.7%
Shell
1.2%