How to Configure the Exec Runtime for Streaming Output as Server-Sent Events
Set sse: true in the ExecOptions when calling workspace.runtime.exec() to stream command output as Server-Sent Events, returning an async iterator that yields real-time stdout and stderr chunks instead of buffering the complete result.
The cloudflare/computer repository provides a Durable Object-based compute platform for executing arbitrary commands in the cloud. When you need real-time visibility into long-running processes, you can configure the exec runtime to stream output as Server-Sent Events (SSE) rather than waiting for process completion.
Understanding the SSE Configuration Options
The streaming behavior is controlled through the ExecOptions interface defined in packages/computerd/src/exec/types.ts. This configuration object accepts an sse boolean flag that, when set to true, instructs the runtime to establish an SSE-compatible connection.
According to the source code, the sse option (referred to as stream: true in earlier versions of the codebase) modifies how the exec runner handles the command's output buffers. Instead of aggregating stdout and stderr into a single response object, the runtime immediately flushes each line of output as an individual SSE message.
Enabling SSE Streaming in Your Exec Call
To configure streaming, pass the sse flag alongside your command and any other runtime options such as backend, cwd, or timeoutMs.
In packages/computer/src/runtime.ts, the high-level façade exposes workspace.runtime.exec(), which forwards these options to the underlying runner in packages/computerd/src/exec/runner.ts.
// Server-side example (Durable Object)
const handle = await workspace.runtime.exec('tail -f /var/log/app.log', {
backend: 'container', // Specify your compute backend
sse: true, // Enable Server-Sent Events streaming
timeoutMs: 60_000, // Optional: timeout in milliseconds
});
When sse: true is specified, the returned handle implements an async iterator that yields objects conforming to the streaming protocol.
Consuming the SSE Stream
The exec runtime provides two primary patterns for consuming streamed output: server-side iteration via the async iterator protocol, or client-side consumption using the browser's native EventSource API.
Server-Side Async Iterator
As implemented in the runtime façade, the returned handle yields chunks with a specific structure containing the stream type and data payload.
for await (const chunk of handle) {
if (chunk.type === 'stdout') {
console.log('STDOUT:', chunk.data);
} else if (chunk.type === 'stderr') {
console.error('STDERR:', chunk.data);
}
}
Each chunk is an object with:
type: Either'stdout'or'stderr'data: A string containing the line or chunk of output
Client-Side EventSource
Browser clients can connect to an endpoint that proxies the exec call. The runtime generates an SSE-compatible response that can be consumed via EventSource.
// Client-side example
const url = 'https://your-worker.dev/exec?command=tail+-f+log.txt&sse=1';
const evtSource = new EventSource(url);
evtSource.addEventListener('stdout', (e) => {
console.log('Output:', e.data);
});
evtSource.addEventListener('stderr', (e) => {
console.error('Error:', e.data);
});
evtSource.onerror = (err) => {
console.error('SSE Connection Error:', err);
};
The runner.ts implementation ensures that each line of output is properly formatted as an SSE message with appropriate event types and data fields.
Implementation Details in the Source Code
The streaming functionality is distributed across three key modules in the cloudflare/computer repository:
| File | Purpose |
|---|---|
packages/computerd/src/exec/types.ts |
Defines the ExecOptions interface including the sse: boolean flag |
packages/computerd/src/exec/runner.ts |
Implements the runtime logic that checks options.sse and constructs the SSE-compatible response stream |
packages/computer/src/runtime.ts |
Provides the high-level workspace.runtime.exec() façade that returns the async iterator when SSE is enabled |
examples/tutorial/worker-configuration.d.ts |
Contains documentation comments referencing SSE streaming capabilities |
The runner.ts module specifically handles the branch between buffered execution and streaming execution. When options.sse is truthy, it bypasses the standard buffer collection and instead pipes the process streams through an SSE encoder.
Summary
- Enable streaming by setting
sse: truein theExecOptionsobject passed toworkspace.runtime.exec() - Server-side consumption uses the async iterator pattern that yields
{ type, data }objects for each stdout and stderr chunk - Client-side consumption works with the native
EventSourceAPI for browser-based real-time log viewing - Compatibility exists with other exec options including
backend,cwd, andtimeoutMs - Source implementation resides in
packages/computerd/src/exec/runner.tswith type definitions inpackages/computerd/src/exec/types.ts
Frequently Asked Questions
What is the difference between sse: true and stream: true?
According to the source analysis, sse: true is the current configuration flag for enabling Server-Sent Events streaming. The stream: true option was used in earlier versions of the codebase but has been superseded by the explicit sse boolean flag in the ExecOptions interface.
Can I combine SSE streaming with other exec options?
Yes. The sse flag operates independently of other configuration parameters. You can combine sse: true with backend: 'container', custom cwd paths, and timeoutMs limits without affecting the streaming behavior, as validated in packages/computerd/src/exec/runner.ts.
What data format does the async iterator yield?
Each iteration yields a JavaScript object with two properties: type (a string equal to either 'stdout' or 'stderr') and data (a string containing the output line or chunk). This structure is consistent across both the server-side iterator and the SSE event data payload.
How do I handle reconnection for long-running SSE streams?
The EventSource API automatically handles HTTP connection reconnections with exponential backoff. For process-level timeouts, configure the timeoutMs option in ExecOptions to prevent indefinite execution. The runtime will close the SSE connection gracefully when the process exits or times out.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →