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

# SDK Reference

> Sandbox, commands, processes, PTYs, files, snapshots, desktop control, and networking reference

This page is the runtime API surface of the Sandbox SDK in one place. It maps the Python and TypeScript sandbox-management APIs you'll use to create sandboxes, execute work inside them, manage files and processes, and interact with desktop sandboxes. Each detail page linked below expands on the same APIs with longer examples and edge cases.

<Note>
  All method names below use the Python form. The TypeScript SDK mirrors them in camelCase (`start_process` → `startProcess`, `read_file` → `readFile`, `memory_mb` → `memoryMb`, etc.). The same JavaScript runtime API is used from Node.js.
</Note>

<Note>
  This page focuses on the sandbox runtime SDK surface. Related interfaces documented elsewhere include the CLI and HTTP API, the image-building DSLs in [Sandbox Images](/sandboxes/images), and the browser/VNC integration details in [Computer Use](/sandboxes/computer-use).
</Note>

<Note>
  Every method below is also available as an async-native variant on `AsyncSandbox` in Python — same names and parameters, just `await`ed. See the [Async SDK](/sandboxes/async) page for usage. The TypeScript SDK is already Promise-based, so the methods shown in the TypeScript tabs *are* the async API.
</Note>

## Sandbox

`Sandbox` is the top-level entry point for managing sandboxes in your namespace. Use `Sandbox.create()` to start a sandbox and get a handle. Use `Sandbox.connect()` to reconnect to an existing sandbox by ID or name.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from tensorlake.sandbox import Sandbox

    # Authentication comes from `tl login` or TENSORLAKE_API_KEY env var
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    import { Sandbox } from "tensorlake";

    ```
  </Tab>
</Tabs>

See [Authentication](/platform/authentication) for the full auth flow.

### Create

Create a sandbox. Omit `name` for an ephemeral sandbox (cannot be suspended); pass `name` to create a named sandbox that supports suspend/resume. Returns a connected `Sandbox` handle (blocks until the sandbox is `running`).

| Parameter                | Type                | Default          | Description                                                                               |
| ------------------------ | ------------------- | ---------------- | ----------------------------------------------------------------------------------------- |
| `name`                   | `str \| None`       | `None`           | Human-readable name. Required for suspend/resume.                                         |
| `cpus`                   | `float`             | `1.0`            | Number of CPUs to allocate.                                                               |
| `memory_mb`              | `int`               | `1024`           | Memory in megabytes. 1024–8192 MB per CPU core.                                           |
| `timeout_secs`           | `int`               | `600`            | Auto-suspend (named) or auto-terminate (ephemeral) after this many seconds.               |
| `image`                  | `str \| None`       | platform default | Name or ID of a prebuilt [Sandbox Image](/sandboxes/images).                              |
| `snapshot_id`            | `str \| None`       | `None`           | Restore from a snapshot instead of booting a fresh VM.                                    |
| `secret_names`           | `list[str] \| None` | `None`           | Secrets to inject as environment variables. Must be pre-registered with `tl secrets set`. |
| `entrypoint`             | `list[str] \| None` | `None`           | Custom entrypoint command.                                                                |
| `allow_internet_access`  | `bool`              | `True`           | Allow outbound internet traffic (see [Networking](/sandboxes/networking)).                |
| `allow_out` / `deny_out` | `list[str] \| None` | `None`           | Outbound destination allow/deny lists.                                                    |

To expose user ports for inbound traffic, call [`sandbox.update(exposed_ports=..., allow_unauthenticated_access=...)`](#update) after `create()`.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    sandbox = Sandbox.create(
        name="my-env",
        cpus=2.0,
        memory_mb=4096,
        timeout_secs=1800,
        secret_names=["OPENAI_API_KEY"],
    )
    print(sandbox.sandbox_id, sandbox.status)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const sandbox = await Sandbox.create({
      name: "my-env",
      cpus: 2.0,
      memoryMb: 4096,
      timeoutSecs: 1800,
    });
    ```
  </Tab>
</Tabs>

### Create and connect

