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

# Commands & Processes

> Run commands, capture and stream output, and start, manage, and signal background processes

Run shell commands inside sandboxes with full stdout/stderr capture, real-time streaming, and configurable timeouts — then keep long-running services alive with background processes, signals, stdin, and supervised restarts.

Commands and processes share one API. Use `run` / `exec` when you want to **run something and wait for the result**; use `start_process` when you want to **start something that keeps running** and manage its lifecycle.

<Tip>
  Use [Sandbox Process Logs](/sandboxes/process-logs) when you want to browse, search, and filter retained stdout/stderr across processes in the Console.
</Tip>

<Note>
  Sandbox-specific operations use sandbox-specific ingress, commonly seen as `https://<sandbox-id-or-name>.sandbox.tensorlake.ai`, derived from the sandbox's `ingress_endpoint`.

  For named sandboxes, you can use the sandbox **name** in place of the ID — both in the proxy hostname and in CLI/API commands. For example, `https://my-env.sandbox.tensorlake.ai/api/v1/processes` and `tl sbx exec my-env python main.py` work the same as their ID-based equivalents. The proxy resolves the name to the underlying sandbox automatically.

  The command and process APIs documented here run on the management URL on port `9501`, which always requires authentication. Unauthenticated proxy access applies only to exposed user ports.
</Note>

## Basic Execution

<Tabs>
  <Tab title="CLI">
    ```bash theme={null}
    # Run in an existing sandbox — use the sandbox ID or name
    tl sbx exec my-env python -c 'print("Hello from sandbox!")'

    # Or create, run, and tear down in one step
    tl sbx run python -c 'print("Hello from sandbox!")'
    ```
  </Tab>

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

    sandbox = Sandbox.create()
    result = sandbox.run("python", ["-c", "print('Hello from sandbox!')"])
    print(result.stdout)     # Hello from sandbox!
    print(result.exit_code)  # 0
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const result = await sandbox.run("python", {
      args: ["-c", "print('Hello from sandbox!')"],
    });

    console.log(result.stdout);   // Hello from sandbox!
    console.log(result.exitCode); // 0
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    # Start a Python process inside the sandbox
    curl -X POST https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes \
      -H "Authorization: Bearer $TL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "command": "python",
        "args": ["-c", "print(\"Hello from sandbox!\")"]
      }'
    ```

    **Response:**

    ```json theme={null}
    {
      "pid": 294,
      "status": "running",
      "exit_code": null,
      "signal": null,
      "stdin_writable": false,
      "command": "python",
      "args": ["-c", "print(\"Hello from sandbox!\")"],
      "started_at": 1773950042728,
      "ended_at": null
    }
    ```
  </Tab>
</Tabs>

## CLI Options

<Tabs>
  <Tab title="CLI">
    ```bash theme={null}
    # Timeout is in seconds
    tl sbx exec <sandbox-id> --timeout 10 python -c 'print("hi")'

    # Run from a specific working directory
    tl sbx exec <sandbox-id> --workdir /workspace python main.py

    # Inject environment variables into a single command
    tl sbx exec <sandbox-id> --env MODE=prod --env DEBUG=0 /bin/sh -lc 'printf "%s %s\n" "$MODE" "$DEBUG"'

    # Keep the sandbox after a one-shot run so you can inspect it afterwards
    tl sbx run --keep /bin/sh -lc 'echo KEEP_TEST && sleep 1'
    ```

    A verified `--env` run printed `prod 0`. A verified `--keep` run ended with `Sandbox <id> kept alive.`, and `tl sbx ls --all` then showed that sandbox as `running`.
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    # Run with a timeout, working directory, and per-command environment
    result = sandbox.run(
        "python",
        ["main.py"],
        env={"MODE": "prod", "DEBUG": "0"},
        working_dir="/workspace",
        timeout=10,
    )
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const result = await sandbox.run("python", {
      args: ["main.py"],
      env: { MODE: "prod", DEBUG: "0" },
      workingDir: "/workspace",
      timeout: 10,
    });

    console.log(result.exitCode);
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    # Start a process with custom environment variables and working directory
    curl -X POST https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes \
      -H "Authorization: Bearer $TL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "command": "python",
        "args": ["main.py"],
        "env": {"MODE": "prod", "DEBUG": "0"},
        "working_dir": "/workspace"
      }'
    ```
  </Tab>
