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

# Commands, code and files

Run commands in a sandbox buffered, streamed or in the background, run code in a Jupyter kernel, move files in and out, and open a terminal.

All of these need `sandboxes:run` and a running sandbox. Set `SBX` to your sandbox's ID in the examples.

## Run a command

`POST /v1/sandboxes/{sandbox_id}/exec` runs a command and, by default, waits for it to exit:

**curl**

```bash
    curl -s "https://beta-api.b3os.org/v1/sandboxes/$SBX/exec" \
      -H "Authorization: Bearer $B3OS_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"cmd": "python3 -c \"print(2 + 2)\""}'
    ```
  **TypeScript**

```ts
    import { B3OS } from "@b3os/sdk";

    const b3os = new B3OS();
    const sbx = process.env.SBX!; // a sandbox ID, sbx_...
    const result = await b3os.sandboxes.exec(sbx, { cmd: 'python3 -c "print(2 + 2)"' });
    console.log(result.exit_code, result.stdout);
    ```
  **Python**

```python
    import os
    from b3os import B3OS

    b3os = B3OS()
    sbx = os.environ["SBX"]  # a sandbox ID, sbx_...
    result = b3os.sandboxes.exec(sbx, {"cmd": 'python3 -c "print(2 + 2)"'})
    if result["object"] == "exec_result":  # with "background": True you get the process instead
        print(result["exit_code"], result["stdout"])
    ```
  **MCP**

```text
    In my sandbox, run the test suite with `npm test` in /workspace/app and tell me what failed.
    ```

    The agent calls `sandbox_exec` with `sandbox_id`, `cmd` and `cwd`, and reads `exit_code`, `stdout` and `stderr`.

```json
{
  "object": "exec_result",
  "exit_code": 0,
  "signal": null,
  "timed_out": false,
  "stdout": "4\n",
  "stderr": "",
  "stdout_truncated": false,
  "stderr_truncated": false,
  "duration_ms": 21.6
}
```

The values are illustrative. `cmd` as a string runs through `/bin/sh -c`; as an array (`["node", "--version"]`) it runs directly. Other fields: `cwd` (default `/workspace`), `env`, `stdin` (written to the command, then closed), `user` (`user` or `root`) and `timeout_ms`. A buffered call waits at most 60 seconds and returns up to 1 MiB of each stream; `stdout_truncated` says when output was dropped. A command killed at its timeout returns `timed_out: true` and the signal, `KILL`.

### Stream the output

Add `?stream=true` (or send `Accept: text/event-stream`) to get output while the command runs, as `exec.stdout` and `exec.stderr` events, then `exec.exit` with the exit code. A streamed command may run up to an hour.

```bash
curl -N -s "https://beta-api.b3os.org/v1/sandboxes/$SBX/exec?stream=true" \
  -H "Authorization: Bearer $B3OS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"cmd": "for i in 1 2 3; do echo $i; sleep 1; done", "timeout_ms": 60000}'
```

### Run in the background

`background: true` returns at once with the process, for servers and long jobs:

```bash
curl -s "https://beta-api.b3os.org/v1/sandboxes/$SBX/exec" \
  -H "Authorization: Bearer $B3OS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"cmd": "npm run dev", "cwd": "/workspace/app", "background": true}'
# {"object": "process", "pid": 812, "cmd": "npm run dev", "status": "running", ...}
```

- `GET /v1/sandboxes/{sandbox_id}/processes` lists background processes, running or exited.
- `GET /v1/sandboxes/{sandbox_id}/logs` streams their output as `log.stdout` and `log.stderr` events, then `process.exited`. It starts with up to 1 MiB of buffered output per process; filter with `pid`, and pass `follow=false` to stop after the buffered output.
- `POST /v1/sandboxes/{sandbox_id}/processes/{pid}/kill` sends `TERM` (or `KILL`, `INT`, `HUP`) to the process and its process group.

## Run code in a kernel

Sandboxes from the `code-interpreter` template have a Jupyter kernel. `POST /v1/sandboxes/{sandbox_id}/run_code` runs code in it and returns rich results; state persists between calls, like cells in a notebook:

```bash
curl -s "https://beta-api.b3os.org/v1/sandboxes/$SBX/run_code" \
  -H "Authorization: Bearer $B3OS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"code": "import math\nmath.sqrt(2)\n"}'
```

```json
{
  "object": "run_code_result",
  "language": "python",
  "execution_count": 3,
  "results": [{ "mime_type": "text/plain", "data": "1.4142135623730951", "is_main_result": true }],
  "stdout": "",
  "stderr": "",
  "error": null,
  "duration_ms": 4.8
}
```

`language` is `python` (the default) or `javascript`. Results carry their MIME type, so plots come back as images and data frames as HTML. A cell that raises returns the exception in `error`. Other templates answer [`kernel_unavailable`](/errors#kernel_unavailable).

## Files

| Call | Does |
|---|---|
| `GET /v1/sandboxes/{sandbox_id}/files?path=/workspace/main.py` | Returns the file's bytes |
| `GET /v1/sandboxes/{sandbox_id}/files?path=/workspace&list=1` | Lists a directory as JSON: name, path, type, size, mode, modified time |
| `PUT /v1/sandboxes/{sandbox_id}/files?path=/workspace/main.py` | Writes the request body to the path, replacing any file; `mkdir=1` creates parent directories, `mode` sets a new file's permissions |

```bash
curl -s -X PUT "https://beta-api.b3os.org/v1/sandboxes/$SBX/files?path=/workspace/data/input.csv&mkdir=1" \
  -H "Authorization: Bearer $B3OS_API_KEY" \
  -H "Content-Type: application/octet-stream" \
  --data-binary @input.csv
```

Paths are absolute. A transfer carries at most 64 MiB; for larger files, fetch them from inside the sandbox.

## Open a terminal

`GET /v1/sandboxes/{sandbox_id}/pty` upgrades to a WebSocket attached to a new pseudo-terminal running the login shell, or `cmd`. Binary frames carry terminal bytes both ways. Text frames carry JSON control messages: send `{"type": "resize", "cols": 120, "rows": 40}`; the server sends `{"type": "exit", "code": 0}` before it closes. Pass `cols`, `rows`, `cmd` and `cwd` as query parameters.

From a browser, get a [stream ticket](/concepts/auth#stream-tickets) with `POST /v1/sandboxes/{sandbox_id}/ticket` and open the socket within 30 seconds:

```js
const { ticket } = await (await fetch(`/api/my-backend/ticket?sandbox=${sandboxId}`)).json();
const socket = new WebSocket(
  `wss://beta-api.b3os.org/v1/sandboxes/${sandboxId}/pty?cols=120&rows=40`,
  ["b3os.v1", `b3os.ticket.${ticket}`],
);
socket.binaryType = "arraybuffer";
```

Mint the ticket on your server with your key, never in the browser. The CLI opens the same terminal with `b3os sandbox shell`.