`Sandbox.create()` creates a sandbox and returns a live `Sandbox` handle you can immediately run commands against.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    sandbox = Sandbox.create(cpus=2.0, memory_mb=2048)
    result = sandbox.run("python", ["-c", "print('hello')"])
    print(result.stdout)
    # Context manager terminates the sandbox on exit
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const sandbox = await Sandbox.create({ cpus: 2.0, memoryMb: 2048 });
    try {
      const result = await sandbox.run("python", { args: ["-c", "print('hello')"] });
      console.log(result.stdout);
    } finally {
      await sandbox.terminate();
    }
    ```
  </Tab>
</Tabs>

### Connect

Get a `Sandbox` handle for an existing sandbox (by ID or name) without creating a new one. Use this to rejoin a named sandbox after `resume`, or to operate on a sandbox a different process created.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    sandbox = Sandbox.connect("my-env")
    print(sandbox.sandbox_id)  # always UUID, even if you connected by name
    print(sandbox.name)        # "my-env"
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const sandbox = Sandbox.connect("my-env");
    ```
  </Tab>
</Tabs>

### List and get

`Sandbox.connect()` attaches to a single sandbox by ID or name. To enumerate all sandboxes in your namespace, use `Sandbox.list()`.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    sandbox = Sandbox.connect("my-env")
    print(sandbox.sandbox_id, sandbox.name, sandbox.status)

    for sb in Sandbox.list():
        print(sb.sandbox_id, sb.status)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const sandbox = await Sandbox.connect("my-env");
    console.log(sandbox.sandboxId, sandbox.name, sandbox.status);
    ```
  </Tab>
</Tabs>

### Update

`sandbox.update()` is the unified instance method for changing a sandbox's name, exposed user ports, or unauthenticated-access flag — renaming and port exposure are the same call. Assigning a name to an ephemeral sandbox converts it to a named sandbox that supports suspend/resume.

| Parameter                      | Type                | Default | Description                                                                                              |
| ------------------------------ | ------------------- | ------- | -------------------------------------------------------------------------------------------------------- |
| `name`                         | `str \| None`       | `None`  | New name for the sandbox. Naming an ephemeral sandbox makes it non-ephemeral and enables suspend/resume. |
| `allow_unauthenticated_access` | `bool \| None`      | `None`  | Whether exposed user ports accept traffic without TensorLake auth.                                       |
| `exposed_ports`                | `list[int] \| None` | `None`  | User ports routable through the sandbox proxy. Port `9501` is reserved.                                  |

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    info = sandbox.update(name="my-env")
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const info = await sandbox.update({ name: "my-env" });
    ```
  </Tab>
</Tabs>

If you only have a sandbox ID (for example, from `Sandbox.list()`), connect first and chain `update()`:

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    info = Sandbox.connect("sbx-123").update(name="my-env", exposed_ports=[8080])
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const sandbox = await Sandbox.connect("sbx-123");
    const info = await sandbox.update({ name: "my-env", exposedPorts: [8080] });
    ```
  </Tab>
</Tabs>

### Suspend and resume

Pause a running named sandbox in place; resume it later under the same ID with its memory, filesystem, and running processes intact. Ephemeral sandboxes return an error on `suspend`.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    sandbox.suspend()
    sandbox.resume()
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    await sandbox.suspend();
    await sandbox.resume();
    ```
  </Tab>
</Tabs>

### Terminate

`terminate()` ends the sandbox permanently. `Terminated` is a final state and cannot be reversed.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    sandbox.terminate()
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    await sandbox.terminate();
    ```
  </Tab>
</Tabs>

See [Lifecycle](/sandboxes/lifecycle) for the full state machine.

### Expose and unexpose ports

Route public internet traffic to services listening on user ports inside the sandbox. Requests arrive at `https://<port>-<sandbox-id-or-name>.sandbox.tensorlake.ai`.

Port exposure is just a `sandbox.update()` call — pass `exposed_ports` and (optionally) `allow_unauthenticated_access`. Pass `exposed_ports=[]` to remove all exposed ports.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    sandbox.update(exposed_ports=[8080], allow_unauthenticated_access=False)
    sandbox.update(exposed_ports=[])  # remove all
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    await sandbox.update({ exposedPorts: [8080], allowUnauthenticatedAccess: false });
    await sandbox.update({ exposedPorts: [] }); // remove all
    ```
  </Tab>
</Tabs>

See [Networking](/sandboxes/networking) for authenticated vs. unauthenticated access and how clients reach user ports.

### Snapshot and restore

Capture a reusable artifact of the sandbox (filesystem + memory + running processes). Restore by passing `snapshot_id` to `Sandbox.create()`.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    snapshot = sandbox.checkpoint()

    # Restore into a fresh sandbox
    restored = Sandbox.create(snapshot_id=snapshot.snapshot_id)

    # Manage snapshots
    sandbox.list_snapshots()
    Sandbox.get_snapshot(snapshot.snapshot_id)
    Sandbox.delete_snapshot(snapshot.snapshot_id)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const snapshot = await sandbox.checkpoint();

    const restored = await Sandbox.create({ snapshotId: snapshot.snapshotId });

    await sandbox.listSnapshots();
    await Sandbox.getSnapshot(snapshot.snapshotId);
    await Sandbox.deleteSnapshot(snapshot.snapshotId);
    ```
  </Tab>
