# socket api
While hrdx runs it serves a control API on a unix socket next to the state file (hrdx.sock), so scripts, editors, and coding agents can inspect and drive a running session. Disable with --api=false. The protocol is newline-delimited JSON: one request per line, one response line with the same id.
# macOS$ SOCK="$HOME/Library/Application Support/hrdx/hrdx.sock"# Linux$ SOCK="$XDG_CONFIG_HOME/hrdx/hrdx.sock"# inspect and drive the running session$ echo '{"id": "1", "method": "status"}' | nc -U "$SOCK"$ echo '{"id": "2", "method": "workspace.create", "params": {"path": "~/Developer/api", "agent": "claude"}}' | nc -U "$SOCK"$ echo '{"id": "3", "method": "pane.create", "params": {"workspace": "api", "kind": "shell", "split": "down"}}' | nc -U "$SOCK"$ echo '{"id": "3b", "method": "pane.create", "params": {"workspace": "api", "kind": "shell", "split": "float", "anchor": "center", "width_pct": 40, "height_pct": 30}}' | nc -U "$SOCK"$ echo '{"id": "4", "method": "pane.send_text", "params": {"pane_id": 3, "text": "run the tests", "enter": true}}' | nc -U "$SOCK"$ echo '{"id": "5", "method": "pane.wait", "params": {"pane_id": 3, "until": "idle"}}' | nc -U "$SOCK"$ echo '{"id": "6", "method": "pane.read", "params": {"pane_id": 3}}' | nc -U "$SOCK"$ echo '{"id": "7", "method": "menu.register", "params": {"target": "pane", "label": "Run linter", "action_id": "custom.run_linter"}}' | nc -U "$SOCK"
| method | effect |
|---|---|
| ping | liveness check, returns pong |
| status | workspaces, tabs, and panes with id, kind, and state |
| workspace.create | open a directory as a workspace |
| workspace.close | close a workspace by name or path |
| pane.create | add a pane (split: right, down, tab, float) |
| pane.send_text | type into a pane, optionally press enter |
| pane.read | the pane's visible screen as plain text |
| pane.wait | block until a pane's agent is idle or busy |
| pane.close | close a pane by id |
| menu.register | add a process-local pane, tab, or sidebar context-menu entry |
| events.subscribe | keep the connection open and push events |
## events
After events.subscribe the connection stays open and hrdx pushes lines like:
{"event": "pane.busy_changed", "data": {"pane_id": 3, "busy": false}}Events: workspace.created, workspace.closed, pane.created, pane.closed, pane.busy_changed, and menu.action, so a script can react the moment an agent finishes or a custom menu action is selected instead of polling. pane.wait plus pane.send_text is enough to build simple agent pipelines: prompt an agent, wait until it is idle, read the screen, move on.
## floating panes
Create a tab-scoped pane above the split layout with split set to float. width_pct and height_pct are required integers from 1 through 100. anchor defaults to center and also accepts top, bottom, left, or right.
{"id":"3b","method":"pane.create","params":{"workspace":"api","kind":"shell","split":"float","anchor":"center","width_pct":40,"height_pct":30}}Floating panes do not change split ratios and are not shown in the sidebar or restored after hrdx restarts. Multiple panes stack in creation or focus order. Close one through its title-bar x or with pane.close. The status response marks them with floating, anchor, width_pct, and height_pct fields.
## custom menu actions
Register an ephemeral item in the pane, tab, or sidebar context menu. The item appears after the built-in actions. Re-registering the same action_id replaces it; registrations last until hrdx exits.
{"id":"7","method":"menu.register","params":{"target":"pane","label":"Run linter","action_id":"custom.run_linter"}}Selecting the item publishes a best-effort menu.action event to event subscribers. It includes the selected target's pane, tab, and workspace context when applicable.
{"event":"menu.action","data":{"action_id":"custom.run_linter","target":"pane","pane_id":3,"workspace":"api","path":"/path/to/api","tab_index":0}}