Annotate inside Herdr: comment on any terminal text, review whole Markdown documents and your agent's replies, and send the feedback straight back to the agent. Document review is powered by plannotator-tui, which also runs on its own outside Herdr.
Watch the demos
- Herdr 0.8.0 or later
- macOS, Linux, or Windows
There is no runtime to install. Both installs download a small prebuilt herdr-annotate binary and verify its SHA-256 checksum.
On Linux, install wl-clipboard, xclip, or xsel for clipboard access.
On Windows, native Herdr plugin support is preview/best-effort. Clipboard access uses PowerShell; no extra clipboard package is required. The install, keybinding, configuration check, reload, and use instructions below also apply on Windows.
Pick one. Installing the other later just swaps it (same plugin id). An install stays on the commit it came from; run the same command again to move to the current release.
Full: annotate terminal text, review documents and agent replies, send feedback to the agent. Wraps Plannotator TUI (macOS and Linux today). Demo
herdr plugin install plannotator/herdr-annotateLite: the simple version: select text, prefix+a, comment in a popover. Demo
herdr plugin install plannotator/herdr-annotate/liteRequired. Bind the keys in Herdr's config.
Full install keys: terminal annotations + document and agent-reply review
# Terminal annotations
[[keys.command]]
key = "prefix+a"
type = "plugin_action"
command = "annotate.capture"
description = "annotate text"
[[keys.command]]
key = "prefix+shift+a"
type = "plugin_action"
command = "annotate.copy-context"
description = "copy annotations as context"
[[keys.command]]
key = "prefix+ctrl+a"
type = "plugin_action"
command = "annotate.copy-archive"
description = "copy annotations as context and archive them"
[[keys.command]]
key = "prefix+m"
type = "plugin_action"
command = "annotate.manage"
description = "manage annotations"
# Document review (plannotator-tui)
[[keys.command]]
key = "prefix+o"
type = "plugin_action"
command = "annotate.open"
description = "review documents in this folder"
[[keys.command]]
key = "prefix+shift+o"
type = "plugin_action"
command = "annotate.last"
description = "review the agent's last reply"Lite install keys: terminal annotations only
[[keys.command]]
key = "prefix+a"
type = "plugin_action"
command = "annotate.capture"
description = "annotate text"
[[keys.command]]
key = "prefix+shift+a"
type = "plugin_action"
command = "annotate.copy-context"
description = "copy annotations as context"
[[keys.command]]
key = "prefix+ctrl+a"
type = "plugin_action"
command = "annotate.copy-archive"
description = "copy annotations as context and archive them"
[[keys.command]]
key = "prefix+m"
type = "plugin_action"
command = "annotate.manage"
description = "manage annotations"Check and reload:
herdr config check
herdr server reload-config| Key | Action |
|---|---|
Ctrl+B A |
comment on the selected text · Ctrl+S saves |
Ctrl+B Shift+A |
copy all annotations as Markdown |
Ctrl+B Ctrl+A |
copy all annotations as Markdown, then archive them |
Ctrl+B M |
manage · y copy one · c copy all · Shift+C copy and archive · Tab archives (y copy · u restore · d d delete) |
Copies made inside the manager pane also emit OSC 52, so on Herdr 0.9.0 they reach the clipboard of
the machine you are viewing from even when the plugin runs on a remote server with no clipboard tool
installed; Ctrl+B Shift+A and Ctrl+B Ctrl+A do not, because those actions run outside a pane and
have no terminal to write to.
Full install. Works with Claude Code, Codex, pi, Copilot CLI, Droid, Oh My Pi, Hermes CLI and OpenCode (1 and 2).
| Key | Opens |
|---|---|
Ctrl+B O |
this folder, with a file tree |
Ctrl+B Shift+O |
the agent's recent replies |
Ctrl-click a file://…md link |
that file |
Send (or E) makes the review the agent's next message. q closes.
| Option | Where |
|---|---|
| Agents request reviews themselves | npx skills add plannotator/herdr-annotate --skill plannotator-tui -g |
| Open as full tab, split, or popup | [herdr] placement = "overlay" | "split" | "popup" in ~/.config/plannotator-tui/config.toml |
| Use without Herdr | plannotator-tui |
Over SSH or herdr --remote, the plugin runs on the server, and two things get in the way:
Herdr's default copy-on-select clears the selection on mouse-up, and the prefix keypress
clears whatever selection remains before a bound action runs
(herdrdev/herdr#3380). A headless server also
has no clipboard for the plugin to fall back to.
What works today:
-
On the server, keep the selection after mouse-up:
# remote server: ~/.config/herdr/config.toml [ui] copy_on_select = false # the selection stays; copy explicitly with Ctrl+C
-
Trigger the action without a keypress in Herdr, while the selection is still highlighted. From your laptop, bound to any key in your terminal or OS:
ssh <host> herdr plugin action invoke annotate.capture # named session on the server: ssh <host> HERDR_SESSION=<name> herdr plugin action invoke annotate.capture
The action reads the focused pane's selection through Herdr's API, which never touches the keyboard path, so the text arrives. Verified: the same selection gives
selected_textthis way and nothing throughprefix+a. -
In Neovim, use the mapping below; it hands the selection over in a file.
Server-side key bindings and herdr --remote <host> --remote-keybindings server are still
needed for the manager (prefix+m) and other plugin keys; without the flag, herdr --remote
uses your local keys and drops plugin bindings. prefix+a itself will work once
herdrdev/herdr#3380 is fixed.
Herdr Annotate reads text that Herdr copies to the system clipboard. The plugin cannot read selection state from Neovim or another terminal application.
The plugin is a Rust binary in rust/.
cargo test --manifest-path rust/Cargo.toml
cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings
bash scripts/stage-local.sh # build and stage bin/herdr-annotate.exe
herdr plugin link "$PWD" # or "$PWD/lite" for the Lite variantherdr plugin link does not run manifest build hooks, so stage the binary first. It also replaces
any existing annotate link; link the other directory to switch back.
bash scripts/lite-regression.sh checks the runtime against goldens recorded from the retired Bun
runtime. docs/lite-testing.md covers what it compares and everything else
that guards Lite.
To test a local plannotator-tui build instead of the pinned release, put it in bin/
before linking: PLANNOTATOR_TUI_BIN=/path/to/plannotator-tui bash scripts/fetch-plannotator-tui.sh.
Before a release, HERDR_SESSION=<disposable session> bash scripts/smoke.sh installs fresh, upgrades
from the first shipped commit, installs lite, swaps to full, and opens the manager and review panes,
then restores whatever was installed.
Add this visual-mode mapping to ~/.config/nvim/lua/config/keymaps.lua for LazyVim, or to init.lua:
vim.keymap.set("x", "<leader>a", function()
-- Hand the selection to the plugin through a file: works on headless servers too.
vim.cmd('normal! "zy')
local base = os.getenv("XDG_RUNTIME_DIR")
if not base or base == "" then base = vim.fn.fnamemodify(vim.fn.tempname(), ":h") end
local dir = base .. "/herdr-annotate-" .. vim.loop.getuid()
vim.fn.mkdir(dir, "p", "0700")
vim.fn.writefile(vim.split(vim.fn.getreg("z"), "\n"), dir .. "/selection")
vim.fn.jobstart({ "herdr", "plugin", "action", "invoke", "annotate.capture" })
end, { desc = "Annotate in Herdr" })Select text with the mouse or Visual mode. Then press <leader>a to open Herdr Annotate.
The file is read once and removed; a file older than 15 seconds is ignored.
LazyVim uses Space as <leader> by default. The mapping keeps mouse support and leaves normal Neovim commands unchanged.
