Neovim, built into your herdr workspace: a persistent nvim sidebar one key away, with quick access to the files your agent works on.
herdr-nvim.mp4 #
Full-height nvim sidebar, one key to toggle. Your panes move into the left half, and nvim takes the right. Toggle it off, and herdr restores the original layout. Each tab keeps its own persistent nvim, so buffers, cursor, and pending annotations survive the toggle.Fuzzy file picker. It opens on the files your agent touched recently (newest first, with diff stats). Type to fuzzy-search the whole repo.⏎
opens the file in the sidebar at the right line.Code annotations you send to the agent. Comment lines or a selection like a code review. Then send them all to any agent in the workspace (pi, claude, codex), with file:line and git context.
nvim ≥ 0.10 · herdr ≥ 0.7.4 · runs inside a herdr session
Both halves come from this repo:
1. The herdr plugin (sidebar + picker):
herdr plugin install ChmaraX/herdr-nvim
Bind keys to the two actions in ~/.config/herdr/config.toml
(herdr binds none by default):
[[keys.command]]
key = "prefix+e"
type = "plugin_action"
command = "chmarax.herdr-nvim.toggle"
description = "nvim sidebar"
[[keys.command]]
key = "prefix+o"
type = "plugin_action"
command = "chmarax.herdr-nvim.pick-file"
description = "open file from agent output"
2. The nvim plugin (annotations), with lazy.nvim:
{ "ChmaraX/herdr-nvim", opts = {} }
prefix+e
toggles it. Each tab gets its own nvim, backed by a headless daemon that survives the toggle. Two tabs can show two different files in two sidebars. When you close and reopen a sidebar, it loses nothing. herdr removes the daemons of closed tabs automatically.
prefix+o
pops a fuzzy file picker. It has two modes:
Default view (no query): the files touched this session, newest first. It mines edits from the agent's session log and adds uncommitted git changes. For agents that herdr does not track, it scrapes recent pane output instead. The cursor starts on the newest file, so⏎
opens it with no typing.Typing: fuzzy matches across thewhole repo, ranked best first. This includes every file thatgit ls-files
reports, and it honors.gitignore
. The match is on the path and filename, not the file contents.
Each row shows:
- the path, relative to the agent's cwd
- a
new
badge for files created this session - green/red
+N -M
diff stats for uncommitted edits - a relative touched-age (
2m
,3h
)
If you start the picker from a non-agent pane (for example, the sidebar itself), it reads the agent in the same tab. So it searches the repo that you see.
The default view shows the latest max_files
entries (20). A typed query is uncapped.
| Mapping | Action |
|---|---|
<leader>ac |
|
| comment the current line / visual selection | |
<leader>al |
|
list comments (float): hover to jump, ⏎ edit, d delete |
|
<leader>as |
|
| paste all comments into a chosen agent's input | |
<leader>aS |
|
| send all comments to a chosen agent (auto-submits) |
Comments are ephemeral by design: in-memory only, extmark-tracked (they follow your edits), cleared after a successful send. The sent prompt includes each comment's file:line plus the repo and branch, so the agent has context.
For a pending-comment indicator (● 3
) in your statusline:
require("herdr-nvim").statusline()
— it returns ""
when nothing is pending.
Two small config surfaces, one per half:
nvim side — setup{}
opts:
require("herdr-nvim").setup({
prefix = "<leader>a", -- keymap prefix
keymaps = true, -- set false to define your own
clear_after_send = true, -- comments are ephemeral by design
})
herdr side — ~/.config/herdr-nvim/config.toml
(optional; missing or malformed files fall back to these defaults):
[sidebar]
nvim_bin = "nvim" # binary used to spawn the per-tab nvim daemon
position = "right" # right (default), left, top, or bottom
[picker]
scan_lines = 300 # pane lines scanned by the fallback text-scrape
max_files = 20 # session entries shown before you type a query
herdr-nvim doctor # live checks: splits, toggle, daemon, remote-ui
herdr-nvim doctor --with-agent claude # also verify agent registration
Doctor runs labeled checks in a scratch workspace and always removes them
afterward. The most common failure is daemon-healthy
FAIL: the nvim daemon
did not start. Make sure that sidebar.nvim_bin
points at a working nvim ≥ 0.10.
just ci # cargo fmt + cargo test + headless Lua suite