</Tabs>

## Shell Commands

<Tabs>
  <Tab title="CLI">
    ```bash theme={null}
    # Count Python files in /workspace with a pipe
    tl sbx exec <sandbox-id> bash -c "ls -la /workspace | grep '.py' | wc -l"

    # Redirect stdout and stderr to files
    tl sbx exec <sandbox-id> bash -c "python script.py > output.txt 2> errors.txt"

    # Chain setup and execution in one shell command
    tl sbx exec <sandbox-id> bash -c "cd /workspace && pip install -r requirements.txt && python main.py"
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    # Pipes
    result = sandbox.run("bash", ["-c", "ls -la /workspace | grep '.py' | wc -l"])
    print(result.stdout)

    # Redirects
    sandbox.run("bash", ["-c", "python script.py > output.txt 2> errors.txt"])

    # Command chaining
    sandbox.run("bash", ["-c", "cd /workspace && pip install -r requirements.txt && python main.py"])
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const count = await sandbox.run("bash", {
      args: ["-lc", "ls -la /workspace | grep '.py' | wc -l"],
    });
    console.log(count.stdout);

    await sandbox.run("bash", {
      args: ["-lc", "python script.py > output.txt 2> errors.txt"],
    });

    await sandbox.run("bash", {
      args: [
        "-lc",
        "cd /workspace && pip install -r requirements.txt && python main.py",
      ],
    });
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    # Use bash when you need pipes, redirects, or command chaining
    curl -X POST https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes \
      -H "Authorization: Bearer $TL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "command": "bash",
        "args": ["-c", "ls -la /workspace | grep .py | wc -l"]
      }'
    ```
  </Tab>
</Tabs>

## Get Process Output