</Tabs>

Suspend pauses *this* sandbox; snapshot captures a reusable artifact you restore into a *new* sandbox. See [Snapshots](/sandboxes/snapshots).

## Sandbox handle

The `Sandbox` object returned by `Sandbox.create()` or `Sandbox.connect()` is how you execute work inside a running sandbox. All methods below target a single live sandbox.

| Property (Python) | Property (TypeScript) | Type          | Description                                   |
| ----------------- | --------------------- | ------------- | --------------------------------------------- |
| `sandbox_id`      | `sandboxId`           | `str`         | Server-assigned UUID.                         |
| `name`            | `name`                | `str \| None` | Human-readable name, or `None` for ephemeral. |

### Run a command

`run()` is the short-lived foreground execution primitive: send a command, wait for it to exit, receive captured output. Use it for the common case of "do this one thing and give me the result."

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    result = sandbox.run("python", ["-c", "print('hello')"], timeout=30)
    print(result.stdout)
    print(result.stderr)
    print(result.exit_code)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const result = await sandbox.run("python", {
      args: ["-c", "print('hello')"],
      timeout: 30,
    });
    console.log(result.stdout, result.stderr, result.exitCode);
    ```
  </Tab>
</Tabs>

Pass `env={"KEY": "value"}` (Python) or `env: { KEY: "value" }` (TypeScript) for per-command environment variables. See [Environment Variables](/sandboxes/environment-variables).

See [Execute Commands](/sandboxes/commands) for streaming, multi-step shell pipelines, and error handling.

### Background processes

For long-running or concurrent work, start a process and keep the handle so you can monitor, stream output, and signal it.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    proc = sandbox.start_process("python", ["-m", "http.server", "8080"])
    print(proc.pid)

    for p in sandbox.list_processes():
        print(p.pid, p.command, p.status)

    for event in sandbox.follow_output(proc.pid):
        print(event.line, end="")

    import signal
    sandbox.send_signal(proc.pid, signal.SIGTERM)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const proc = await sandbox.startProcess("python", { args: ["-m", "http.server", "8080"] });

    for (const p of await sandbox.listProcesses()) {
      console.log(p.pid, p.command, p.status);
    }

    for await (const event of sandbox.followOutput(proc.pid)) {
      console.log(event.line);
    }

    await sandbox.sendSignal(proc.pid, 15); // SIGTERM
    await sandbox.killProcess(proc.pid);    // SIGKILL
    ```
  </Tab>
</Tabs>

### Writing to stdin

Drive a process interactively from code by writing bytes to its stdin, then closing the stream when you're done.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    proc = sandbox.start_process("python", ["-c", "import sys; print(sys.stdin.read())"])
    sandbox.write_stdin(proc.pid, b"hello from stdin\n")
    sandbox.close_stdin(proc.pid)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const proc = await sandbox.startProcess("python", {
      args: ["-c", "import sys; print(sys.stdin.read())"],
    });
    await sandbox.writeStdin(proc.pid, new TextEncoder().encode("hello from stdin\n"));
    await sandbox.closeStdin(proc.pid);
    ```
  </Tab>
</Tabs>

See [Process Management](/sandboxes/processes) for the full API.

### PTY sessions

Open an interactive terminal inside the sandbox. The PTY is created over HTTPS; terminal I/O then moves over a WebSocket attached to the session.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    pty = sandbox.create_pty(
        command="bash",
        cols=120,
        rows=40,
        env={"PS1": "sandbox$ "},
    )
    # `pty` is a connected Pty handle — see PTY Sessions for send_input / resize / wait.
    # Reconnect later from session_id and token:
    reattached = sandbox.connect_pty(pty.session_id, pty.token)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const pty = await sandbox.createPty({
      command: "bash",
      cols: 120,
      rows: 40,
    });
    ```
  </Tab>
