Tmux pane observability for Hermes Agent — four tools that let the agent see what's running in tmux, send text/keys into panes, wait for output to appear, and share pane context between the user and the agent. Tmux's tricky flag combinations and failure modes are baked into the tool defaults so the model never has to remember them.
| Tool | What it does |
|---|---|
tmux_list |
List panes with stable %pane_id, session/window, current command, working dir, dead/alive. |
tmux_capture |
Read a pane's contents as text (ANSI stripped). Defaults to the TUI surface — what's on screen right now. Pass include_normal_scrollback: true to read the history that's scrolled out of view. |
tmux_send |
Type text (typing mode) or send a key-name sequence (keystroke mode). Defaults: literal text, press Enter after. Pass keys: ["C-c", ...] for keystrokes; include "Enter" in the list to submit. Returns a 5-line post_send_capture snapshot. |
tmux_wait |
Block until a substring (or regex, with regex: true) appears in the pane, or time out. Returns the last ~30 lines on both paths. Pass async: true to return immediately — the result arrives as a follow-up message. |
The agent could write raw tmux capture-pane -t %12 and tmux send-keys. The plugin isn't saving keystrokes — it's removing failure modes the model hits with raw tmux:
- Flag gotchas baked in.
capture-paneneeds-J(joined lines),-q(suppress spurious alternate-screen errors), and the-aflag has semantics opposite of the manpage wording. The model gets these wrong. The plugin gets them right by default. - Injection guards. The agent's own pane is off-limits to
tmux_send— a stale%pane_idcan't inject keystrokes into the agent's input. Key names starting with-(useMinus, not-) are caught before tmux interprets them as flags. - ANSI stripped. The model almost never wants raw escape sequences in its context window. The plugin strips them automatically.
- Polling wait and async. No raw-tmux equivalent for
tmux_wait— the model would need 3+ chained terminal calls and a hand-rolled polling loop. The async mode lets the agent continue other work during long waits.
The plugin doesn't replace the terminal. The agent can still run raw tmux when it needs something the tools don't cover (spawning windows, resizing, anything lifecycle-related). The tools handle the common patterns where getting tmux's flags right matters.
hermes plugins install git@github.com:m4dni5/hermes-tmux.git
hermes plugins enable hermes-tmuxThe tools appear whenever the tmux binary is on PATH — the agent doesn't have to be inside a tmux session to drive one.
hermes-tmux/
├── pyproject.toml # pytest config
├── plugin.yaml # name, version, provides_tools
├── __init__.py # register(ctx) — wires the 4 tools
├── schemas.py # 4 tool schemas (what the model reads)
├── tmux_tools.py # 4 handlers (what runs)
├── README.md
├── AGENTS.md
├── DESIGN.md
├── LICENSE
└── tests/ # pytest suite (one file per tool)
├── conftest.py
├── test_tmux_list.py
├── test_tmux_capture.py
├── test_tmux_send.py
└── test_tmux_wait.py
MIT