Fetch the buffered stdout, stderr, or combined output of a running or finished process.

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

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

    const proc = await sandbox.startProcess("python", {
      args: [
        "-c",
        "import sys; print('hello'); print('oops', file=sys.stderr)",
      ],
    });

    let info = await sandbox.getProcess(proc.pid);
    while (info.status === ProcessStatus.RUNNING) {
      await new Promise((resolve) => setTimeout(resolve, 100));
      info = await sandbox.getProcess(proc.pid);
    }

    console.log((await sandbox.getStdout(proc.pid)).lines);
    console.log((await sandbox.getStderr(proc.pid)).lines);
    console.log((await sandbox.getOutput(proc.pid)).lines);
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    # Get stdout
    curl https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes/<pid>/stdout \
      -H "Authorization: Bearer $TL_API_KEY"

    # Get stderr
    curl https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes/<pid>/stderr \
      -H "Authorization: Bearer $TL_API_KEY"

    # Get combined output
    curl https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes/<pid>/output \
      -H "Authorization: Bearer $TL_API_KEY"
    ```

    **Combined output response:**

    ```json theme={null}
    {
      "pid": 297,
      "lines": ["hello", "oops"],
      "line_count": 2
    }
    ```
  </Tab>

  <Tab title="CLI">
    Not supported in the CLI.
  </Tab>
</Tabs>

## Error Handling

<Tabs>
  <Tab title="CLI">
    ```bash theme={null}
    # The CLI prints stderr and returns a non-zero exit code on failure
    tl sbx exec <sandbox-id> python -c "import nonexistent_module"
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    sandbox = Sandbox.create()
    result = sandbox.run("python", ["-c", "import nonexistent_module"])

    if result.exit_code != 0:
        print(f"Command failed with exit code {result.exit_code}")
        print(f"stderr: {result.stderr}")
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const result = await sandbox.run("python", {
      args: ["-c", "import nonexistent_module"],
    });

    if (result.exitCode !== 0) {
      console.log(`Command failed with exit code ${result.exitCode}`);
      console.log(`stderr: ${result.stderr}`);
    }
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    # Check the exited process status
    curl https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes/<pid> \
      -H "Authorization: Bearer $TL_API_KEY"
    ```

    **Process status response:**

    ```json theme={null}
    {
      "pid": 305,
      "status": "exited",
      "exit_code": 1,
      "signal": null,
      "stdin_writable": false,
      "command": "python",
      "args": ["-c", "import nonexistent_module"],
      "started_at": 1773950228855,
      "ended_at": 1773950228866
    }
    ```

    **stderr response:**

    ```json theme={null}
    {
      "pid": 305,
      "lines": [
        "Traceback (most recent call last):",
        "  File \"<string>\", line 1, in <module>",
        "ModuleNotFoundError: No module named 'nonexistent_module'"
      ],
      "line_count": 3
    }
    ```
  </Tab>
</Tabs>

## Start a Background Process

Use `start_process` for work that should keep running after the call returns — servers, watchers, and other long-lived jobs.

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

    sandbox = Sandbox.create()
    # Start a background process
    proc = sandbox.start_process("python", ["-m", "http.server", "8080"])
    print(f"PID: {proc.pid}")
    ```
  </Tab>

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

    console.log(`PID: ${proc.pid}`);
    ```
  </Tab>

  <Tab title="CLI">
    ```bash theme={null}
    # Run a command in the background using shell syntax
    tl sbx exec <sandbox-id> bash -c "python -m http.server 8080 &"
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    curl -X POST https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes \
      -H "Authorization: Bearer $TL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "command": "python",
        "args": ["-m", "http.server", "8080"]
      }'
    ```

    **Response** (`201 Created`):

    ```json theme={null}
    {
      "pid": 42,
      "status": "running",
      "command": "python",
      "args": ["-m", "http.server", "8080"],
      "stdin_writable": false,
      "started_at": 1710000000000
    }
    ```

    **Request options:**

    ```json theme={null}
    {
      "command": "python",
      "args": ["-m", "http.server", "8080"],
      "env": {"PORT": "8080"},
      "working_dir": "/workspace",
      "stdin_mode": "pipe",
      "stdout_mode": "capture",
      "stderr_mode": "capture"
    }
    ```
  </Tab>
</Tabs>

## List Processes

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    procs = sandbox.list_processes()
    for p in procs:
        print(f"PID {p.pid}: {p.status}")
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const processes = await sandbox.listProcesses();
    for (const proc of processes) {
      console.log(`PID ${proc.pid}: ${proc.status}`);
    }
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    curl https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes \
      -H "Authorization: Bearer $TL_API_KEY"
    ```

    **Response:**

    ```json theme={null}
    {
      "processes": [
        {
          "pid": 42,
          "status": "running",
          "command": "python",
          "args": ["-m", "http.server", "8080"],
          "stdin_writable": false,
          "started_at": 1710000000000
        }
      ]
    }
    ```
  </Tab>
</Tabs>

## Stream Output

Stream stdout/stderr in real time for long-running commands using Server-Sent Events:

<Tabs>
  <Tab title="CLI">
    `tl sbx exec` streams combined output to your terminal while the process runs.
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    # Start a long-running process
    sandbox = Sandbox.create()
    proc = sandbox.start_process("python", ["-c", """
    import time
    for i in range(5):
        print(f"Step {i+1}/5")
        time.sleep(1)
    """])

    # Stream output as it arrives
    for event in sandbox.follow_output(proc.pid):
        print(event.line, end="")
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    const proc = await sandbox.startProcess("python", {
      args: [
        "-c",
        "import time\nfor i in range(5):\n print(f'Step {i+1}/5')\n time.sleep(1)",
      ],
    });

    for await (const event of sandbox.followOutput(proc.pid)) {
      process.stdout.write(event.line);
    }
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    # Follow stdout via SSE
    curl -N https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes/<pid>/stdout/follow \
      -H "Authorization: Bearer $TL_API_KEY"

    # Follow combined output via SSE
    curl -N https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes/<pid>/output/follow \
      -H "Authorization: Bearer $TL_API_KEY"
    ```

    **SSE stream:**

    ```
    event: output
    data: {"line":"Step 1/2","timestamp":1773950220162,"stream":"stdout"}

    event: output
    data: {"line":"Step 2/2","timestamp":1773950220162,"stream":"stdout"}

    event: eof
    data: {}
    ```
  </Tab>
</Tabs>

## Send Signals

Send POSIX signals to running processes:

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    import signal

    proc = sandbox.start_process("python", ["-m", "http.server", "8080"])

    # Gracefully stop the process
    sandbox.send_signal(proc.pid, signal.SIGTERM)
    ```
  </Tab>

  <Tab title="TypeScript">
    ```typescript theme={null}
    await sandbox.sendSignal(proc.pid, 15);
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    # Send SIGTERM (15)
    curl -X POST https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes/<pid>/signal \
      -H "Authorization: Bearer $TL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"signal": 15}'

    # Send SIGKILL (9)
    curl -X POST https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes/<pid>/signal \
      -H "Authorization: Bearer $TL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"signal": 9}'
    ```
  </Tab>
