Skip to content

Socket API

Herdr exposes a local socket API for scripts and agents that need to inspect or control a running session.

Most automation should start with the CLI wrappers. Use the raw socket API only when you need direct request/response control or long-lived event subscriptions.

LayerUse it for
Agent skillTeaching a coding agent how to use Herdr from inside a pane.
CLI wrappersShell scripts, simple orchestration, and human debugging.
Raw socket APICustom tools, protocol clients, and event subscribers.

The layers share the same control surface.

The socket API can:

  • create, list, focus, rename, and close workspaces
  • create, list, focus, rename, and close tabs
  • list, inspect, split, rename, read, close, and send input to panes
  • list, inspect, read, send to, rename, focus, start, and attach agents through CLI helpers
  • report custom agent state from hooks and plugins
  • subscribe to events and wait for output or state changes
  • install and uninstall built-in integrations
  • stop the server and reload config

Create a workspace:

Terminal window
herdr workspace create --cwd ~/project --label api

Create a tab:

Terminal window
herdr tab create --label logs

Split a pane and run a command:

Terminal window
herdr pane split 1-1 --direction right
herdr pane run 1-2 "npm test"

Wait for an agent:

Terminal window
herdr wait agent-status 1-1 --status done

Read pane output:

Terminal window
herdr pane read 1-2 --source recent --lines 50

Raw socket method names use dot notation:

AreaMethods
Serverping, server.stop, server.reload_config
Workspaceworkspace.create, workspace.list, workspace.get, workspace.focus, workspace.rename, workspace.close
Worktreeworktree.list, worktree.create, worktree.open, worktree.remove
Tabtab.create, tab.list, tab.get, tab.focus, tab.rename, tab.close
Panepane.split, pane.list, pane.get, pane.rename, pane.send_text, pane.send_keys, pane.send_input, pane.read, pane.report_agent, pane.report_agent_session, pane.report_metadata, pane.clear_agent_authority, pane.release_agent, pane.close, pane.wait_for_output
Agentagent.list, agent.get, agent.read, agent.send, agent.rename, agent.focus, agent.start
Eventsevents.subscribe, events.wait
Integrationsintegration.install, integration.uninstall

Some CLI commands are conveniences around these methods. For example, herdr agent wait resolves an agent target and then subscribes to pane agent state events.

Worktree methods manage Git checkouts as Herdr workspaces. worktree.create creates a checkout and returns the new workspace, tab, root_pane, and worktree records. worktree.open opens an existing checkout or returns the already-open workspace. worktree.remove runs git worktree remove against a linked child workspace and never deletes the branch.

Create a worktree from a source workspace:

{"id":"req_1","method":"worktree.create","params":{"workspace_id":"1","branch":"worktree/api","focus":false}}

Open an existing checkout:

{"id":"req_2","method":"worktree.open","params":{"workspace_id":"1","branch":"worktree/api","focus":true}}

Remove a linked checkout:

{"id":"req_3","method":"worktree.remove","params":{"workspace_id":"2","force":false}}

Use at most one of workspace_id or cwd for worktree.list, worktree.create, and worktree.open; omit both to use the active workspace. Use exactly one of path or branch for worktree.open. Raw socket cwd and path values must be absolute; the CLI expands relative --cwd and --path values before sending requests. Workspace responses include optional worktree provenance when a workspace belongs to a Herdr worktree group. Worktree commands can emit workspace.updated when an existing workspace gains or changes worktree provenance.

Herdr uses newline-delimited JSON over a Unix domain socket.

Send one request per line:

{"id":"req_1","method":"ping","params":{}}

A successful response includes the same id:

{"id":"req_1","result":{"type":"pong"}}

Event subscriptions keep the connection open after the initial response.

The default socket lives under your Herdr config directory.

Named sessions have separate sockets:

~/.config/herdr/herdr.sock
~/.config/herdr/sessions/<name>/herdr.sock

Resolution order:

  1. explicit CLI --session <name>
  2. HERDR_SOCKET_PATH
  3. HERDR_SESSION=<name>
  4. default session socket

