Conductor reference
CLI verbs, JSON-RPC methods, fields, events, config keys, and exit codes for the Paneflow Conductor control plane.
This page is the compact reference for Conductor. It names the public surface and the fields a script or LLM can rely on.
CLI verbs
| Verb | Primary method | Use |
|---|---|---|
ps [--json] | fleet.list | List detected agents across workspaces |
status <target> [--json] | surface.status | Read one pane's agent state |
watch [--surface <sel>] [--type <event>] | events.subscribe | Stream lifecycle events and surface changes |
read <target> | surface.read | Read pane scrollback |
send <target> <text> | surface.send_text | Stage or submit text to a pane |
wait --match <sel> | surface.read, event stream when idle mode is used | Block until idle state, a regex, or both |
up <file> | workspace orchestration | Create a declarative agent workspace |
flow run <file> | flow orchestration | Run a multi-agent pipeline |
ls, search, focus, key | scripting methods | Use lower-level pane automation when conductor state is not enough |
Read operations are allowed by default. Writes such as send --submit, key, and flow steps that submit text require the scripting gate or AI free access mode.
Selectors
| Selector | Example | Notes |
|---|---|---|
| Numeric id | paneflow status 42 | Exact pane id |
| Name | paneflow status backend | Best selector for conductor workflows |
cmdline:<substr> | paneflow read cmdline:claude | Useful but less portable than a pane name |
cwd:<path> | paneflow read cwd:/home/me/app | Good for repo-scoped scripts |
A selector that matches nothing or several panes exits with code 3, except commands that explicitly accept multiple matches such as broadcast sends or wait --any and wait --all.
fleet.list
paneflow ps --json returns an agents array.
| Field | Meaning |
|---|---|
pid | Agent process id, or null for scan-only detection |
tool | Agent family such as claude, codex, opencode, or gemini |
state | thinking, waiting_for_input, finished, errored, stalled, idle, or unknown_running |
hooked | true when Paneflow receives lifecycle hook events |
reason | Detection reason, including no_hook for unhooked processes |
surface_id | Pane id when resolved |
surface_name | Pane name when present |
workspace | Workspace index |
active_tool_name | Tool currently running inside the agent, when reported |
message | Waiting question or permission text, when reported |
last_result | Last turn summary, when the hook provides one |
waiting_ms | Milliseconds spent waiting for input |
idle_ms | Milliseconds since the last observed activity |
An empty fleet is {"agents":[]} with exit code 0.
surface.status
paneflow status <target> --json returns one pane status.
| Field | Meaning |
|---|---|
surface_id | Pane id |
state | Same state vocabulary as fleet.list |
hooked | Whether lifecycle tracking is active |
tool | Agent family, when detected |
active_tool_name | Tool currently running, when reported |
message | Waiting question or permission text, when reported |
last_result | Last turn summary, when available |
waiting_ms | Milliseconds spent waiting for input |
idle_ms | Milliseconds since the last observed activity |
output_generation | Monotonic counter that advances when pane output changes |
A pane with no active agent returns an idle state instead of an error.
surface.read
paneflow read <target> returns terminal text. By default, output is wrapped in <untrusted_terminal_output> so an LLM can inspect it without treating it as instructions. Use --raw only for trusted human scripts.
Useful fields in JSON mode include text, lines, total_lines, eof, and output_generation.
events.subscribe and watch
paneflow watch is newline-delimited JSON. It may emit:
| Event type | Meaning |
|---|---|
ai.session_start | An agent session begins |
ai.prompt_submit | A prompt is submitted |
ai.tool_use | The agent invokes a tool |
ai.notification | The agent asks a question or requests permission |
ai.stop | A turn ends |
ai.exit | The agent process exits |
ai.session_end | The session closes |
surface_changed | The pane's output_generation advanced |
Control frames are also valid:
| Frame | Meaning |
|---|---|
subscribed | Subscription acknowledged |
heartbeat | Keepalive frame |
dropped | The subscriber lagged and events were shed |
When a client receives dropped, it should resync with paneflow ps --json or paneflow status <target> --json.
wait
wait --idle uses the event stream when available and falls back safely when needed. wait --pattern polls recent scrollback every 500 ms and scans the latest 500 lines.
| Mode | Example | Use |
|---|---|---|
| Idle | paneflow wait --match reviewer --idle --timeout 600 | Continue after the agent stops producing work |
| Pattern | paneflow wait --match backend --pattern '^DONE:' --timeout 300 | Continue after a sentinel line |
| Idle plus pattern | paneflow wait --match reviewer --idle --pattern '^REPORT_DONE' --timeout 600 | Require both a stable pane and a marker |
| Any or all | paneflow wait --match 'cmdline:claude' --pattern 'tests passed' --all | Coordinate multiple panes in pattern mode |
Timeouts exit with code 4.
Config keys
| Key | Default | Meaning |
|---|---|---|
ai_unrestricted | false | Allows trusted AI automation to submit when enabled |
ai_injection_fence | true | Wraps peer terminal output as untrusted text |
agent_stall_threshold_secs | app default | Marks silent in-progress turns as stalled |
Exit codes
| Code | Meaning |
|---|---|
0 | Success |
1 | Runtime failure |
2 | CLI usage error |
3 | Target not found or ambiguous |
4 | wait timeout |