--- name: herdr description: "Control herdr from inside it. Manage workspaces and tabs, split panes, spawn agents, read output, and wait for state changes — all via CLI commands that talk to the running herdr instance over a local unix socket. Use when running inside herdr (HERDR_ENV=1)." --- # herdr — agent skill you are running inside herdr, a terminal-native agent multiplexer. herdr gives you workspaces, tabs, and panes — each pane is a real terminal with its own shell, agent, server, or log stream — and you can control all of it from the cli. this means you can: - see what other panes and agents are doing - create tabs for separate subcontexts inside one workspace - split panes and run commands in them - start servers, watch logs, and run tests in sibling panes - wait for specific output before continuing - wait for another agent to finish - spawn more agent instances the `herdr` binary is available in your PATH. its workspace, tab, pane, and wait commands talk to the running herdr instance over a local unix socket. if you need the raw protocol or full api reference, read [`SOCKET_API.md`](./SOCKET_API.md). ## concepts **workspaces** are project contexts. each workspace has one or more tabs. unless manually renamed, a workspace's label follows the first tab's root pane — usually the repo name, otherwise the root pane's current folder name. **tabs** are subcontexts inside a workspace. each tab has one or more panes. **panes** are terminal splits inside a tab. each pane runs its own process — a shell, an agent, a server, anything. **agent state** is detected automatically by herdr. each pane can be: - `idle` — agent finished and the state is calm - `working` — agent is actively working - `blocked` — agent needs input or approval - `unknown` — no recognized agent plain shells still exist as panes, but herdr's sidebar agent section intentionally focuses on detected agents rather than listing every shell. **ids** — workspace ids look like `1`, `2`. tab ids look like `1:1`, `1:2`, `2:1`. pane ids look like `1-1`, `1-2`, `2-1`. these are compact public ids for the current live session. important: ids can compact when tabs, panes, or workspaces are closed. do not treat them as durable ids. re-read ids from `workspace list`, `tab list`, `pane list`, or create/split responses when you need a current id. do not guess that an older `1-3` is still the same pane later. ## discover yourself see what panes exist and which one is focused: ```bash herdr pane list ``` the focused pane is yours. other panes are your neighbors. list workspaces: ```bash herdr workspace list ``` ## tab management list tabs in the current workspace: ```bash herdr tab list --workspace 1 ``` create a new tab: ```bash herdr tab create --workspace 1 ``` rename it: ```bash herdr tab rename 1:2 "logs" ``` focus it: ```bash herdr tab focus 1:2 ``` close it: ```bash herdr tab close 1:2 ``` ## read another pane see what is on another pane's screen: ```bash herdr pane read 1-1 --source recent --lines 50 ``` - `--source visible` = current viewport - `--source recent` = recent scrollback as rendered in the pane - `--source recent-unwrapped` = recent terminal text with soft wraps joined back together ## split a pane and run a command split your pane to the right and keep focus on your current pane: ```bash herdr pane split 1-2 --direction right --no-focus ``` that prints json with the new pane nested at `result.pane.pane_id`. parse that value, then run a command in that pane: ```bash NEW_PANE=$(herdr pane split 1-2 --direction right --no-focus | python3 -c 'import sys,json; print(json.load(sys.stdin)["result"]["pane"]["pane_id"])') herdr pane run "$NEW_PANE" "npm run dev" ``` split downward instead: ```bash herdr pane split 1-2 --direction down --no-focus ``` ## wait for output block until specific text appears in a pane. useful for waiting on servers, builds, and tests. for `--source recent`, matching uses unwrapped recent terminal text, so pane width and soft wrapping do not break matches. `pane read --source recent` still shows the pane as rendered. if you want to inspect the same transcript that the waiter matches, use `pane read --source recent-unwrapped`. ```bash herdr wait output 1-3 --match "ready on port 3000" --timeout 30000 ``` with regex: ```bash herdr wait output 1-3 --match "server.*ready" --regex --timeout 30000 ``` if it times out, exit code is `1`. ## wait for an agent state block until another agent reaches a specific state: ```bash herdr wait agent-state 1-1 --state idle --timeout 60000 ``` useful when you need another agent to finish before you proceed. ## send text or keys to a pane send text without pressing Enter: ```bash herdr pane send-text 1-1 "hello from claude" ``` press Enter or other keys: ```bash herdr pane send-keys 1-1 Enter ``` `pane run` sends the text and then a real `Enter` key in one request: ```bash herdr pane run 1-1 "echo hello" ``` ## workspace management create a new workspace: ```bash herdr workspace create --cwd /path/to/project ``` create one without focusing it: ```bash herdr workspace create --no-focus ``` focus a workspace: ```bash herdr workspace focus 2 ``` rename: ```bash herdr workspace rename 1 "api server" ``` close: ```bash herdr workspace close 2 ``` ## close a pane ```bash herdr pane close 1-3 ``` ## recipes ### run a server and wait until it is ready ```bash NEW_PANE=$(herdr pane split 1-2 --direction right --no-focus | python3 -c 'import sys,json; print(json.load(sys.stdin)["result"]["pane"]["pane_id"])') herdr pane run "$NEW_PANE" "npm run dev" herdr wait output "$NEW_PANE" --match "ready" --timeout 30000 herdr pane read "$NEW_PANE" --source recent --lines 20 ``` ### run tests in a separate pane and inspect the result ```bash herdr pane split 1-2 --direction down --no-focus herdr pane run 1-3 "cargo test" herdr wait output 1-3 --match "test result" --timeout 60000 herdr pane read 1-3 --source recent --lines 30 ``` ### check what another agent is working on ```bash herdr pane list herdr pane read 1-1 --source recent --lines 80 ``` ### watch another pane robustly use this pattern when you need to coordinate with a sibling pane: ```bash # inspect what is already there herdr pane read 1-3 --source recent --lines 40 # wait only for the next output you expect herdr wait output 1-3 --match "ready" --timeout 30000 # if you need to inspect the same transcript the waiter matched, # read the unwrapped recent text directly herdr pane read 1-3 --source recent-unwrapped --lines 40 ``` ### spawn a new agent and give it a task ```bash herdr pane split 1-2 --direction right --no-focus herdr pane run 1-3 "claude" herdr wait output 1-3 --match ">" --timeout 15000 herdr pane run 1-3 "review the test coverage in src/api/" ``` ### coordinate with another agent ```bash herdr wait agent-state 1-1 --state idle --timeout 120000 herdr pane read 1-1 --source recent --lines 100 ``` ## notes - `workspace list`, `workspace create`, `tab list`, `tab create`, `tab get`, `tab focus`, `tab rename`, `tab close`, `pane list`, `pane get`, `pane split`, `wait output`, and `wait agent-state` print json on success. - `pane read` prints text, not json. - `pane read --source recent-unwrapped` is useful when you want to inspect the same unwrapped transcript that `wait output --source recent` matches against. - `pane send-text`, `pane send-keys`, and `pane run` print nothing on success. - parse ids from `workspace create`, `tab create`, and `pane split` responses when you need new ids. for `pane split`, the new pane id is at `result.pane.pane_id`. - use `pane read` for current output that already exists. use `wait output` for future output you expect next. - `--no-focus` on split, tab create, and workspace create keeps your current terminal context focused. - if you are running inside herdr, the `HERDR_ENV` environment variable is set to `1`.