</Tabs>

## Kill a Process

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    import signal

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

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

  <Tab title="HTTP">
    ```bash theme={null}
    curl -X DELETE https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes/<pid> \
      -H "Authorization: Bearer $TL_API_KEY"
    ```
  </Tab>
</Tabs>

## Write to Stdin

Send input to a running process started with stdin in pipe mode:

```typescript theme={null}
import { StdinMode } from "tensorlake";

const proc = await sandbox.startProcess("python", {
  args: ["-i"],
  stdinMode: StdinMode.PIPE,
});

await sandbox.writeStdin(
  proc.pid,
  new TextEncoder().encode("print('hello')\n"),
);

await sandbox.closeStdin(proc.pid);
```

```bash theme={null}
# Start a process with stdin pipe
curl -X POST https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes \
  -H "Authorization: Bearer $TL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"command": "python", "args": ["-i"], "stdin_mode": "pipe"}'

# Write to stdin
curl -X POST https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes/<pid>/stdin \
  -H "Authorization: Bearer $TL_API_KEY" \
  -H "Content-Type: application/octet-stream" \
  --data-binary "print('hello')\n"

# Close stdin
curl -X POST https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes/<pid>/stdin/close \
  -H "Authorization: Bearer $TL_API_KEY"
```

## Managed Processes

Use a managed process for long-running services that should restart after a crash or failed health check. Managed processes use the same process API as normal background commands, but opt into supervision when you provide a `name`, a restart policy, or a health check.

<Note>
  Managed process flags start a background process. In the CLI, these flags require `--detach`. For blocking one-shot commands that stream output and return an exit code, use plain `tl sbx exec` or `sandbox.run(...)`.
</Note>