Use HERDR_SOCKET_PATH only for low-level overrides.

Integrations report agent state with pane.report_agent.

{
"id": "req_1",
"method": "pane.report_agent",
"params": {
"pane_id": "1-1",
"source": "custom:docs",
"agent": "docs-bot",
"state": "working",
"message": "building docs",
"custom_status": "indexing"
}
}

state is semantic. It affects waits, notifications, and rollups.

custom_status is visual. It can show a short label like indexing without changing semantic behavior.

Session-only official integrations report native session references with pane.report_agent_session. State-reporting integrations can still include native session references in pane.report_agent. State-independent session reports do not affect waits, notifications, or rollups.

{
"id": "req_2",
"method": "pane.report_agent_session",
"params": {
"pane_id": "1-1",
"source": "herdr:codex",
"agent": "codex",
"agent_session_id": "..."
}
}

pane.get, pane.list, agent.get, and agent.list expose a read-only agent_session object when Herdr has a stored native session reference:

{
"agent_session": {
"source": "herdr:codex",
"agent": "codex",
"kind": "id",
"value": "..."
}
}

If no native session reference is stored, the field is omitted.

pane.get, pane.list, agent.get, and agent.list also expose foreground_cwd when Herdr can resolve the cwd of the process currently controlling the pane PTY. The existing cwd field remains the pane/workspace cwd used for labels, follow-cwd behavior, and restored session state.

Use pane.report_metadata when a user hook wants to customize presentation without taking over lifecycle state from a Herdr integration.

{
"id": "req_2",
"method": "pane.report_metadata",
"params": {
"pane_id": "1-1",
"source": "user:claude-title",
"agent": "claude",
"title": "Refactor auth middleware",
"display_agent": "Claude: auth",
"custom_status": "refactor auth",
"state_labels": {
"working": "refactoring auth",
"idle": "ready",
"done": "review ready"
},
"ttl_ms": 3600000
}
}

Metadata reports are display-only. Valid metadata can override the pane title, displayed agent name, compact custom status, and visible state labels. working, blocked, idle, waits, notifications, and rollups still come from semantic state. Native session restore comes from stored official session references. agent is an optional guard for the authoritative agent label; applies_to_source is an optional guard for the active lifecycle authority source. Use display_agent to change the visible name. state_labels keys must be idle, working, blocked, done, or unknown. Use clear fields such as clear_custom_status: true with the same source to remove one presentation override.

Subscribe to events when you need a long-lived stream:

{
"id": "sub_1",
"method": "events.subscribe",
"params": {
"subscriptions": [
{ "type": "pane.agent_status_changed", "pane_id": "1-1", "agent_status": "blocked" }
]
}
}

The first response acknowledges the subscription. Later lines are pushed events.

Workspace event subscriptions include workspace.created, workspace.updated, workspace.renamed, workspace.closed, and workspace.focused.

Use events.wait when you want one matching event and then a response.

Use pane.read through the CLI unless you are writing a protocol client.

Terminal window
herdr pane read 1-1 --source visible --lines 80
herdr pane read 1-1 --source recent --lines 120
herdr pane read 1-1 --source recent-unwrapped --lines 120

recent-unwrapped is useful for logs because it ignores soft wrapping.

Use waits to coordinate agents and scripts.

Terminal window
herdr wait agent-status 1-1 --status done
herdr wait agent-status 1-1 --status blocked

Agent waits observe semantic state, not arbitrary command completion.

Successful responses look like this:

{
"id": "req_1",
"result": {
"type": "pane_info",
"pane": {
"pane_id": "1-1",
"terminal_id": "term_abc123",
"workspace_id": "1",
"tab_id": "1-1",
"focused": true,
"agent_status": "working",
"revision": 42
}
}
}

Errors look like this:

{
"id": "req_1",
"error": {
"code": "not_found",
"message": "pane not found"
}
}

Herdr has a protocol version for client/server compatibility. Protocol changes are reviewed with release compatibility in mind.

Check the server protocol with ping or herdr status before depending on new behavior. Handle unknown fields gracefully.