# How to Configure the Exec Runtime for Streaming Output as Server-Sent Events

> Configure the exec runtime for streaming output as Server-Sent Events by setting sse: true in ExecOptions. Get real-time stdout and stderr chunks instantly.

- Repository: [Cloudflare/computer](https://github.com/cloudflare/computer)
- Tags: how-to-guide
- Published: 2026-08-08

---

**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`](https://github.com/cloudflare/computer/blob/main/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`](https://github.com/cloudflare/computer/blob/main/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`](https://github.com/cloudflare/computer/blob/main/packages/computerd/src/exec/runner.ts).

```typescript
// 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.

```typescript
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`.

```javascript
// 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`](https://github.com/cloudflare/computer/blob/main/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`](https://github.com/cloudflare/computer/blob/main/packages/computerd/src/exec/types.ts) | Defines the **`ExecOptions`** interface including the `sse: boolean` flag |
| [`packages/computerd/src/exec/runner.ts`](https://github.com/cloudflare/computer/blob/main/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`](https://github.com/cloudflare/computer/blob/main/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`](https://github.com/cloudflare/computer/blob/main/examples/tutorial/worker-configuration.d.ts) | Contains documentation comments referencing SSE streaming capabilities |

The [`runner.ts`](https://github.com/cloudflare/computer/blob/main/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: true` in the `ExecOptions` object passed to `workspace.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 `EventSource` API for browser-based real-time log viewing
- **Compatibility** exists with other exec options including `backend`, `cwd`, and `timeoutMs`
- **Source implementation** resides in [`packages/computerd/src/exec/runner.ts`](https://github.com/cloudflare/computer/blob/main/packages/computerd/src/exec/runner.ts) with type definitions in [`packages/computerd/src/exec/types.ts`](https://github.com/cloudflare/computer/blob/main/packages/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`](https://github.com/cloudflare/computer/blob/main/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.