CLI reference
Herdr’s CLI talks to the running server over the same local socket API used by integrations and agents.
Most commands print JSON responses for deterministic automation in scripts.
Launch and status
herdr # launch or attach to the default sessionherdr --session work # launch or attach to a named sessionherdr --remote workbox # attach through SSH, using local keybindingsherdr --remote workbox --remote-keybindings serverherdr --remote workbox --handoffherdr --no-session # single-process escape hatchherdr --default-config # print default configherdr update # download and install from the configured channelherdr update --handoff # opt into live handoff for supported running serversherdr completion zsh # generate a zsh completion scriptherdr channel show # print stable or previewherdr channel set preview # opt into preview buildsherdr channel set stable # return a direct install to stableherdr --version # print version
Terminal window
Status commands:
herdr statusherdr status serverherdr status client
Terminal window
API schema commands:
herdr api schemaherdr api schema --jsonherdr api schema --output herdr-api.schema.json
Terminal window
herdr api schema prints a short summary of the socket protocol schema
bundled with the installed binary. Use --json for the full JSON Schema
document, or --output PATH to write that document to a file.
Shell completions
herdr completion zshherdr completions zshherdr completion bashherdr completion fishherdr completion powershellherdr completion elvish
Terminal window
completion prints the script to stdout. completions is an alias. For
a temporary zsh session, load the script directly:
source <(herdr completion zsh)
Terminal window
For a persistent zsh setup, write the generated _herdr function
somewhere on your fpath before compinit runs:
mkdir -p ~/.zfuncherdr completion zsh > ~/.zfunc/_herdr
Terminal window
Then make sure your .zshrc contains:
fpath=(~/.zfunc $fpath)autoload -Uz compinitcompinit
Terminal window
Server
herdr serverherdr server stopherdr server reload-configherdr server agent-manifests [--json]herdr server update-agent-manifests [--json]herdr server reload-agent-manifests
Terminal window
herdr server runs the headless server explicitly. Use it for
supervised or service-style setups. reload-config applies reloadable
settings without restarting panes. agent-manifests shows the active
agent detection manifest sources, cached remote versions, and last
remote update results. update-agent-manifests fetches remote manifest
updates immediately, reloads them into the running server, and prints
the updated manifest status; pass --json for the raw status response.
reload-agent-manifests reloads agent detection manifests into the
running server after local override edits.
Notifications
herdr notification show <title> [--body TEXT] [--position top-left|top-right|bottom-left|bottom-right] [--sound none|done|request]
Terminal window
notification show uses the configured [ui.toast] delivery.
--position only affects in-app Herdr toasts. --sound defaults to
none; done and request play the existing finished and
needs-attention sounds only when the notification is shown.
Sessions
herdr session list [--json]herdr session attach <name>herdr session stop <name> [--json]herdr session delete <name> [--json]
Terminal window
Use default as the session name when you need to stop the default
session explicitly.
Workspaces
herdr workspace listherdr workspace create [--cwd PATH] [--label TEXT] [--env KEY=VALUE] [--focus] [--no-focus]herdr workspace get <workspace_id>herdr workspace focus <workspace_id>herdr workspace rename <workspace_id> <label>herdr workspace report-metadata <workspace_id> --source ID [--token NAME=VALUE] [--clear-token NAME] [--seq N] [--ttl-ms N]herdr workspace close <workspace_id>
Terminal window
Create a workspace without stealing focus:
herdr workspace create --cwd ~/project --label api --no-focus
Terminal window
A workspace is a top-level project or work context. Creating one also
creates its first tab and root pane. The JSON response exposes their IDs
as .result.workspace.workspace_id, .result.tab.tab_id, and
.result.root_pane.pane_id.
Worktrees
herdr worktree list [--workspace ID | --cwd PATH]herdr worktree create [--workspace ID | --cwd PATH] [--branch NAME] [--base REF] [--path PATH] [--label TEXT] [--focus] [--no-focus]herdr worktree open [--workspace ID | --cwd PATH] (--path PATH | --branch NAME) [--label TEXT] [--focus] [--no-focus]herdr worktree remove --workspace ID [--force]
Terminal window
Worktrees are normal Herdr workspaces with Git checkout provenance.
worktree create creates a Git worktree checkout, opens it as a
workspace, and groups it with the parent repo workspace. If --branch
names an existing local branch, Herdr checks it out; otherwise it
creates the branch from --base or HEAD. Without --path, Herdr
creates the checkout under <worktrees.directory>/\<repo\>/<branch-slug>.
workspace close closes only Herdr state. To delete the checkout, run
worktree remove. It runs git worktree remove, never deletes the
branch, and requires --force when Git refuses a dirty checkout.
Tabs
herdr tab list [--workspace <workspace_id>]herdr tab create [--workspace <workspace_id>] [--cwd PATH] [--label TEXT] [--env KEY=VALUE] [--focus] [--no-focus]herdr tab get <tab_id>herdr tab focus <tab_id>herdr tab rename <tab_id> <label>herdr tab close <tab_id>
Terminal window
A tab is another terminal layout inside a workspace. Without
--workspace, tab create uses the active workspace and fails if none
exists. Its JSON response exposes .result.tab.tab_id and
.result.root_pane.pane_id. Closing a workspace’s last tab also closes
the workspace, matching the TUI close-tab action. If confirm_close is
enabled and closing the tab would also close a whole worktree group,
tab close returns a confirmation_required error instead.
Workspace and tab creation, and pane splitting, leave focus unchanged by
default. --focus selects the new layout; --no-focus states the
default explicitly. Without --cwd, new terminals follow the configured
terminal.new_cwd policy, which follows the source pane or workspace by
default. Each --env KEY=VALUE adds or replaces that variable in the
new root shell.
Panes
herdr pane list [--workspace <workspace_id>]herdr pane current [--pane ID|--current]herdr pane get <pane_id>herdr pane layout [--pane ID|--current]herdr pane process-info [--pane ID|--current]herdr pane neighbor --direction left|right|up|down [--pane ID|--current]herdr pane edges [--pane ID|--current]herdr pane focus --direction left|right|up|down [--pane ID|--current]herdr pane resize --direction left|right|up|down [--amount FLOAT] [--pane ID|--current]herdr pane zoom [<pane_id>|--pane ID|--current] [--toggle|--on|--off]herdr pane rename <pane_id> <label>|--clearherdr pane input [<pane_id>|--pane ID|--current] --right-click herdr|paneherdr pane split [<pane_id>|--pane ID|--current] --direction right|down [--ratio FLOAT] [--cwd PATH] [--env KEY=VALUE] [--right-click herdr|pane] [--focus] [--no-focus]herdr pane swap --direction left|right|up|down [--pane ID|--current]herdr pane swap --source-pane ID --target-pane IDherdr pane move <pane_id> --tab <tab_id> --split right|down [--target-pane ID] [--ratio FLOAT] [--focus|--no-focus]herdr pane move <pane_id> --new-tab [--workspace ID] [--label TEXT] [--focus|--no-focus]herdr pane move <pane_id> --new-workspace [--label TEXT] [--tab-label TEXT] [--focus|--no-focus]herdr pane close <pane_id>
Terminal window
For pane commands that accept --current, Herdr uses the calling pane’s
HERDR_PANE_ID when the command runs inside a Herdr pane. For
pane split, an explicit pane id or --pane ID splits that pane,
--current splits the calling pane, and an omitted target keeps using
the UI-focused pane. The split response exposes the new pane ID as
.result.pane.pane_id.
pane input --right-click pane forwards unmodified right-click gestures
to a mouse-reporting pane application. herdr restores the default pane
menu. Right-clicking the pane frame still opens Herdr’s menu.
pane split --right-click pane applies the same policy to the new pane
at creation.
After pane move, use .result.move_result.pane.pane_id for later
commands. A cross-workspace move changes the workspace-qualified pane
ID; the prior value remains at .result.move_result.previous_pane_id.
The running process keeps its launch-time HERDR_PANE_ID,
HERDR_TAB_ID, and HERDR_WORKSPACE_ID; Herdr retains the old pane ID
as an alias for that terminal, so pane commands using --current still
resolve it. A live agent name follows the terminal and continues to
resolve after the move.
Read output:
herdr pane read <pane_id> [--source visible|recent|recent-unwrapped|detection] [--lines N] [--format text|ansi] [--ansi] [--raw]herdr pane read <pane_id> --source visible --ansiherdr pane read <pane_id> --source recent-unwrapped --lines 120
Terminal window
pane read prints UTF-8 terminal text directly. ANSI escapes are
stripped by default; use --format ansi or --ansi to preserve them
where the source exposes styling. The detection source is always plain
text. For recent sources, --lines N selects the last N rendered
terminal rows before optional unwrapping; without it, reads default to
80 rows. For visible and detection, omitting --lines returns the
full snapshot, while specifying it keeps the last N newline-delimited
lines. agent read uses the same output and line behavior.
Send input:
herdr pane send-text <pane_id> <text>herdr pane send-keys <pane_id> <key> [key ...]herdr pane run <pane_id> <command>
Terminal window
<key> uses Herdr key-combo syntax: plain printable keys such as a,
special keys such as enter, tab, esc, backspace, left,
right, up, and down, modifier chords such as ctrl+h,
control+j, alt+x, and shift+tab, function keys such as f1, and
named punctuation such as minus, plus, and backtick. Legacy C-c
and c-c are accepted as aliases for ctrl+c. esc is the canonical
spelling; escape is also accepted.
pane run honors live bracketed-paste mode and submits text plus Enter
atomically. Prefer it over send-text plus send-keys Enter for
commands; the separate send operations remain low-level and
non-submitting.
Report agent state from custom hooks:
herdr pane report-agent <pane_id> \ --source ID \ --agent LABEL \ --state idle|working|blocked|unknown \ [--message TEXT] \ [--seq N] \ [--agent-session-id ID] \ [--agent-session-path PATH]
herdr pane report-agent-session <pane_id> \ --source ID \ --agent LABEL \ [--seq N] \ [--agent-session-id ID] \ [--agent-session-path PATH] \ [--session-start-source SOURCE]
herdr pane release-agent <pane_id> \ --source ID \ --agent LABEL \ [--seq N]
Terminal window
report-agent-session updates native session identity without reporting
lifecycle state. release-agent ends that source’s lifecycle authority
when its agent process exits.
pane get, pane list, agent get, and agent list include a
read-only agent_session object when an official integration has
reported a native session reference. If no native session reference is
stored, the field is omitted.
Those commands include foreground_cwd when Herdr can resolve the cwd
of the foreground process controlling the pane. The cwd field remains
the pane/workspace cwd used for labels and follow-cwd behavior.
pane get and pane list include scroll when terminal scroll metrics
are available. scroll.offset_from_bottom == 0 means the pane is at the
bottom of its scrollback.
Report display-only pane metadata without taking over semantic state:
herdr pane report-metadata <pane_id> \ --source ID \ [--agent LABEL] \ [--applies-to-source ID] \ [--title TEXT|--clear-title] \ [--display-agent TEXT|--clear-display-agent] \ [--state-label STATUS=TEXT] \ [--clear-state-labels] \ [--token NAME=VALUE] \ [--clear-token NAME] \ [--seq N] \ [--ttl-ms N]
Terminal window
STATUS is one of idle, working, blocked, done, or unknown.
--agent and --applies-to-source guard only --title,
--display-agent, and --state-label. They do not guard token patches;
token reporters own clearing or TTL refresh. Use --display-agent to
change the visible name.
Metadata text is normalized before storage. Herdr trims surrounding
whitespace, removes control characters, and caps --title,
--display-agent, each --state-label, and token values at 80
characters. Empty normalized token values clear that key.
--token patches one named display value; --clear-token removes one.
Unmentioned tokens remain unchanged. Pane tokens are available to Agent
sidebar rows as $name; workspace tokens are available to Space rows.
TTL applies independently to the token keys updated by that call.
--source and --applies-to-source must be 80 characters or fewer and
may contain only ASCII letters, digits, colon, dot, underscore, and
hyphen. --ttl-ms makes metadata expire automatically and must be
between 1 and 86400000 milliseconds. Omit it for metadata that
should stay until replaced, cleared, or the pane closes. --seq lets
Herdr ignore stale reports from the same --source; stale reports are
accepted by the API but ignored by pane state. A pane or workspace
accepts sequenced token reports from at most 32 distinct sources during
its lifetime; clearing or expiry does not release those source slots.
Agents
For the pane-versus-agent model and complete orchestration examples, see Agent automation.
herdr agent listherdr agent get <target>herdr agent read <target> [--source visible|recent|recent-unwrapped|detection] [--lines N] [--format text|ansi] [--ansi]herdr agent send-keys <target> <key> [key ...]herdr agent prompt <target> <text> [--wait] [--until STATUS]... [--timeout MS]herdr agent rename <target> <name>|--clearherdr agent focus <target>herdr agent wait <target> [--until STATUS]... [--timeout MS]herdr agent attach <target> [--takeover]herdr agent start <name> --kind KIND --pane ID [--timeout MS] [-- <agent-args...>]herdr agent explain <target> [--json|--verbose]herdr agent explain --file PATH --agent LABEL [--json|--verbose]
Terminal window
Agent targets are either a unique live agent name or the pane ID that
currently hosts the agent. Terminal IDs and bare agent-kind labels are
not agent targets. Agents started through agent start require a name;
manually launched agents remain unnamed and use their pane ID.
agent start activates an existing available shell pane: the pane’s
interactive shell must own the foreground, with no foreground command,
editor, or agent running. Topology must be created separately. Names are
unique among live agents and must match [a-z][a-z0-9_-]{0,31}. The
kind selects Herdr’s canonical interactive executable, while arguments
after -- are passed to that executable. Supported kinds are pi,
claude, codex, gemini, cursor, devin, agy, cline, omp,
mastracode, opencode, copilot, kimi, kiro, droid, amp,
grok, hermes, kilo, qodercli, qwen, and maki. A name follows
the current pane occupant and is cleared when that agent exits, is
released, or is replaced. Temporary detection uncertainty does not clear
it.
A successful start returns only after the expected agent owns the same
terminal and is ready for interactive input. If detection reports
blocked during startup, the command returns agent_not_ready
immediately. The name remains available for agent read and
agent send-keys, and becomes ready for prompts after detection reports
idle. The default startup timeout is 30000 milliseconds; explicit
values must be greater than 3000 and no more than 300000.
agent prompt honors live bracketed-paste mode and sends text followed
by encoded Enter after a short delay, including while the agent is
working. If the agent is already blocked, it returns agent_blocked
without sending input. With --wait, an accepted prompt sent from
another non-working state must produce an observed lifecycle change
within five seconds or Herdr returns agent_prompt_stalled; a caller
timeout of five seconds or less keeps the normal timeout error. After
activity is observed, it waits for the first requested settled status.
It does not track individual turns. If the agent is already working,
completion of that active turn may satisfy the wait. --until narrows
the matching states and is rejected unless --wait is also present.
Standalone agent wait returns immediately when the current status
matches. Both default to idle, done, or blocked; use
--until unknown explicitly when needed.
idle means ready for input after its tab has been seen in the focused
Herdr UI; done is the same underlying idle state after unseen
background work completes. Focusing that tab or targeting it with
pane focus / agent focus marks it seen; reading it through the CLI
does not. blocked means Herdr recognized an approval or question UI.
unknown means an agent is present but Herdr cannot classify it
confidently, not that its work succeeded.
agent send-keys sends logical terminal keys such as enter, up,
esc, or ctrl+c. Herdr validates every key before writing any bytes.
agent read reads the resolved terminal stream, and agent rename
names an already detected agent.
agent explain asks the running server to classify the same
bottom-buffer detection snapshot used by screen detection, so live
output reflects the server’s active manifest cache. Because this uses
the agent.explain socket method, restart or hand off to an updated
server after upgrading Herdr before using live explain. Use
--file PATH --agent LABEL to explain a saved fixture locally instead.
The default output shows the agent, final state, manifest source and
version, matched rule with its region evidence, and any fallback, skip,
or warning reasons. Add --verbose for visible evidence flags, cached
remote version, local override shadowing, remote update status, and the
full evaluated-rules list with matcher and region evidence. Add --json
for issue reports or tests.
Use pane send-text, pane send-keys, pane run, and
terminal attach for ordinary terminals, servers, tests, shells, or
low-level terminal control. Use pane run when you want to submit a
command with Enter.
Direct terminal attach
herdr terminal attach <terminal_id> [--takeover]herdr terminal session control <target> [--takeover] [--cols N] [--rows N]herdr terminal session observe <target> [--cols N] [--rows N]herdr terminal title set <title>herdr terminal title clear
Terminal window
Detach from direct attach with ctrl+b q. Send literal ctrl+b with
ctrl+b ctrl+b. terminal session control opens a writable live
terminal stream for a pane, terminal, or agent target. It prints the
same newline-delimited terminal.frame and terminal.closed records as
observe mode. It reads newline-delimited JSON commands on stdin:
terminal.input, terminal.resize, terminal.scroll, and
terminal.release. One controller can own a terminal at a time; use
--takeover to replace it. terminal session observe opens a read-only
live terminal stream for a pane, terminal, or agent target. It prints
newline-delimited JSON terminal.frame records with base64-encoded ANSI
bytes, then a terminal.closed record when the server closes the
stream. Multiple observers can watch the same terminal without taking
input, resize, scroll, or takeover authority. terminal title clear
hands the outer terminal window title back to ui.window_title.
Output waits
Wait for output in a pane:
herdr pane wait-output <pane_id> (--match <text> | --regex <pattern>) [--source visible|recent|recent-unwrapped] [--lines N] [--timeout MS] [--raw]
Terminal window
Use pane wait-output for normal commands and servers. Use agent wait
for coding agents.
pane wait-output checks the selected snapshot immediately, including
output that already exists, then polls until it matches. The default
source name is recent; matching treats it as unwrapped recent output
from the latest 80 rendered terminal rows. --lines changes that row
limit. --match finds a literal substring on one line, and --regex
uses Rust regular-expression syntax and also matches one line at a time.
pane wait-output, agent wait, and agent prompt --wait wait
indefinitely when --timeout is omitted. A timeout or server error is
emitted as JSON on stderr with exit status 1. CLI usage errors exit with
status 2.
Integrations
herdr integration install piherdr integration install ompherdr integration install claudeherdr integration install codexherdr integration install copilotherdr integration install devinherdr integration install droidherdr integration install kimiherdr integration install opencodeherdr integration install kiloherdr integration install hermesherdr integration install qodercliherdr integration install qwenherdr integration install cursorherdr integration install mastracodeherdr integration install grokherdr integration uninstall piherdr integration uninstall ompherdr integration uninstall claudeherdr integration uninstall codexherdr integration uninstall copilotherdr integration uninstall devinherdr integration uninstall droidherdr integration uninstall kimiherdr integration uninstall opencodeherdr integration uninstall kiloherdr integration uninstall hermesherdr integration uninstall qodercliherdr integration uninstall qwenherdr integration uninstall cursorherdr integration uninstall mastracodeherdr integration uninstall grokherdr integration status [--outdated-only]
Terminal window
Plugins
Plugin commands install and run local executable workflow plugins. A plugin is a manifest plus out-of-process commands; Herdr owns the host surface and plugins own their implementation language.
Install, list, and remove plugins:
herdr plugin install <owner>/<repo>[/subdir...] [--ref REF] [--yes]herdr plugin list [--plugin ID] [--json]herdr plugin uninstall <plugin_id|owner/repo[/subdir...]>herdr plugin enable <plugin_id>herdr plugin disable <plugin_id>
Terminal window
plugin install accepts GitHub shorthand only, such as
ogulcancelik/herdr-plugin-examples/worktree-bootstrap. It uses git,
shows a trust preview in interactive terminals, runs supported manifest
build commands, and stores GitHub installs in a Herdr-managed directory.
Use --yes for noninteractive installs. Reinstalling a GitHub-managed
plugin replaces that managed checkout. Installing over a locally linked
plugin is refused. Plugin manifests must declare min_herdr_version;
install and link fail when the plugin requires a newer Herdr binary.
plugin list is human-readable by default; pass --json for the raw
API response.
Plugin installation and enabled state are global to the current user. A plugin installed, linked, enabled, or disabled through one Herdr session is immediately available with the same state in every session.
Local development:
herdr plugin link <path> [--disabled]herdr plugin unlink <plugin_id>
Terminal window
plugin link accepts a plugin directory containing herdr-plugin.toml
or a direct manifest path. Use it while authoring or testing a plugin
from a local checkout. plugin unlink unregisters the plugin and leaves
files alone. plugin uninstall unregisters a plugin and also removes
Herdr-managed GitHub checkout files. For GitHub installs, uninstall
accepts either the plugin id or the same owner/repo[/subdir...]
shorthand used by install. Actions, event hooks, panes, and link
handlers are declared in the manifest; runtime action registration is
not part of v1.
Config directory:
herdr plugin config-dir <plugin_id>
Terminal window
plugin config-dir prints the plugin’s config directory. It creates the
directory if needed and seeds it from legacy plugin config locations
when present. Use it in setup docs and shell scripts to point users at a
stable path for .env files and other user-editable config, separate
from the managed plugin checkout.
Actions:
herdr plugin action list [--plugin ID]herdr plugin action invoke <action_id> [--plugin ID]
Terminal window
plugin action invoke starts the manifest command for an installed,
enabled, platform-compatible plugin action and prints the started
command log record in the JSON response. Use the qualified action id
(plugin.id.action) when more than one plugin uses the same action id.
Local action ids cannot contain dots, so qualified ids remain
unambiguous even when plugin ids contain dots.
Logs:
herdr plugin log list [--plugin ID] [--limit N]
Terminal window
Managed terminal panes:
herdr plugin pane open --plugin ID --entrypoint ID [--placement overlay|popup|split|tab|zoomed] [--width SIZE] [--height SIZE] [--workspace ID] [--target-pane PANE] [--direction right|down] [--cwd PATH] [--env KEY=VALUE] [--focus|--no-focus]herdr plugin pane focus <pane_id>herdr plugin pane close <pane_id>
Terminal window
plugin pane open requires the plugin to be linked, enabled, and
compatible with the current platform. It starts a manifest-declared
[[panes]] command as a Herdr-managed terminal pane. The manifest
default is overlay, which opens a temporary zoomed overlay over the
active pane. It can also open as a split, a new tab, a zoomed pane, or a
session-modal popup that does not change the tab layout. --width and
--height set the outer popup dimensions in terminal cells or
percentages such as 80%; omitted dimensions default to half the
terminal size, and values smaller than the popup minimum are clamped. A
popup is not a Herdr pane, does not export HERDR_PANE_ID, and does not
participate in pane or agent APIs. Native non-terminal plugin panes are
outside plugin v1.
--env KEY=VALUE can be repeated on process-launching commands. It
applies to the newly launched process only. Herdr-managed variables such
as HERDR_SOCKET_PATH, HERDR_BIN_PATH, HERDR_ENV,
HERDR_WORKSPACE_ID, HERDR_TAB_ID, HERDR_PANE_ID,
HERDR_PLUGIN_ID, HERDR_PLUGIN_ROOT, HERDR_PLUGIN_CONFIG_DIR,
HERDR_PLUGIN_STATE_DIR, HERDR_PLUGIN_ENTRYPOINT_ID, and
HERDR_PLUGIN_CONTEXT_JSON stay authoritative when they conflict with
caller-provided env.
Read sources
| Source | Meaning |
|---|---|
visible | Current rendered screen. Best for UI feedback loops. |
recent | Recent scrollback with terminal wrapping. |
recent-unwrapped | Recent scrollback without soft wrapping. Best for logs. |
detection | Bottom-buffer snapshot used by agent screen detection. |
These meanings apply to reads. For pane wait-output only, both
recent and recent-unwrapped search the unwrapped recent snapshot;
recent remains the default spelling.
Environment variables
| Variable | Purpose |
|---|---|
HERDR_CONFIG_PATH | Override the config file path. |
HERDR_SESSION | Select a named session for CLI commands. |
HERDR_SOCKET_PATH | Low-level socket path override. |
HERDR_PROCESS_DETECTION | Linux process detection strategy: native (default) or opt-in child-groups. |
HERDR_ENV | Set to 1 inside Herdr-managed pane processes. |
HERDR_PANE_ID | Public pane id for the running pane process. |
HERDR_TAB_ID | Public tab id for the running pane process. |
HERDR_WORKSPACE_ID | Public workspace id for the running pane process. |
HERDR_LOG | Set log filter, for example HERDR_LOG=herdr=debug. |
HERDR_DISABLE_SOUND | Disable sound playback even when sound notifications are enabled. |
Last updated Oct 08, 2026