Skip to content

WebSocket Stream

--ws <url> (or EXPLORBOT_WS_URL) streams a run to your own UI. Explorbot dials out — your side is the server — so the same flag covers a child process you spawned and a CI bot connecting from elsewhere.

Terminal window
npx explorbot explore /dashboard --ws ws://127.0.0.1:8787

Every message is JSON with a type and a ts, plus whatever that type carries. Nothing is validated on either side: render the types you know, ignore the rest, and expect new ones.

TypeWhat it is
hellothe run itself: command, working directory, pid
statethe page under test: url, path, title, heading
testa test starting or finishing, with its status, result and plan
planthe current plan and the status of every test in it
screenshotthe screenshot file just written
researchthe researcher’s map of a page: markdown and its file
reportthe analyst’s end-of-session report: markdown and its file
docsthe doc collector’s spec index: markdown and its file
activitywhat the run is doing this second
loga log line and its level
aska question for a human, carrying an askId
resultthe run exited, with its code

Each type carries the latest truth, so keep the last frame per type — that is what the terminal itself shows.

TypeWhat it does
answeranswers an ask: same askId, plus value — or null to skip the question
interruptstops the current step; the run then asks what to do instead

A run with nobody to answer never asks in the first place, so connecting a listener that answers is what makes a headless run interactive.

Frames queue while disconnected — the last 1000 — and the connection retries on its own, so treat it as a live feed rather than a history. On exit the queue is flushed after result.

Frames are logged, not published:

tag('data').log('coverage', { visited: 12, total: 30 });

That reaches listeners as a coverage frame. A data entry never goes to the console, the log file, or the TUI.