Skip to main content
For builds, training runs, servers, or anything else that takes a while, pass onStdout / on_stdout and onStderr / on_stderr callbacks. Output arrives as the command produces it, one line at a time, or in chunks when it comes fast.
const result = await sandbox.commands.run("npm run build", {
  onStdout: (data) => process.stdout.write(data),
  onStderr: (data) => process.stderr.write(data),
  timeoutMs: 300_000,
})

console.log(`Build exited ${result.exitCode}`)
Even while streaming, the returned result still holds the complete stdout and stderr.
AsyncSandbox takes the same callbacks with an awaitable run(). See the Sandbox reference.

Idle timeout

The timer resets on every chunk, so a command that keeps producing output won’t trip timeoutMs no matter how long it runs. A command that goes completely silent still has to finish before the timeout.

Network drops

If the stream ends before the finished event (a network hiccup, say), run() throws. Retry from the caller if you need the resilience. The command keeps running in the sandbox after your client disconnects, so you can reconnect with Sandbox.connect(id) if you saved the ID.

Capture and stream together

Streaming and sync return aren’t mutually exclusive - capture chunks for logs while also collecting the full buffer for analysis.
const result = await sandbox.commands.run("./long-job.sh", {
  onStdout: (data) => process.stdout.write(data), // watch it live
})

await uploadLogs(result.stdout) // full buffer, already captured for you