Output Events
The soketi events emitted on a job's private channel.
All real-time output is emitted on the soketi channel private-run-<jobId>. A
client subscribes to that channel (with auth) and binds
to the events below.
soketi delivers each event's data as a JSON-encoded string. Parse it with
JSON.parse before use. The React SDK does this for you.
The event names and payloads are generated from
packages/contract/schema/wire.schema.json, so they're identical across the worker,
the API, and the SDKs.
stage
A lifecycle transition.
{ "phase": "queued" }phase ∈ queued · compiling · running. (compiling only appears for compiled
languages.)
stdout / stderr
A chunk of process output. Same shape for both streams.
{ "chunk": "name? ", "seq": 0 }| Field | Type | Notes |
|---|---|---|
chunk | string | UTF-8 output text. |
seq | number | Monotonic sequence number for ordering. A single logical output may be split across several events (each ≤ ~8 KB); reassemble by seq. |
compile_output
The live, interleaved build log — emitted during the compiling stage for
compiled languages only. Same OutputChunkEvent shape as stdout / stderr.
{ "chunk": "compiling main.go\n", "seq": 0 }It carries the compile command's stdout and stderr in emission order. It's kept on
its own event — separate from stdout / stderr — so a client can render a
dedicated real-time build panel. The seq shares the same per-job sequence space
as stdout / stderr; reassemble by seq like the other output streams.
result
The terminal event, emitted exactly once when the sandbox exits.
{
"exitCode": 0,
"signal": null,
"timedOut": false,
"idleTimedOut": false,
"truncated": false,
"durationMs": 312
}| Field | Type | Notes |
|---|---|---|
exitCode | number | null | null when killed by a signal. |
signal | string | null | The signal name, if killed by one. |
timedOut | boolean | Wall-clock or CPU-clock expiry. |
idleTimedOut | boolean | Idle-clock expiry. |
truncated | boolean | Output exceeded the outputKb budget. |
durationMs | number | Wall-clock duration of the run. |
See The Three Clocks for what each timeout means.
artifact
Emitted for files captured from /workspace when artifact storage is configured.
{ "name": "plot.png", "mimeType": "image/png", "bytes": 20481, "url": "https://.../plot.png?X-Amz-..." }url is a presigned GET URL (no bearer needed). See
Artifacts.
Binding example
With pusher-js directly (the React SDK abstracts this):
const channel = pusher.subscribe(`private-run-${jobId}`);
channel.bind('stage', (d: string) => { const { phase } = JSON.parse(d); });
channel.bind('stdout', (d: string) => { const { chunk, seq } = JSON.parse(d); });
channel.bind('stderr', (d: string) => { const { chunk, seq } = JSON.parse(d); });
channel.bind('compile_output', (d: string) => { const { chunk, seq } = JSON.parse(d); });
channel.bind('result', (d: string) => { const r = JSON.parse(d); /* terminal */ });