</Tabs>

See [PTY Sessions](/sandboxes/pty-sessions) for the wire protocol, reconnect flow, and resize frames.

### File operations

Copy data in and out of the sandbox filesystem without spawning a shell.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    sandbox.write_file("/workspace/data.csv", b"name,score\nAlice,95\n")

    content = bytes(sandbox.read_file("/workspace/data.csv"))
    print(content.decode("utf-8"))

    for entry in sandbox.list_directory("/workspace"):
        print(entry.name, entry.is_dir, entry.size)

    sandbox.delete_file("/workspace/data.csv")
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    await sandbox.writeFile(
      "/workspace/data.csv",
      new TextEncoder().encode("name,score\nAlice,95\n"),
    );

    const bytes = await sandbox.readFile("/workspace/data.csv");
    console.log(new TextDecoder().decode(bytes));

    const entries = await sandbox.listDirectory("/workspace");
    await sandbox.deleteFile("/workspace/data.csv");
    ```
  </Tab>
</Tabs>

See [File Operations](/sandboxes/file-operations) for binary uploads, recursive listings, and move/copy patterns.

### Desktop sessions

Desktop sandboxes expose a higher-level remote-control handle on top of the normal `Sandbox` APIs. Use this with `tensorlake/ubuntu-vnc` to capture screenshots and drive mouse and keyboard input through the authenticated sandbox proxy.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    with sandbox.connect_desktop(password="tensorlake") as desktop:
        png_bytes = desktop.screenshot()
        desktop.move_mouse(640, 400)
        desktop.click()
        desktop.type_text("hello from desktop")
        print(desktop.width, desktop.height)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const desktop = await sandbox.connectDesktop({ password: "tensorlake" });
    try {
      const pngBytes = await desktop.screenshot();
      await desktop.moveMouse(640, 400);
      await desktop.click();
      await desktop.typeText("hello from desktop");
      console.log(desktop.width, desktop.height);
    } finally {
      await desktop.close();
    }
    ```
  </Tab>
</Tabs>

Common desktop methods are:

| Python                          | TypeScript                    | Description                                      |
| ------------------------------- | ----------------------------- | ------------------------------------------------ |
| `screenshot()`                  | `screenshot()`                | Capture the current desktop as PNG bytes.        |
| `move_mouse(x, y)`              | `moveMouse(x, y)`             | Move the pointer to absolute screen coordinates. |
| `click()`                       | `click()`                     | Click the current pointer location.              |
| `double_click()`                | `doubleClick()`               | Double-click the current pointer location.       |
| `scroll_up()` / `scroll_down()` | `scrollUp()` / `scrollDown()` | Scroll vertically.                               |
| `press(keys)`                   | `press(keys)`                 | Send a key or key chord.                         |
| `type_text(text)`               | `typeText(text)`              | Type text into the active window.                |
| `width`, `height`               | `width`, `height`             | Desktop resolution.                              |

See [Computer Use](/sandboxes/computer-use) for reconnect patterns, coordinate workflows, and noVNC integration.

### Terminate

