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 |