Serve mode
botctl serve is the current runtime-backed observation and HTTP facade.
It is one of the main user-facing commands, alongside runtime, dashboard, and yolo.
The central runtime process holds the tmux control-mode connection open and rebases that stream with periodic capture-pane snapshots. serve connects to that runtime and exposes a session-scoped foreground stream plus optional HTTP API.
In managed mode, serve auto-starts the runtime in a hidden tmux session when needed. Use --unmanaged if you want it to require an already-running runtime instead.
What it does today
serve runs in the foreground and emits structured events to stdout from the runtime's shared event stream.
Current behavior:
- requires an existing local
runtime - narrows the shared runtime stream to one tmux session or one explicit pane
- emits human-readable or JSONL events
- can also expose a localhost HTTP API for polling clients and web UIs
- uses the same runtime-owned pane snapshots and guarded action scheduler seen by
dashboardandyolo
Basic usage
Observe one session:
botctl serve --session demo
This is the main session-scoped live observation facade. Use it when you want a foreground stream; use observe only when you specifically want a bounded diagnostic sample.
Observe one specific pane inside that session:
botctl serve --session demo --pane %19
Use JSONL output for tooling:
botctl serve --session demo --format jsonl
Expose the local HTTP API for a browser-based control surface:
botctl serve --session demo --http 127.0.0.1:8787 --allowed-origin http://localhost:3000
Repeat --allowed-origin URL for each browser origin that should be able to call the API.
Current HTTP endpoints include:
GET /instancesGET /instances/:idPOST /instances/:id/promptPOST /instances/:id/actions/:actionPOST /instances/:id/interactions/:optionId
For the full route, payload, and response reference, see HTTP API reference.
The prompt endpoint accepts JSON like:
{
"text": "Summarize the current repo",
"submit_delay_ms": 100
}
You can also point serve at an explicit state root so it reaches the right runtime socket:
botctl serve --session demo --state-dir /tmp/botctl-state
Slow down periodic reconciliation:
botctl serve --session demo --reconcile-ms 5000
Event kinds
The current stream includes:
runtime-startedpane-discoveredpane-snapshot-updatedpane-state-changedyolo-enabledyolo-disabledyolo-monitoring-stoppedaction-requestedaction-executedaction-failedpane-removed
Snapshot-bearing events include:
- pane metadata
- current classified state
- classifier signals
- whether the state changed
- desired and effective yolo state
- wait duration and last stop reason when available
Current scope
This is the current implementation, not the final remote/API product yet.
Implemented now:
- explicit
runtimecommand - runtime-owned tmux observation and periodic reconciliation
- runtime-owned guarded action execution
- runtime-owned yolo supervision
- foreground session-scoped
servestream and polling HTTP API
Not implemented yet:
- SSE endpoints
- full reconstructed terminal screen model
- remote/distributed runtimes
Safety rules
Serve mode keeps the same safety rules as the rest of botctl:
- targeting stays explicit
- observation stays scoped to the requested tmux session or explicit pane
Unknownremains a refusal state- serve mode does not bypass guarded workflow checks
- the HTTP API only exposes panes inside the served tmux session
- the HTTP API exposes visible prompt options conservatively; when a dialog cannot be selected safely yet, it falls back to low-level confirmation controls
Current limits:
- it still depends on a local runtime you start explicitly
- it does not expose SSE yet
- classification still depends on capture-plus-merge heuristics, not a full terminal model
Relationship to the larger plan
The current shipped shape is already the central-runtime design: one local runtime owns observation and actions, and serve is the session-scoped facade over that owner.