Skip to content

Navigation Menu

Sign in
Sign up

Repository files navigation

Pouch β€” store instructions for LLMs while they work in Herdr

Pouch

A Herdr plugin for stashing prompts before an agent needs them, and inserting them when it is ready.

Queue the next three instructions while the agent is still working, then hand them over one keypress at a time. Text is typed into the input, never submitted β€” you always press Enter yourself.

β”Œ 1 πŸ‘œ ┬ 2 ┬ + ─────────────────────────────────────────────────────────────┐
β”‚ > implement the retry logic β”‚

Install

Requires Herdr 0.7+ and Node 22.6+ or Bun . No build step, no clone.

herdr plugin install AltanS/herdr-pouch
herdr plugin action invoke setup --plugin herdr.pouch

Expected setup output:

βœ“ plugin installed from GitHub, nothing to link
βœ“ cli installed ~/.local/bin/herdr-pouch
βœ“ keys prefix+shift+o, prefix+shift+i, prefix+shift+a bound
βœ“ keys work prefix+shift+o, prefix+shift+i, prefix+shift+a reach Pouch

βœ“ did it. Β· nothing to do. ! needs you, with the remedy on the same line. Re-running setup is safe, and it is how you repair an install.

Setup writes one marked block to ~/.config/herdr/config.toml, between # pouch:begin keybindings and # pouch:end keybindings. Anything outside those markers is yours, and is never rewritten β€” a chord you already use is reported and left alone. Uninstall removes exactly that block. Setup also keeps a backup at ~/.config/herdr/config.toml.pouch-backup, and uninstall leaves it there.

setup --no-keys skips the config entirely, so you can bind herdr.pouch.<action> yourself.

Check it worked: herdr-pouch add "run the tests" in any pane. The pane wears a πŸ‘œ, and prefix+shift+O opens the pouch. Until a pouch holds a message, Pouch shows nothing β€” that is normal, not a failed load.

Update and remove

herdr plugin action invoke update --plugin herdr.pouch # routine update
herdr plugin action invoke update-major --plugin herdr.pouch # crossing a major
herdr plugin action invoke uninstall --plugin herdr.pouch

herdr-pouch update and herdr-pouch uninstall do the same from a shell. Update advances the checkout and re-links it β€” Herdr caches the action set at link time, so a release that adds an action answers plugin_action_not_found until it is linked again.

Uninstall keeps your stashed messages. They are your writing, not a cache. --purge deletes them too, --dry-run shows what would go, and --keep-config leaves config.toml alone.

Installs older than 0.3.0 have no update action: cd <checkout> && git pull --ff-only && herdr plugin link "$PWD".

Use

Stash from anywhere β€” a shell, a script, or one agent preparing work for another:

herdr-pouch add "run the full test suite and report only failures"
herdr-pouch add --pane w1:p3 "now write the changelog entry"
git log -1 --format=%B | herdr-pouch add --agent reviewer
key does
prefix+shift+O open the pouch for the focused pane
prefix+shift+I insert the top message
prefix+shift+A write a new message in the editor

Insert-and-submit ships unbound β€” every free chord was taken. Bind herdr.pouch.insert-top-submit yourself, or invoke it from the action menu.

Inside the popup:

key effect
↑↓ / jk move Β· g/G jump to ends
1–9 insert that slot and close
enter insert the selected message and close
space / i insert without closing β€” for queueing several
/ filter as you type; enter keeps it, esc clears it
y copy to the clipboard (OSC 52)
n Β· e Β· d new Β· edit Β· delete
J / K reorder (clear the filter first)
p switch pouch β€” every pouch on disk, live agent or not
I choose which pane inserts go to
q / esc close

Clicking a row selects it; clicking it again inserts.

surface scope works when
pane border, a πŸ‘œ that pane the pane shares a tab with another
tab label that tab the pane is alone in its tab and has no border
agent sidebar, $pouch every pane your rows name the token (see Config)
the strip that pane pinned with herdr-pouch strip β€” costs three rows

