herdr (plugin)
herdr is a terminal multiplexer with workspaces, panes and a plugin API. herdr-plugin-gwm wires gwm into it: create, switch, remove, review a PR, exec and clean across worktrees, and gwm’s own TUI in a pane, with each worktree reflected as a herdr workspace.
The plugin is glue-only bash. It holds no worktree logic of its own: every script is gwm <cmd> --format=json → jq → a herdr CLI call, riding the frozen 1.0 JSON contract of list, path and doctor.
The one rule
Section titled “The one rule”The plugin never calls
herdr worktree createorworktree open --branch. Creation and removal always go through gwm; herdr only reflects, viaworktree open --path(adopt) andworkspace close/workspace focus.
That is what keeps a single source of truth. Break it and herdr starts creating git worktrees outside gwm’s control: two writers on the same repo, drifting apart on the first gwm remove. The plugin enforces it rather than documenting it: one helper (adopt_worktree) is the only path to herdr, and a grep-assert in its test suite fails the build if any script reaches around it.
Install
Section titled “Install”| Channel | Command |
|---|---|
| herdr marketplace | herdr plugin install kbrdn1/herdr-plugin-gwm |
| Local checkout | herdr plugin link "$PWD" |
There is no build step: plain bash, nothing to compile.
Requirements: herdr ≥ 0.7.4 (popup panes) · gwm on PATH · jq · fzf · bash · macOS or Linux.
The actions
Section titled “The actions”Invoke from any pane inside a herdr workspace sitting in a gwm-managed repo:
herdr plugin action invoke gwm.switch| Action | What it does | Opens as |
|---|---|---|
gwm.create |
branch type → issue number → description → gwm create, then adopts the new worktree, resolved by its linked issue |
split pane |
gwm.switch |
fzf over gwm list --format=json with live badges (issue #N, PR#N, dirty ±, ahead ↑, behind ↓), focuses the workspace if herdr already reflects the pick, adopts otherwise |
popup |
gwm.remove |
fzf over removable worktrees (never the main checkout) → confirm gate → gwm remove (branch kept) → workspace close |
popup |
gwm.review |
fzf over gh pr list → gwm review <N> materialises the PR as its own worktree → adopt |
split pane |
gwm.exec |
gwm exec -- <cmd> across every worktree, with a ✓/✗ rollup |
split pane |
gwm.clean |
gwm clean reports reclaimable build artifacts, deletes after a confirm |
split pane |
gwm.dashboard |
gwm’s TUI, as-is | zoomed pane |
Pick-and-go pickers are session-modal popups so the tiled layout does not move; the panes whose output is the point (exec, clean) or that run long git or network work (create, review) stay split: a modal that blocks the session for a 30-second clone reads as frozen.
Two things happen without being invoked:
- A clicked GitHub PR URL (
https://github.com/<owner>/<repo>/pull/<N>) triggersgwm.review. The pattern is anchored and the script re-extracts the number itself, so only an integer ever reaches gwm, never a raw URL. worktree.created, fired when a worktree is created on the herdr side, outside gwm, runsgwm bootstrapon its path so it gets the same file copies, hooks and preset as agwm createone. Adopts fireworktree.opened, not.created, so this never double-runs on the plugin’s own work.
Binding a key
Section titled “Binding a key”In ~/.config/herdr/config.toml, then herdr server reload-config:
[[keys.command]]key = "prefix+ctrl+shift+g"type = "plugin_action"command = "gwm.switch"description = "gwm: switch worktree"Configuration
Section titled “Configuration”Presentation only: the plugin has no behaviour to configure, since gwm owns the behaviour. Create ~/.config/herdr/plugins/config/gwm/config.toml (or run herdr plugin config-dir gwm):
# "workspace" (default) → adopt as a nested worktree workspace in the sidebar.# "tab" → lighter: open a tab with the worktree cwd.open_mode = "workspace"
# "user" (default) → inherit your FZF_DEFAULT_OPTS (colors, borders); the picker# only neutralizes file-browser bits that would garble# non-file lines or rebind keys.# "clean" → drop FZF_DEFAULT_OPTS entirely for a bare picker.fzf_theme = "user"Worktrees are adopted under the repo’s root workspace, so invoking an action from inside a linked-worktree pane does not hit herdr’s linked_worktree_source rejection.
Limits
Section titled “Limits”Multi-repo mode (gwm --workspace) is not wired through the actions yet: the plugin operates on the single repo of the current workspace. Everything else (create, switch, remove, review, exec, clean, dashboard, bootstrap-on-create) is implemented.