Shortcut for `sandbox.terminate()` that uses the handle you already have.

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    sandbox.terminate()
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    await sandbox.terminate();
    ```
  </Tab>
</Tabs>

## Data models

The SDK returns typed objects for every API call. The fields below are the ones you'll read most often. Field names shown in Python `snake_case`; TypeScript uses the `camelCase` equivalent.

### SandboxInfo

Returned by `Sandbox.create()`, `Sandbox.connect()`, `client.list()`, and the suspend/resume/expose calls.

| Field                          | Type                     | Description                                                                           |
| ------------------------------ | ------------------------ | ------------------------------------------------------------------------------------- |
| `sandbox_id`                   | `str`                    | Server UUID.                                                                          |
| `name`                         | `str \| None`            | Name, or `None` for ephemeral.                                                        |
| `namespace`                    | `str`                    | Namespace owning the sandbox.                                                         |
| `status`                       | `SandboxStatus`          | One of `pending`, `running`, `snapshotting`, `suspending`, `suspended`, `terminated`. |
| `image`                        | `str \| None`            | Sandbox image in use.                                                                 |
| `resources`                    | `ContainerResourcesInfo` | `.cpus: float`, `.memory_mb: int`.                                                    |
| `secret_names`                 | `list[str]`              | Injected secrets.                                                                     |
| `timeout_secs`                 | `int \| None`            | Auto-suspend/terminate timeout.                                                       |
| `exposed_ports`                | `list[int] \| None`      | Public-routed user ports.                                                             |
| `allow_unauthenticated_access` | `bool`                   | Whether exposed ports accept unauthenticated traffic.                                 |
| `entrypoint`                   | `list[str] \| None`      | Custom entrypoint command.                                                            |
| `network`                      | `NetworkConfig \| None`  | Outbound network configuration (`allow_internet_access`, `allow_out`, `deny_out`).    |
| `created_at`                   | `datetime \| None`       | Creation timestamp.                                                                   |
| `terminated_at`                | `datetime \| None`       | Termination timestamp (if terminated).                                                |

### Sandbox

Returned by `Sandbox.create()` and `Sandbox.connect()`. Exposes the runtime methods documented above plus:

| Property                   | Type          | Description                      |
| -------------------------- | ------------- | -------------------------------- |
| `sandbox_id` / `sandboxId` | `str`         | UUID, even if connected by name. |
| `name`                     | `str \| None` | Human-readable name.             |

### ProcessInfo

Returned by `start_process()` and `list_processes()`.

| Field        | Type               | Description                                              |
| ------------ | ------------------ | -------------------------------------------------------- |
| `pid`        | `int`              | Process ID inside the sandbox.                           |
| `command`    | `str`              | The executed command.                                    |
| `args`       | `list[str]`        | Command arguments.                                       |
| `status`     | `ProcessStatus`    | One of `running`, `exited`, `signaled`.                  |
| `exit_code`  | `int \| None`      | Exit code once the process has exited.                   |
| `signal`     | `int \| None`      | Signal number if the process was terminated by a signal. |
| `started_at` | `datetime`         | When the process started.                                |
| `ended_at`   | `datetime \| None` | When the process ended.                                  |

### CommandResult

Returned by `run()`.

| Field       | Type  | Description               |
| ----------- | ----- | ------------------------- |
| `stdout`    | `str` | Captured standard output. |
| `stderr`    | `str` | Captured standard error.  |
| `exit_code` | `int` | Process exit code.        |

### SnapshotInfo

Returned by the snapshot APIs.

| Field         | Type               | Description                                     |
| ------------- | ------------------ | ----------------------------------------------- |
| `snapshot_id` | `str`              | Server-assigned ID, use to restore.             |
| `sandbox_id`  | `str`              | Source sandbox this snapshot was captured from. |
| `status`      | `SnapshotStatus`   | One of `in_progress`, `completed`, `failed`.    |
| `size_bytes`  | `int \| None`      | Size of the snapshot artifact.                  |
| `created_at`  | `datetime \| None` | Capture timestamp.                              |

## Learn more

<CardGroup cols={3}>
  <Card title="Lifecycle" icon="arrows-spin" href="/sandboxes/lifecycle">
    State machine, suspend/resume, timeouts.
  </Card>

  <Card title="Execute Commands" icon="terminal" href="/sandboxes/commands">
    Run commands, capture output, stream.
  </Card>

  <Card title="Process Management" icon="microchip" href="/sandboxes/processes">
    Background processes, stdin, signals.
  </Card>

  <Card title="PTY Sessions" icon="keyboard" href="/sandboxes/pty-sessions">
    Interactive shells over WebSocket.
  </Card>

  <Card title="File Operations" icon="file" href="/sandboxes/file-operations">
    Read, write, list, delete.
  </Card>

  <Card title="Snapshots" icon="camera" href="/sandboxes/snapshots">
    Capture and restore full VM state.
  </Card>

  <Card title="Sandbox Images" icon="box" href="/sandboxes/images">
    Prebuild dependencies into reusable images.
  </Card>

  <Card title="Computer Use" icon="desktop" href="/sandboxes/computer-use">
    Desktop sessions, screenshots, mouse, keyboard.
  </Card>

  <Card title="Networking" icon="globe" href="/sandboxes/networking">
    Expose user ports to the internet.
  </Card>

  <Card title="Environment Variables" icon="gear" href="/sandboxes/environment-variables">
    Per-command and per-PTY environment.
  </Card>
</CardGroup>
