by ogulcancelik
herd your agents. terminal workspace manager for AI coding agents.
# Add to your Claude Code skills
git clone https://github.com/ogulcancelik/herdryou 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:
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.
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 calmworking — agent is actively workingblocked — agent needs input or approvalunknown — no recognized agentplain 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 , . tab ids look like , , . pane ids look like , , . these are compact public ids for the current live session.
herdr is a terminal-native agent multiplexer for coding agents.
it runs inside your existing terminal: ghostty, alacritty, kitty, wezterm, even inside tmux. a single rust binary that gives you workspaces, tiled panes, automatic agent detection, and notification alerts without asking you to leave the terminal for a separate gui window, electron wrapper, or web dashboard.
it is also becoming a shared control surface. you manage agents in herdr, and increasingly those agents can interact with herdr too through its local socket api, cli commands, and the example agent skill in this repo.
https://github.com/user-attachments/assets/043ec09f-4bdd-41d5-aee0-8fda6b83e267
most tools in this space try to replace your environment.
herdr takes the opposite approach. it lives where cli agents already live, keeps mouse and keyboard both first-class, and adds the missing layer: awareness and coordination for running multiple agents in parallel.
that means two things:
herdr is opinionated about workspaces.
it does not start by asking you to create an empty named project or pick a folder in a setup flow. you create a workspace, and it opens immediately as a new terminal context.
from there, the workspace identity comes from its root pane:
No comments yet. Be the first to share your thoughts!
121:11:22:11-11-22-1important: 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.
see what panes exist and which one is focused:
herdr pane list
the focused pane is yours. other panes are your neighbors.
list workspaces:
herdr workspace list
list tabs in the current workspace:
herdr tab list --workspace 1
create a new tab:
herdr tab create --workspace 1
rename it:
herdr tab rename 1:2 "logs"
focus it:
herdr tab focus 1:2
close it:
herdr tab close 1:2
see what is on another pane's screen:
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 togethersplit your pane to the right and keep focus on your current pane:
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:
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:
herdr pane split 1-2 --direction down --no-focus
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.
herdr wait output 1-3 --match "ready on port 3000" --timeout 30000
with regex:
herdr wait output 1-3 --match "server.*ready" --regex --timeout 30000
if it times out, exit code is 1.
block until another agent reaches a specific state:
herdr wait agent-state 1-1 --state idle --timeout 60000
useful when you need another agent to finish before you proceed.
send text without pressing Enter:
herdr pane send-text 1-1 "hello from claude"
press Enter or other keys:
herdr pane send-keys 1-1 Enter
pane run combines both — sends text, then presses Enter:
herdr pane run 1-1 "echo hello"
create a new workspace:
herdr workspace create --cwd /path/to/project
create one without focusing it:
herdr workspace create --no-focus
focus a workspace:
herdr workspace focus 2
rename:
herdr workspace rename 1 "api server"
close:
herdr workspace close 2
herdr pane close 1-3
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
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
herdr pane list
herdr pane read 1-1 --source recent --lines 80
use this pattern when you need to coordinate with a sibling pane:
# 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
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/"
herdr wait agent-state 1-1 --state idle --timeout 120000
herdr pane read 1-1 --source recent --lines 100
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.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.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.HERDR_ENV environment variable is set to 1.this keeps workspaces lightweight. they are project contexts first, labels second.
the sidebar is split into two layers:
herdr automatically detects running agents by looking at the foreground process and reading terminal output. the top section compresses each workspace into one prioritized signal so you can scan the whole workspace list quickly; the bottom section shows which specific agent is causing it.
workspace and agent states map to:
workspace rollups prefer the most urgent thing happening in that workspace: blocked first, then unseen finished work, then working, then idle.
plain shells still contribute to workspace rollups, but the sidebar's agent section intentionally hides non-agent panes so the detail list stays focused on actual agents.
if you want more interruption than ambient sidebar awareness, herdr can also play sounds or show top-right toast notifications for background events. notification suppression is tab-aware: the active tab stays quiet, but background tabs in the same workspace can still alert.
herdr is not just a passive manager for humans watching agents. it gives agents two clean integration paths:
SKILL.md — the reusable agent skill. use this if you want an agent inside herdr to learn the workflow quickly through the existing cli surface.SOCKET_API.md — the direct integration doc. use this if you want the low-level socket protocol, event subscriptions, or the cli wrapper reference that sits on top of it.those two paths meet at the same control surface. the built-in herdr workspace ..., herdr tab ..., herdr pane ..., and herdr wait ... commands all talk to the same local socket api.
that means agents running inside herdr can do useful orchestration work themselves:
in that sense, herdr is for you and for your agents.
herdr detects agent state by identifying the foreground process and reading terminal output patterns. the following agents have been tested:
| agent | idle / done | working | blocked | |-------|-------------|---------|---------| | pi | ✓ | ✓ | partial | | claude code | ✓ | ✓ | ✓ | | codex | ✓ | ✓ | ✓ | | droid | ✓ | ✓ | ✓ | | amp | ✓ | ✓ | partial | | opencode | ✓ | ✓ | ✓ |
detection heuristics also exist for these agents but have not been fully tested yet. if you use them and run into issues, please open an issue:
for any other cli agent, herdr still works as a terminal-native multiplexer. you still get workspaces, panes, tiling, and notifications. richer direct agent-side reporting on top of the socket/event layer is still evolving.
curl -fsSL https://herdr.dev/install.sh | sh
or download the binary directly from releases.
requirements: linux or macos.
herdr checks for updates automatically in the background. when a new version is ready, you'll see a notification in the ui. just restart to apply. you can also update manually:
herdr update
launch herdr:
herdr
on first run, herdr opens a short onboarding flow so you can choose your notification style. after that, if a session is restored you'll land in terminal mode; otherwise you'll start in navigate mode.
press n to create your first workspace. it opens immediately as a new terminal context in your current project context, and herdr labels it automatically from the root pane's repo or folder.
press ctrl+b (the prefix key) to switch back to navigate mode. from there you can manage workspaces, tabs, and panes.
navigate mode is the workspace control layer. a workspace can contain multiple tabs, and each tab can contain multiple panes. movement actions stay in navigate mode; mutating actions like split, close, new workspace, new tab, and sidebar toggle return you to terminal mode.
common defaults:
n new workspaceshift+n rename workspaced close workspacec new tabv / - split panex close panef fullscreenr resize modeb toggle sidebaroptional direct bindings are available but unset by default. you can bind workspace, tab, and pane switching directly in terminal mode without going through the prefix first.
example:
[keys]
previous_workspace = "ctrl+alt+["
next_workspace = "ctrl+alt+]"
previous_tab = "alt+["
next_tab = "alt+]"
focus_pane_left = "alt+h"
focus_pane_down = "alt+j"
focus_pane_up = "alt+k"
focus_pane_right = "alt+l"
full keybinding and config reference: CONFIGURATION.md
the sidebar is your triage surface.
this is the core loop of herdr: scan the workspace list, drop into the right context, then act.
| key | action |
|-----|--------|
| h l | resize width |
| j k | resize height |
| esc | exit resize mode |
mouse support is built in. herdr is not keyboard-only.
« / » at the sidebar bottom to collapse/expandtext copy uses OSC 52, so it depends on your terminal's clipboard support.
you're in a real terminal. everything works: your shell, vim, htop, ssh, anything. press the prefix key (ctrl+b) to go back to navigate mode.
config file: ~/.config/herdr/config.toml
print the full default config with:
herdr --default-config
herdr ships with 9 built-in themes: catppuccin (default), tokyo night, dracula, nord, gruvbox, one dark, solarized, kanagawa, and rosé pine.
[theme]
name = "tokyo-night"
you can also override individual color tokens on top of any base theme. see CONFIGURATION.md for the full token reference.
for all keybindings, onboarding, notification, sound, ui options, and environment variables, see CONFIGURATION.md.
herdr saves your workspaces, tabs, pane layou