The key words MUST, MUST NOT, SHOULD, SHOULD NOT and MAY in this skill are to be interpreted as described in BCP 14 (RFC 2119, RFC 8174) when, and only when, they appear in all capitals.
Locating this skill's helpers (do this first). The steps below run bundled scripts. You execute from the target repo, not from this skill's directory, so a path written relative to this skill will not resolve. Resolve the base directory once and use it everywhere — including in any subagent prompt, which MUST receive the literal absolute path:
SKILL_DIR="<this skill's base directory>" # your harness provides it when the skill loads
# If you don't have it, discover it:
SKILL_DIR=$(find ~/.claude ~/.config ~/.agents -type d -name 'tmux-agent-herdr-lite' 2>/dev/null | head -1)
test -d "$SKILL_DIR/assets" || test -d "$SKILL_DIR/scripts" # verify before proceeding
On invocation — install, then serve the request
help first. When the invocation asks for help (/tmux-agent-herdr-lite help, "how do I use this", "what are the keys"), run bash "$SKILL_DIR/scripts/agent-cheatsheet" and show its output verbatim as the answer, then mention prefix a h opens the same guide inside tmux. Skip the steps below for a pure help request.
When this skill fires (slash command or auto-trigger), immediately do this — it is idempotent, so do it every time rather than asking:
-
Run the installer from this skill's directory:
bash "$SKILL_DIR/scripts/install.sh"It generates
~/.tmux/agent-panes/tmux-agent.confpointing at this skill'sscripts/in place (nothing is copied onto PATH), wires asource-fileline into~/.tmux.conf(before any TPMrunline), wires the optional tmux-resurrect/continuum persistence layer when TPM is present, generates a zsh shell hook and sources it from~/.zshrc, installs the optional convenience shell functions (tm,tp, …; opt out withAGENT_SHELL_FUNCS=off), merges Claude Code status hooks into~/.claude/settings.jsonbeside existing hooks (opt out withAGENT_CLAUDE_HOOKS=off), and reloads a running tmux server. Both opt-outs persist across later runs. No network needed. -
Verify the result (see "Verification" below) and report the outcome. Tell the human to open a new shell (or
source ~/.zshrc) so the shell hook activates, and that Claude sessions started before the install report exact status only after a restart (until then the scan adopts and screen-reads them). -
Then serve the user's actual request — checking status, coordinating panes — using the commands in this skill's
scripts/directory, invoked by path.
Zero-command auto-tracking (the core model)
The human never runs a launcher. Three layers find agents, each covering the previous one's blind spot:
- Shell hook — the installed zsh hook (
agent-shell-hook.zsh, sourced from~/.zshrc) watches for a known agent binary (claude,codex,gemini, …) being run at the prompt in any tmux pane. Onpreexecit registers that pane (bash "$SKILL_DIR/scripts/agent-observe" register); onprecmd(the agent exited) it deregisters it. It checks the alias-expanded command too, soalias ccl='claude …'is tracked. - Adoption — every scan lists agent processes, reads their
TMUX_PANE, and registers panes nothing else saw (tmux-resurrect restores, agents started before install, wrappers the shell gate misses). - Agent hooks — Claude Code reports its own lifecycle (
agent-hook, installed into Claude's settings), so itsworking/blocked/done/errorare exact rather than read off the screen.
The scan/summary/jump pipeline then tracks the pane exactly as if it were launched by agent-pane. Dead panes are pruned by agent-status-scan, so the fleet is always live-agents-only. agent-pane still exists but is optional — only for worktree isolation or scripted fan-out where you want to spawn an agent programmatically.
The two surfaces
- Humans use tmux only. They just run their agent (
claude,codex, …) in any pane — it is tracked automatically. Everything else lives under one prefix key —prefix aopens the cockpit key-table, then a single lowercase key (m= menu,d= dashboard, jumps, etc.). You SHOULD NOT tell the user to runagent-*commands; point them atprefix aand the menu. - Agents use the scripts. The
agent-*commands inscripts/are the coordination API (Herdr socket-API equivalents). Invoke them by path from this skill directory (bash "$SKILL_DIR/scripts/agent-pane"and siblings). Full reference:references/commands.md; recipes:references/coordination-recipes.md; what is and isn't ported from Herdr:references/herdr-parity.md.
Keybindings installed (the human surface)
The cockpit deliberately claims exactly one prefix key (prefix a) and puts every
action in its own agent key-table. This guarantees it never collides with your own
bindings and never needs Shift — pane navigation, splits, zoom, copy-mode, and the
status-bar layout stay entirely yours.
prefix a then:
d dashboard/help popup
m command menu — new agent pane, jump, worktree, resume
s refresh agent statuses (status scan)
t session/window/pane tree
h user guide popup (scripts/agent-cheatsheet)
b jump: next blocked agent
e jump: next error (crashed) agent
w jump: next working agent
i jump: next idle agent (idle also matches done)
f jump: next finished/done agent
Jumps cycle: pressing the same key again moves to the next agent in that state, wrapping around.
The cockpit does not rebind pane navigation, splits, zoom, or copy mode — use your own.
It only adds additive settings (mouse, vi copy mode, focus events, pane border titles) and
sets window tabs to show the folder (#{b:pane_current_path}) instead of the running command.
The fleet summary is not force-injected into your status bar; add it yourself with
#(scripts/agent-status-summary) in your status-right.
Convenience shell functions (optional, human-facing)
Session shortcuts for the human's own shell, separate from the agent cockpit. The installer sources assets/tmux-shell-functions.zsh from ~/.zshrc. Rerunning it with AGENT_SHELL_FUNCS=off removes them and the choice persists across later runs until AGENT_SHELL_FUNCS=on. A name the human already owns (their own function, an alias, or a command such as the tv fuzzy finder) is left alone. Each opener attaches from outside tmux and switches client from inside it, so none of them nest tmux.
| Function | Does |
|---|---|
tm |
attach/create the session named after the current directory (./: → _) |
tp [name] |
fzf picker over sessions, attached first; Esc falls back to tm; with a name, attach/create it |
tv [file] |
cwd session that starts in nvim (optionally on file) |
tn <name> |
attach/create a session with an explicit name |
tms [name] |
the same over SSH to $TMS_HOST (fzf or numbered picker on the remote) |
tw <branch> |
git worktree at ../<repo>-<branch> (slashes flattened) plus a session for it; reuses an existing one only if it is this repo on that branch |
twd [-f] |
remove the current linked worktree and kill its session; refuses the main checkout, and keeps a dirty worktree unless -f |
Mention these when the human asks how to open, pick, or clean up sessions; agents keep using the agent-* API below.
The agent coordination API (scripts/)
agent-workspace— create or attach theagentscockpit session.agent-pane [--agent <kind>] [--cwd <dir>] <name> <command...>— launch and register an agent.agent-list [--json]— registry with statuses.agent-status-scan/agent-status-summary/agent-dashboard— status pipeline.agent-jump <state>— focus the next pane in a state (repeat to cycle).agent-hook claude— Claude Code hook entry point (status from the agent itself);agent-hook install-claude <settings.json> [--remove]is the installer's merge step.agent-explain <target>— why a pane classified the way it did.agent-read <target> [--lines N] [--source recent]— read another pane.agent-send <target> <text>/--keys Enter— type (no Enter) or press keys.agent-run <target> <command>— send command + Enter atomically.agent-wait <target> --status done | --match <regex>— block on status/output (--status idlealso matchesdone).agent-notify <name> <status> [msg]— toast/sound (fired automatically on transitions).agent-resume [--dry-run] [<name> --session-id <id>] [--force]— relaunch dead agents; native resume.agent-worktree create|open|remove|list <branch>— per-agent git worktree isolation.agent-cheatsheet— print the reference.
Runtime state lives under ~/.tmux/agent-panes/. Targets accept an agent name, window name, or pane id; names are stable, pane ids are not.
Recommended agent workflow
- Install + verify (steps above), then create or attach the cockpit:
scripts/agent-workspace. - To launch an agent, just run it in a pane (
claude,codex, …) — the shell hook tracks it. Useagent-paneonly when you need worktree isolation or scripted spawning (agent-worktree create <branch> --window, then--cwd). - Coordinate instead of watching:
agent-wait tests --status done,agent-read reviewer --lines 40,agent-send backend --keys Enter. Recipes:references/coordination-recipes.md. - Route attention:
agent-jump blocked(notifications fire on blocked/error/done transitions automatically; the human'sprefix a bdoes the same). - Verify real outcomes separately — a
donestate means the pane looks finished, not that the work is correct. Debug a wrong status withagent-explain <name>, never by guessing. - After a tmux server restart, recover with
agent-resume(add--session-id <id>to reopen a native CLI session, e.g.claude --resume).
Output style. Write reports and explanations for the user in about 80% ASD-STE100 Simplified Technical English. Use short sentences, common words, active voice and one action per step. This style is for prose to the user, not for the code, prompts or files that this skill makes.
Status model
Statuses are routing hints, not truth:
error— crash or non-zero exit; distinct fromblocked(a crashed agent needs a look, not an answer).blocked— a known approval/question UI for the pane's agent, a live interactive prompt (password, y/N) at the pane bottom, or an explicit blocked marker.working— active output, a spinner title, or the agent's own "esc to interrupt" chrome.idle— quiescent, or a finished pane already viewed.done— completion sentinel or finished-agent prompt chrome; focusing the pane demotes it toidle(viewed), Herdr-style.unknown— the pane is gone or metadata is incomplete.
For Claude Code the status comes from its own hooks (reason: hook <Event> in agent-explain/the dashboard) and outranks every screen rule. Everything else falls back to screen detection, which is two-layered, ported from Herdr's manifests: panes with a known agent (--agent or inferred from the command) are classified by that agent's screen rules plus the pane title — loose word heuristics are skipped so an agent discussing an error is not mislabeled, and unknown prompts fall back to idle, never blocked. Unrecognized commands use generic tail heuristics where explicit AGENT_STATUS: sentinels and real failure signals outrank loose words. Per-agent rules can be replaced by dropping <agent>.json into ~/.tmux/agent-panes/detect/ (format in references/commands.md). The classifier is pure and unit-tested (scripts/agent_classify.py, assets/test_agent_classify.py, run by make gate).
For best accuracy, instruct coding agents to print explicit markers — they outrank every heuristic:
AGENT_STATUS: working
AGENT_STATUS: blocked reason="needs approval"
AGENT_STATUS: done result="tests passed"
Files in this skill
scripts/install.sh— idempotent installer (generates config referencing scripts in place).scripts/agent-observe— auto-register/deregister a pane's agent; called by the zsh hook (the zero-command core).scripts/agent-pane,scripts/agent-workspace— optional explicit launch/register, cockpit session.scripts/agent-status-scan,scripts/agent-status-summary,scripts/agent-dashboard,scripts/agent-jump,scripts/agent-explain— status pipeline.scripts/agent-list,scripts/agent-read,scripts/agent-send,scripts/agent-run,scripts/agent-wait— coordination commands.scripts/agent-notify,scripts/agent-resume,scripts/agent-worktree,scripts/agent-menu,scripts/agent-cheatsheet— notifications, persistence, isolation, menus.scripts/agent_classify.py,scripts/agent_registry.py— pure classifier (per-agent manifests) and target resolution.scripts/agent-hook,scripts/agent_hooks.py— Claude Code status hooks, the settings.json merge, and process adoption.assets/tmux-agent.conf(template;@AGENT_BIN@is substituted at install),assets/tmux-agent-persistence.conf— tmux configuration.assets/agent-shell-hook.zsh(template;@AGENT_BIN@/@AGENT_ROOT@/@AGENT_NAMES@substituted at install) — the zsh preexec/precmd hook that makes agents auto-track.assets/tmux-shell-functions.zsh— optional human shortcuts (tm,tp,tv,tn,tms,tw,twd), sourced from~/.zshrcby the installer.assets/test_agent_classify.py,assets/test_agent_hooks.py,assets/test_cockpit_scripts.sh— stdlib unit suites and offline shell suite (run bymake gate).references/commands.md,references/coordination-recipes.md,references/herdr-parity.md— full CLI reference, recipes, Herdr parity map.
Common pitfalls
- Do not tell the human to run
agent-*commands — point them atprefix a(thenmfor the menu,dfor the dashboard); the commands are the agent-facing API. - Do not expect exact Zellij or Herdr behavior — no plugin runtime, no socket event push;
agent-waitpolls. Seereferences/herdr-parity.md. - Do not tell the human to use
agent-panefor normal work — agents are auto-tracked by the zsh hook when run in any pane.agent-paneis only for worktree isolation or scripted spawning. After install, remind the human to open a new shell (orsource ~/.zshrc) so the hook activates. - Do not trust
doneas correctness, and do not answer ablockedprompt blind —agent-readthe question first. - Notifications default to tmux toasts + sound; set
AGENT_NOTIFY=offorAGENT_NOTIFY_SOUND=offin noisy environments.
Verification
After running the installer:
tmux -V
# Exactly ONE source line for the config, and it must sit before any TPM run line:
grep -n 'source-file .*agent-panes/tmux-agent.conf\|run .*tpm/tpm' ~/.tmux.conf
"$SKILL_DIR/scripts/agent-workspace"
"$SKILL_DIR/scripts/agent-pane" smoke 'echo AGENT_STATUS: working; sleep 1; echo ok; sleep 5'
"$SKILL_DIR/scripts/agent-wait" smoke --status done --timeout 30
"$SKILL_DIR/scripts/agent-explain" smoke
"$SKILL_DIR/scripts/agent-list" --json
Inside tmux, prefix a d opens the dashboard popup, prefix a m opens the menu with "New agent pane", and (if you added the snippet to status-right) the status bar shows the fleet summary. The skill's unit suite passes via make gate-skill SKILL=tmux-agent-herdr-lite.