An oil.nvim-style explorer for herdr. The directory listing is a text buffer. Rename, create, delete, move and copy by editing lines with vim keys, then :w. A fuzzy finder, live grep and a project switcher live in the same popup.
▸ ~/atlas/ [+] pending +2 ~2 ⧉1 −2 :w name + ◆ benches/render.rs + ▸ notes/ ▸ assets/ 2 items ▸ docs/ 2 items ~ ▸ bin/ 1 item ▸ src/ 2 items ▸ tests/ 1 item ◆ Cargo.toml 60B ↪ DESIGN.md → docs/design.md 14B ◆ LICENSE 12B ⧉ ▤ LICENSE-APACHE 12B ~ ◆ INTRO.md 72B
Needs Rust (cargo). bat and ripgrep are optional; they power previews and grep when installed.
# clone, then link (the build hook runs cargo build --release)
git clone https://github.com/christineecker/herdr-oil
herdr plugin link "$PWD/herdr-oil"
herdr server reload-config
# ~/.config/herdr/config.toml [[keys.command]] key = "prefix+d" # explorer type = "plugin_action" command = "herdr-oil.explorer" [[keys.command]] key = "prefix+shift+f" # fuzzy files type = "plugin_action" command = "herdr-oil.finder" [[keys.command]] key = "prefix+slash" # live grep type = "plugin_action" command = "herdr-oil.grep" [[keys.command]] key = "prefix+shift+o" # projects (any free chord) type = "plugin_action" command = "herdr-oil.projects"
Options go in $(herdr plugin config-dir herdr-oil)/config.toml. See config.example.toml for the editor, open target, Trash or permanent delete, and display settings.
Captured from a herdr pane running the release binary against a sample project. The keys under each screen are exactly what was sent. Nerd Font icons are shown as simple glyphs here.
Each line carries a hidden id, as in oil.nvim. This is the same rule set the planner uses, reduced to one directory. Type in the boxes, duplicate a line, delete one, add a new one.
Edits from all visited directories are planned together. Validation runs first, so a clash stops the save before any file moves.
| Where the entry's id appears now | Operation |
|---|---|
| nowhere | DELETE to the Trash, or permanently if configured |
| at its original path, plus other places | kept; every other place is a COPY |
| only somewhere else | first place is a MOVE (same folder shows as RENAME), the rest are copies |
| a line with no id | CREATE; a trailing / makes a directory, a/b/c.txt creates parents |
Copies are made first, while every source is still untouched, into hidden staging names.
A moved entry is parked inside the nearest folder that never moves. That makes swaps, case-only renames and "move the child out, delete the parent" safe.
Creates and staged entries land at their final paths, re-rooted under folders that were renamed. An occupied path is reported and the entry is put back.
Validation rejects two lines with the same name, a name that already exists and is not being vacated, moving a folder into itself, absolute paths, and an id line that was emptied. On macOS names are compared case-insensitively, which is how the session above caught DESIGN.md landing next to design.md.
g? inside the popup shows the full sheet.
The default open = "view" shows the file highlighted and scrollable in the oil window; e edits it in $EDITOR in the same popup. open = "auto" instead types $EDITOR file into the pane you came from when it idles at a shell prompt, and never types names that contain control characters.
The suggested prefix d, prefix ⇧F and prefix / are free in herdr’s defaults. If a key does nothing, a built-in action on the same chord wins; set that built-in to "" in [keys].
Esc keeps its vim meaning first: it leaves insert, visual or command mode and cancels a half-typed key. On a clean slate in normal mode it closes the popup, after a save, discard or cancel prompt when edits are unsaved.
Split and tab targets run exec $EDITOR, so quitting the editor closes the pane. Typing into the origin pane does not use exec.
Every save is reviewed by default. confirm = false skips it, except when something would be deleted.
u undoes buffer edits only. Deleted files can be restored from the Trash; renames and moves have no history.
Moving a relative symlink into another folder does not rewrite it, so it can break. The DESIGN.md move in the screens is an example.
herdr gives popups no readable pane id, so the captures were taken in a normal herdr pane running the same binary.
The planner and apply engine tests run on temporary folders: swaps, case-only renames, nested renames, recursive copies with symlinks, and no leftover staging files.
herdr-oil exists because of oil.nvim by Steven Arcangeli. The central idea comes from oil: the directory listing is an ordinary editable buffer where every line carries a hidden entry id, and saving diffs that buffer against the disk and asks before applying creates, renames, moves, copies and deletes. Keys like - for the parent directory and g. for hidden files follow oil too.
herdr-oil is an independent Rust reimplementation for herdr popups, not a port, and uses no oil.nvim code. If you live in Neovim, use the original.
Every file in the plugin, in reading order. Search filters to lines that contain the text.