herdr-palette
A Raycast/Linear-style command palette for Herdr, the terminal workspace manager for AI coding agents.
prefix+space opens a centered overlay that fuses every Herdr surface into one
palette: keybindings, plugin actions, custom commands, workspaces, tabs, and
agents. It defaults to a mnemonic tree view, toggles to a flat Raycast-style
list with Ctrl-t, and dispatches safe rows with Enter.
┌ Herdr Palette · catppuccin ─────────────────────────┐
│View TREE > split▏ │
│ ▾ Panes │
│ ▾ Focus │
│ • Previous pane prefix+shift+tab match │
│ ▾ Layout │
│ • Split vertical prefix+v, prefix+| match │
│▶ • Split horizontal prefix+minus match │
└─────────────────────────────────────────────────────┘
What it does
The palette is a read layer over the live Herdr server. It collects:
| Source | How | Count |
|---|---|---|
| Keybindings | herdr-pretty-which binding model |
49 |
| Plugin actions | herdr plugin action list |
2 |
| Custom commands | [[keys.command]] entries |
3 |
| Workspaces | herdr workspace list |
3 |
| Tabs | herdr tab list |
4 |
| Agents | herdr agent list |
4 |
Tree mode preserves mnemonic group context from herdr-pretty-which. Flat list
mode sorts by fuzzy score, dispatchability, source priority, then title.
Dispatch tiers
- Tier A — direct CLI: safe create/focus/split/zoom actions and plugin
actions with fully resolved
command[]arrays. - Tier B — list + resolve + focus: previous/next workspace, tab, and agent cycles. The palette reads the live ordered list, finds the focused row, then focuses the neighbor.
- Reference-only: rows that are keybinding-only or need a target/prompt the palette cannot provide safely yet. These render greyed and ignore Enter.
Build
Requires the herdr-pretty-which crate as a path sibling at
../herdr-pretty-which. That crate provides config loading, action modeling,
discovery, theming, and binding scoring.
Run
# Interactive overlay, when stdout is a TTY.
# Snapshot to stdout for tests/screenshots/non-TTY.
# Diagnose which sources are contributing items.
# Print occupied chords from all collected key sources.
| Flag | Default | Purpose |
|---|---|---|
--config <PATH> |
~/.config/herdr/config.toml |
Config to reflect |
--query <Q> |
"" |
Initial fuzzy query |
--snapshot |
off | Render once to stdout |
--width / --height |
100 / 24 |
Snapshot dimensions |
--debug-kinds |
off | Print item counts by source |
--debug-keys |
off | Print occupied chords |
Keybindings inside the palette
| Key | Action |
|---|---|
Enter |
Dispatch selected row |
↑ ↓ or Ctrl-n / Ctrl-p |
Move selection |
Ctrl-t |
Toggle tree/list view |
← / → |
Collapse, expand, or enter tree groups |
Ctrl-[ / Ctrl-] |
Collapse/expand all tree groups |
Esc / Ctrl-c / Ctrl-d |
Cancel |
Ctrl-u |
Clear query |
| typing | Append to query |
Theming
Inherits your configured Herdr theme via Palette::from_theme: catppuccin,
tokyo-night, dracula, nord, gruvbox, one-dark, solarized, kanagawa, and custom
[[theme.custom]] overrides. The palette uses the same colors as
herdr-pretty-which, so it matches the rest of the Herdr UI.
Herdr plugin manifest
herdr-plugin.toml declares the plugin so Herdr can discover and launch it:
= "ramarivera.palette"
[[]]
= "open"
= "Open palette"
= ["workspace", "tab", "pane", "global"]
= [
"herdr",
"plugin",
"pane",
"open",
"--plugin",
"ramarivera.palette",
"--entrypoint",
"overlay",
"--placement",
"overlay",
"--focus",
]
Bind it to a chord in your Herdr config:
[]
# e.g. open the palette with prefix+space
= "prefix+space"
Architecture
src/
├── main.rs # CLI args and mode dispatch
├── source.rs # collects sources into Vec<Item>
├── items.rs # item constructors and tree metadata
├── dispatch.rs # action-to-dispatch map and runner
└── tui.rs # tree/list state, fuzzy filtering, render loop
The terminal restore path is guarded by drop guards, so a failure mid-loop never leaves your terminal in raw mode.
License
MIT