A pouch outlives the pane it was filled for. When that agent is gone the pouch has no destination, so I (or any insert) asks which pane to send to. p, herdr-pouch browse and the Pouch: browse all pouches action are the only way back into an orphan.

Nothing showing?

  1. The pouch is empty β€” an empty pouch paints nothing, on purpose.
  2. A remote client kills all three keys. Herdr applies the foreground client's keybindings to the whole server, and herdr --remote sends a profile that drops every [[keys.command]] entry. Attach with herdr --remote <host> --remote-keybindings server, or use the action menu.
  3. herdr plugin action invoke doctor --plugin herdr.pouch, then read herdr plugin log list --plugin herdr.pouch. It says which case you are in.
  4. herdr server reload-config after any config edit. Herdr does not hot-reload config.toml.
  5. herdr plugin list confirms the plugin is registered at all.

CLI

command does
add [target] [text...] stash a message (reads stdin when no text)
list [target] [--all] show a pouch, or every pouch with --all
show <ref> [target] print one message in full
insert [ref] [target] type it into the agent's input (--submit, --to <pane>)
rm <ref>, clear remove a message, or empty the pouch
strip, unstrip pin or remove the three-row strip under a pane
open, browse the popup for one pouch, or the picker over all of them
sync, key repaint the indicators; print the resolved pouch identity
setup, update, uninstall install, advance, remove

Targets β€” --here (the calling pane, default) Β· --pane w1:p3 Β· --agent <name> (a live agent name, or a saved pouch label). Refs β€” a 1-based slot number, a message id, or a unique text prefix.

Config

~/.config/herdr/plugins/config/herdr.pouch/config.json. All keys optional.

key default effect
editor "builtin" what n and e open. "builtin" is Pouch's own box (ctrl-s saves, esc cancels); "system" is $VISUAL/$EDITOR; anything else runs as a command with the file appended
consumeOnInsert false remove a message once it has been used
focusAfterInsert true focus the agent pane after inserting, so Enter submits
indicator "πŸ‘œ" the mark on the border or tab label; {count} is replaced with the count
maxChipWidth 34 widest strip chip, in columns
pollMs 500 how often the strip re-reads the pouch

POUCH_EDITOR, POUCH_CONSUME=1 and POUCH_NO_FOCUS=1 override the file for one run. POUCH_STATE_DIR moves the store.

The count is also a $pouch token for the sidebar:

[ui.sidebar.agents]
rows = [["state_icon", "workspace", "tab", "$pouch"], ["agent"]]

Where things are stored

~/.local/state/herdr/plugins/herdr.pouch/ β€” one JSON file per pouch under pouches/, plus the derived bookkeeping (aliases, pinned strips, tab marks, workspace labels) that sync rebuilds.

A pouch is keyed by (workspace label, cwd, agent), never by pane id: pane ids are not reused, change on move, and are regenerated when the server restarts. So the pouch you filled yesterday is still on the same agent this morning, and renaming a workspace migrates its pouches rather than stranding them. Every write takes a lock and re-reads inside it, so the popup, the strip, the CLI and Herdr's event hooks can never clobber each other.

Development

git clone git@github.com:AltanS/herdr-pouch.git && bun install
herdr plugin link "$PWD" # re-run after ANY manifest change
bun run lint && bun x tsc --noEmit && bun run test

All three gates must pass. bun run test also runs the CLI under both Node and Bun, which is what catches syntax that Node's type-stripping cannot handle. See CLAUDE.md for the versioning rules and the Herdr API traps.

License

MIT Β© Altan Sarisin

About

Herdr plugin: stash prompts for an agent ahead of time and insert them when it's ready

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

AltStyle γ«γ‚ˆγ£γ¦ε€‰ζ›γ•γ‚ŒγŸγƒšγƒΌγ‚Έ (->γ‚ͺγƒͺγ‚ΈγƒŠγƒ«) /