Concepts

Event stream

How ExecHandle streams stdout from the sandbox in real time — pipe, async generator, and await.

sb.exec() and sb.execCode() both return an ExecHandle. Under the hood, execd sends execution output as an SSE stream. ExecHandle wraps that stream and exposes three consumption modes.

Modes

Pipe

Send stdout directly to any writable with a write(chunk: string) method:

await sb.exec("npm run build").pipe(process.stdout);
await sb.exec("npm test").pipe(process.stderr);

This is the most common mode. Output flows in real time as the command runs.

Async generator

Iterate stdout chunks one at a time:

for await (const chunk of sb.exec("npm run build").stdout()) {
  process.stdout.write(chunk);
  // or process each chunk (e.g. parse log lines)
}

Use this when you want to inspect or transform output as it arrives.

Await

Await the handle directly to get the full result after the command completes:

const { stdout, stderr, exitCode } = await sb.exec("node --version");

This buffers all stdout in memory and resolves once the command exits. Use when you need the full output as a string.

result()

.result() is an explicit promise form that resolves to { stdout, stderr, exitCode }:

const handle = sb.exec("npm test");
// ... do something else ...
const { exitCode } = await handle.result();

ExecResult type

interface ExecResult {
  stdout: string; // full stdout as a string
  stderr: string; // full stderr as a string
  exitCode: number; // process exit code
}

Strict mode

By default, exec() throws CommandError if the exit code is non-zero (strict mode). Pass { strict: false } to get the ExecResult instead:

const { exitCode } = await sb.exec("test -f package.json", { strict: false });
if (exitCode !== 0) {
  console.log("no package.json");
}

What gets streamed

Only stdout is streamed via pipe() and the stdout() generator. Stderr is buffered separately and available via (await handle).stderr or .result().

The underlying SSE stream from execd also carries exit code information, which ExecHandle uses to populate exitCode in the result.