> ## Documentation Index
> Fetch the complete documentation index at: https://docs.superserve.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Stream command output

> Watch a command's stdout and stderr as it runs.

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.

<CodeGroup>
  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
  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}`)
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
  import sys

  result = sandbox.commands.run(
      "npm run build",
      on_stdout=lambda data: sys.stdout.write(data),
      on_stderr=lambda data: sys.stderr.write(data),
      timeout_seconds=300,
  )

  print(f"Build exited {result.exit_code}")
  ```
</CodeGroup>

<Note>
  Even while streaming, the returned `result` still holds the complete `stdout` and `stderr`.
</Note>

<Note>
  `AsyncSandbox` takes the same callbacks with an awaitable `run()`. See the [Sandbox reference](/sdk-reference/sandbox).
</Note>

## 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.

<CodeGroup>
  ```typescript TypeScript theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
  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
  ```

  ```python Python theme={"theme":{"light":"github-light","dark":"vitesse-dark"}}
  result = sandbox.commands.run(
      "./long-job.sh",
      on_stdout=lambda data: print(data, end=""),  # watch it live
  )

  upload_logs(result.stdout)  # full buffer, already captured for you
  ```
</CodeGroup>