<Tabs>
  <Tab title="CLI">
    ```bash theme={null}
    # Start and supervise a web server. The CLI prints the PID.
    tl sbx exec <sandbox-id> --detach \
      --name dev-server \
      --restart always \
      --health-http 8080 \
      python -m http.server 8080

    # Inspect the managed process
    tl sbx ps <sandbox-id> <pid> --json

    # Manually restart it through the supervisor
    tl sbx restart <sandbox-id> <pid>

    # Stop the process and remove it from supervision
    tl sbx kill <sandbox-id> <pid>
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    from tensorlake.sandbox import (
        ProcessHealthCheck,
        ProcessHealthCheckType,
        RestartPolicy,
        RestartPolicyConfig,
        Sandbox,
    )


    sandbox = Sandbox.create()
    proc = sandbox.start_process(
        "python",
        args=["-m", "http.server", "8080"],
        user="root",
        name="dev-server",
        restart=RestartPolicyConfig(
            policy=RestartPolicy.ALWAYS,
            max_restarts=10,
            initial_backoff_ms=500,
            max_backoff_ms=30_000,
        ),
        health_check=ProcessHealthCheck(
            type=ProcessHealthCheckType.HTTP,
            port=8080,
            path="/",
            interval_ms=1_000,
            failure_threshold=3,
        ),
    )

    print(proc.pid)
    print(proc.managed.status)
    print(proc.managed.health_status)

    current = sandbox.get_process(proc.pid)
    restarted = sandbox.restart_process(proc.pid)
    ```
  </Tab>

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

    const sandbox = await Sandbox.create();
    const proc = await sandbox.startProcess("python", {
      args: ["-m", "http.server", "8080"],
      user: "root",
      name: "dev-server",
      restart: {
        policy: "always",
        maxRestarts: 10,
        initialBackoffMs: 500,
        maxBackoffMs: 30_000,
      },
      healthCheck: {
        type: "http",
        port: 8080,
        path: "/",
        intervalMs: 1_000,
        failureThreshold: 3,
      },
    });

    console.log(proc.pid);
    console.log(proc.managed?.status);
    console.log(proc.managed?.healthStatus);

    const current = await sandbox.getProcess(proc.pid);
    const restarted = await sandbox.restartProcess(proc.pid);
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    curl -X POST https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes \
      -H "Authorization: Bearer $TL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "command": "python",
        "args": ["-m", "http.server", "8080"],
        "user": "root",
        "name": "dev-server",
        "restart": {
          "policy": "always",
          "max_restarts": 10,
          "initial_backoff_ms": 500,
          "max_backoff_ms": 30000
        },
        "health_check": {
          "type": "http",
          "port": 8080,
          "path": "/",
          "interval_ms": 1000,
          "failure_threshold": 3
        }
      }'
    ```

    **Managed response fields:**

    ```json theme={null}
    {
      "pid": 42,
      "status": "running",
      "command": "python",
      "args": ["-m", "http.server", "8080"],
      "managed": {
        "id": "dev-server",
        "name": "dev-server",
        "status": "running",
        "restart_count": 0,
        "restart": {"policy": "always"},
        "health_status": "starting",
        "consecutive_health_failures": 0
      }
    }
    ```

    ```bash theme={null}
    # Manual managed restart
    curl -X POST https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/processes/<pid>/restart \
      -H "Authorization: Bearer $TL_API_KEY"
    ```
  </Tab>
</Tabs>

Restart policies are `never`, `on_failure`, and `always`. Health checks can be HTTP checks against a local sandbox port and optional path, or TCP checks against a local port. Process user selection accepts a username such as `root`, a UID string, a `uid:gid` string, or an object such as `{"uid": 1000, "gid": 1000}`. The default user is `tl-user`.

## Interactive Shell

<Tabs>
  <Tab title="CLI">
    ```bash theme={null}
    # Open an interactive shell in the sandbox
    tl sbx ssh <sandbox-id>

    # Use a custom shell
    tl sbx ssh <sandbox-id> --shell /bin/sh
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    pty = sandbox.create_pty(
        command="/bin/bash",
        rows=24,
        cols=80,
    )

    pty.send_input("pwd\nexit\n")
    print(pty.wait())
    ```
  </Tab>

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

    await pty.sendInput("pwd\nexit\n");
    console.log(await pty.wait());
    ```
  </Tab>

  <Tab title="HTTP">
    ```bash theme={null}
    # 1. Create a PTY session
    curl -X POST https://<sandbox-id>.sandbox.tensorlake.ai/api/v1/pty \
      -H "Authorization: Bearer $TL_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"command": "/bin/bash", "rows": 24, "cols": 80}'
    ```

    **Response:**

    ```json theme={null}
    {
      "session_id": "LYtJOrxE9Kz3bphPUDzuX",
      "token": "<pty-session-token>"
    }
    ```

    ```bash theme={null}
    # 2. Connect via WebSocket
    wscat -c "wss://<sandbox-id>.sandbox.tensorlake.ai/api/v1/pty/<session-id>/ws?token=<token>"
    ```
  </Tab>
</Tabs>

`tl sbx ssh` requires an interactive terminal and automatically resumes a suspended sandbox before opening the PTY session.

For the full programmatic PTY flow, including the `READY` handshake, binary WebSocket opcodes, and clean shutdown, see [PTY Sessions](/sandboxes/pty-sessions).

## Learn More

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

  <Card title="File Operations" icon="folder-open" href="/sandboxes/file-operations">
    Read, write, and copy files.
  </Card>

  <Card title="Lifecycle" icon="arrows-spin" href="/sandboxes/lifecycle">
    Sandbox states, resources, and timeouts.
  </Card>

  <Card title="Networking" icon="globe" href="/sandboxes/networking">
    Control internet access and outbound destinations.
  </Card>
</CardGroup>
