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

# Run commands and work with files

> Run commands and background processes, read and write files, and call HTTP services in a running sandbox with an SDK, the CLI, or the sandbox runtime API.

Baseten Sandboxes are now available and free to use until November 16. Each organization can run up to 10 sandboxes at once. To raise this limit, [contact support](mailto:support@baseten.co).

After a sandbox reaches status `DEPLOYED`, run commands and work with files
through its [sandbox runtime API](https://docs.baseten.co/sandboxes/overview.md#sandbox-apis). The SDKs and
the CLI call it for you, and direct HTTP requests and MCP clients call it at
the sandbox's URL.

The examples use a running sandbox named `hello-world` created from **Base
Image**, which includes Python. To create one, see
[Create a sandbox](https://docs.baseten.co/sandboxes/manage.md#create-a-sandbox). Before you start:

* [Set up your SDK or the CLI](https://docs.baseten.co/sandboxes/manage.md#set-up). The SDK examples
  read your API key from `BASETEN_API_KEY`, and the CLI examples read the
  sandbox name from `SANDBOX_NAME`.
* For direct HTTP requests and MCP clients, request a
  [sandbox access token](https://docs.baseten.co/sandboxes/authentication.md) and set `SANDBOX_TOKEN`.

## Connect to a sandbox

Each sandbox serves its sandbox runtime API at its own URL. The CLI and SDKs
look the URL up for you. Direct HTTP requests and MCP clients need it.

### Get the sandbox URL

The sandbox URL is the `url` field that the create and get requests return.
For what each part of the URL means, see
[Sandbox URLs](https://docs.baseten.co/sandboxes/overview.md#sandbox-urls).

**To get the sandbox URL**:

> [tab] TypeScript
>
> Run the following code:
>
> ```typescript theme={"system"}
> import { SandboxClient } from "@basetenlabs/sandbox";
>
> const client = new SandboxClient({ apiKey: process.env.BASETEN_API_KEY! });
> const sandbox = await client.get({ name: "hello-world" });
> console.log(sandbox.url);
> ```

> [tab] Python
>
> Run the following code:
>
> ```python Code theme={"system"}
> import os
>
> from baseten.sandbox import SandboxClient
>
> with SandboxClient(api_key=os.environ["BASETEN_API_KEY"]) as client:
>     sandbox = client.get(name="hello-world")
>     print(sandbox.url)
> ```
>
> ```txt Output theme={"system"}
> https://sbx-hello-world-abc123.us-pdx-1.b10.co/
> ```
>
> The Python SDK returns the URL with a trailing slash. Remove it before you
> append a path.

> [tab] Go
>
> Run the following code:
>
> ```go theme={"system"}
> package main
>
> import (
>     "context"
>     "fmt"
>     "log"
>     "os"
>
>     "github.com/basetenlabs/baseten-go/sandbox"
> )
>
> func main() {
>     ctx := context.Background()
>     client, err := sandbox.NewClient(sandbox.ClientOptions{
>         APIKey: os.Getenv("BASETEN_API_KEY"),
>     })
>     if err != nil {
>         log.Fatal(err)
>     }
>     sb, err := client.Get(ctx, sandbox.GetOptions{Name: "hello-world"})
>     if err != nil {
>         log.Fatal(err)
>     }
>     fmt.Println(sb.URL())
> }
> ```

> [tab] API
>
> Run the following command:
>
> ```bash theme={"system"}
> curl --url "https://api.baseten.co/v1/sandboxes/instances/$SANDBOX_NAME" \
>   --header "Authorization: Bearer $SANDBOX_TOKEN"
> ```
>
> The response's `url` field holds the URL. For more information, see
> [Get a sandbox](https://docs.baseten.co/reference/management-api/sandboxes/get-a-sandbox.md).

> [tab] CLI
>
> Run the following command:
>
> ```bash Command theme={"system"}
> baseten sandbox describe --name "$SANDBOX_NAME" --jq '.url'
> ```
>
> ```txt Output theme={"system"}
> "https://sbx-hello-world-abc123.us-pdx-1.b10.co"
> ```

> [tab] UI
>
> 1. Sign in to your workspace at [app.baseten.co](https://app.baseten.co)
>    and choose **Sandboxes** in the sidebar.
> 2. Choose the sandbox.
> 3. On **Overview**, choose **Connect**.
> 4. In the **Connect to sandbox** dialog, choose a tab and copy its value.

Use the URL exactly as the API returns it, and set `SANDBOX_URL` to it for
the HTTP examples on this page.

### Call the sandbox runtime API over HTTP

Send requests to the sandbox's URL with a sandbox access token as a bearer
token.

**To call the sandbox runtime API**:

1. Run the following command to send an authenticated request to the
   sandbox:

   ```bash Command theme={"system"}
   curl --url "$SANDBOX_URL" \
     --header "Authorization: Bearer $SANDBOX_TOKEN"
   ```

   ```json Output theme={"system"}
   {"message":"Welcome to your Baseten Sandbox. Discover your capabilities here: /swagger/doc.json","apiReference":"/swagger/doc.json","documentation":"https://docs.baseten.co/sandboxes/overview","description":"This sandbox provides a full-featured environment for running code securely. Visit the documentation to learn how to manage processes, access the filesystem, and more."}
   ```

2. Run the following command to download the OpenAPI spec for the API in that
   sandbox, including its file and process operations:

   ```bash theme={"system"}
   curl --url "${SANDBOX_URL%/}/swagger/doc.json" \
     --header "Authorization: Bearer $SANDBOX_TOKEN"
   ```

Requests without a valid sandbox access token return HTTP `401`. For more
information, see the [Sandbox runtime API reference](https://docs.baseten.co/reference/sandbox-api/overview.md).

### Open a terminal

The CLI opens an interactive shell in the sandbox. The SDKs don't open
terminals; use them to [run commands](#run-a-command) instead.

**To open an interactive terminal in the sandbox**:

Run the following command:

```bash theme={"system"}
baseten sandbox connect --name "$SANDBOX_NAME"
```

Press **Ctrl+D** to disconnect.

### Connect an MCP client

Each sandbox serves an MCP server at its URL followed by `/mcp`. An MCP client
connected to it gets tools for running commands and for reading, writing, and
editing files. This server is separate from the
[Baseten MCP](https://docs.baseten.co/agent-setup.md), which manages resources across your workspace.

**To connect an MCP client to the sandbox**:

Configure your MCP client with the following endpoint and authorization
header, replacing `<SANDBOX_URL>` with the sandbox's URL and
`<SANDBOX_TOKEN>` with a sandbox access token:

```text theme={"system"}
<SANDBOX_URL>/mcp
Authorization: Bearer <SANDBOX_TOKEN>
```

Applications that need tighter control than the MCP server's tools can define
their own tool functions that call an SDK.

## Run a command

Run a command in the sandbox and wait for it to exit. The result includes the
command's standard output, standard error, and exit code.

**To check the sandbox's Python version**:

> [tab] TypeScript
>
> Run the following code:
>
> ```typescript theme={"system"}
> import { SandboxClient } from "@basetenlabs/sandbox";
>
> const client = new SandboxClient({ apiKey: process.env.BASETEN_API_KEY! });
> const sandbox = await client.get({ name: "hello-world" });
> const result = await sandbox.process.exec({
>   command: "python3 --version",
>   waitForCompletion: true,
> });
> console.log(result.stdout, result.exitCode);
> ```

> [tab] Python
>
> Run the following code:
>
> ```python theme={"system"}
> import os
>
> from baseten.sandbox import SandboxClient
>
> with SandboxClient(api_key=os.environ["BASETEN_API_KEY"]) as client:
>     sandbox = client.get(name="hello-world")
>     result = sandbox.process.exec(command="python3 --version", wait_for_completion=True)
>     print(result.stdout, result.exit_code)
> ```

> [tab] Go
>
> Run the following code:
>
> ```go theme={"system"}
> package main
>
> import (
>     "context"
>     "fmt"
>     "log"
>     "os"
>
>     "github.com/basetenlabs/baseten-go/sandbox"
> )
>
> func main() {
>     ctx := context.Background()
>     client, err := sandbox.NewClient(sandbox.ClientOptions{
>         APIKey: os.Getenv("BASETEN_API_KEY"),
>     })
>     if err != nil {
>         log.Fatal(err)
>     }
>     sb, err := client.Get(ctx, sandbox.GetOptions{Name: "hello-world"})
>     if err != nil {
>         log.Fatal(err)
>     }
>     process, err := sb.Process().Exec(ctx, sandbox.ProcessExecOptions{
>         Command:           "python3 --version",
>         WaitForCompletion: true,
>     })
>     if err != nil {
>         log.Fatal(err)
>     }
>     fmt.Println(process.Stdout, process.ExitCode)
> }
> ```

> [tab] API
>
> Run the following command:
>
> ```bash Command theme={"system"}
> curl --request POST \
>   --url "${SANDBOX_URL%/}/process" \
>   --header "Authorization: Bearer $SANDBOX_TOKEN" \
>   --header "Content-Type: application/json" \
>   --data '{"command": "python3 --version", "waitForCompletion": true}'
> ```
>
> ```json Output theme={"system"}
> {"pid":"9","name":"proc-eq76750y","command":"python3 --version","status":"completed","startedAt":"Thu, 05 Nov 2026 18:49:12 GMT","completedAt":"Thu, 05 Nov 2026 18:49:12 GMT","exitCode":0,"workingDir":"/workspace","logs":"Python 3.12.15\n","stdout":"Python 3.12.15\n","stderr":"","restartOnFailure":false,"maxRestarts":0,"restartCount":0,"keepAlive":false,"stdin":false}
> ```
>
> The response is the process record, with the command's output in `stdout`
> and its exit code in `exitCode`. The request returns HTTP `200` even when
> the command exits with a nonzero code, so check `exitCode`.

> [tab] CLI
>
> Run the following command:
>
> ```bash Command theme={"system"}
> baseten sandbox exec --name "$SANDBOX_NAME" -- python3 --version
> ```
>
> ```txt Output theme={"system"}
> Python 3.12.15
> ```
>
> The command's output streams to your terminal, and its exit code becomes
> the CLI's exit code.

`DEPLOYED` means the sandbox is ready, not that a task succeeded. Confirm a
task by its command's exit code and output.

**To add environment variables to one command**:

These variables apply on top of the sandbox's own
[environment variables](https://docs.baseten.co/sandboxes/configure.md#set-environment-variables). Replace
`worker.py` with the path to your script in the sandbox.

> [tab] TypeScript
>
> Update the previous example as follows:
>
> ```typescript theme={"system"}
> const result = await sandbox.process.exec({
>   command: "python3 worker.py",
>   env: { LOG_LEVEL: "debug" },
>   waitForCompletion: true,
> });
> ```

> [tab] Python
>
> Update the previous example as follows:
>
> ```python theme={"system"}
> result = sandbox.process.exec(
>     command="python3 worker.py",
>     env={"LOG_LEVEL": "debug"},
>     wait_for_completion=True,
> )
> ```

> [tab] Go
>
> Update the previous example as follows:
>
> ```go theme={"system"}
> process, err := sb.Process().Exec(ctx, sandbox.ProcessExecOptions{
>     Command:           "python3 worker.py",
>     Env:               map[string]string{"LOG_LEVEL": "debug"},
>     WaitForCompletion: true,
> })
> ```

> [tab] API
>
> Run the following command:
>
> ```bash theme={"system"}
> curl --request POST \
>   --url "${SANDBOX_URL%/}/process" \
>   --header "Authorization: Bearer $SANDBOX_TOKEN" \
>   --header "Content-Type: application/json" \
>   --data '{"command": "python3 worker.py", "env": {"LOG_LEVEL": "debug"}, "waitForCompletion": true}'
> ```

> [tab] CLI
>
> Run the following command:
>
> ```bash theme={"system"}
> baseten sandbox exec --name "$SANDBOX_NAME" --env LOG_LEVEL=debug -- python3 worker.py
> ```

## Run a background process

Start a long-running command, such as a training script or a server, and
return right away. Give the process a name so you can wait for it, read its
output, or stop it later. A sandbox goes on
[standby](https://docs.baseten.co/sandboxes/lifecycle.md#active-and-standby) when it stops receiving
requests, which pauses its processes. Turn on keep-alive to keep the sandbox
active while the process runs.

**To run a background process and wait for it**:

> [tab] TypeScript
>
> Replace `worker.py` with the path to your script in the sandbox, then run
> the following code:
>
> ```typescript theme={"system"}
> import { SandboxClient } from "@basetenlabs/sandbox";
>
> const client = new SandboxClient({ apiKey: process.env.BASETEN_API_KEY! });
> const sandbox = await client.get({ name: "hello-world" });
> await sandbox.process.exec({
>   command: "python3 worker.py",
>   name: "worker",
>   keepAlive: true,
> });
> const finished = await sandbox.process.wait({ identifier: "worker" });
> console.log(finished.status, finished.exitCode);
> ```
>
> To list the sandbox's processes, call `sandbox.process.list()`. To stop a
> process, call `sandbox.process.stop({ identifier: "worker" })`, or
> `sandbox.process.kill({ identifier: "worker" })` to force it.

> [tab] Python
>
> Replace `worker.py` with the path to your script in the sandbox, then run
> the following code:
>
> ```python theme={"system"}
> import os
>
> from baseten.sandbox import SandboxClient
>
> with SandboxClient(api_key=os.environ["BASETEN_API_KEY"]) as client:
>     sandbox = client.get(name="hello-world")
>     sandbox.process.exec(command="python3 worker.py", name="worker", keep_alive=True)
>     finished = sandbox.process.wait(identifier="worker")
>     print(finished.status, finished.exit_code)
> ```
>
> To list the sandbox's processes, call `sandbox.process.list()`. To stop a
> process, call `sandbox.process.stop(identifier="worker")`, or
> `sandbox.process.kill(identifier="worker")` to force it.

> [tab] Go
>
> Replace `worker.py` with the path to your script in the sandbox, then run
> the following code:
>
> ```go theme={"system"}
> package main
>
> import (
>     "context"
>     "fmt"
>     "log"
>     "os"
>
>     "github.com/basetenlabs/baseten-go/sandbox"
> )
>
> func main() {
>     ctx := context.Background()
>     client, err := sandbox.NewClient(sandbox.ClientOptions{
>         APIKey: os.Getenv("BASETEN_API_KEY"),
>     })
>     if err != nil {
>         log.Fatal(err)
>     }
>     sb, err := client.Get(ctx, sandbox.GetOptions{Name: "hello-world"})
>     if err != nil {
>         log.Fatal(err)
>     }
>     if _, err := sb.Process().Exec(ctx, sandbox.ProcessExecOptions{
>         Command:   "python3 worker.py",
>         Name:      "worker",
>         KeepAlive: true,
>     }); err != nil {
>         log.Fatal(err)
>     }
>     finished, err := sb.Process().Wait(ctx, sandbox.ProcessWaitOptions{Identifier: "worker"})
>     if err != nil {
>         log.Fatal(err)
>     }
>     fmt.Println(finished.Status, finished.ExitCode)
> }
> ```
>
> To list the sandbox's processes, call `sb.Process().List`. To stop a
> process, call `sb.Process().Stop` with
> `sandbox.ProcessStopOptions{Identifier: "worker"}`, or `sb.Process().Kill`
> with `sandbox.ProcessKillOptions{Identifier: "worker"}` to force it.

> [tab] CLI
>
> The example runs a short shell command. Replace it with your own command.
>
> 1. Run the following command to start the process in the background:
>
>    ```bash theme={"system"}
>    baseten sandbox process start --name "$SANDBOX_NAME" --process-name worker --keep-alive -- 'sleep 3; echo finished'
>    ```
>
> 2. Run the following command to wait for the process to exit:
>
>    ```bash Command theme={"system"}
>    baseten sandbox process wait --name "$SANDBOX_NAME" --process-name worker
>    ```
>
>    ```txt Output theme={"system"}
>    PID:          20
>    Name:         worker
>    Command:      sleep 3; echo finished
>    Status:       completed
>    Exit code:    0
>    Working dir:  /workspace
>    Started:      2026-11-05T18:02:28Z
>    Completed:    2026-11-05T18:02:31Z
>    ```
>
>    The process's exit code becomes the CLI's exit code. Pass `--timeout`,
>    such as `--timeout 1h`, to stop waiting after a duration. Neither a
>    timeout nor **Ctrl+C** stops the process.
>
> 3. Run the following command to print the process's output:
>
>    ```bash Command theme={"system"}
>    baseten sandbox process logs --name "$SANDBOX_NAME" --process-name worker
>    ```
>
>    ```txt Output theme={"system"}
>    finished
>    ```
>
> To list the sandbox's processes, run the following command:
>
> ```bash theme={"system"}
> baseten sandbox process list --name "$SANDBOX_NAME"
> ```
>
> To stop a running process, run the following command:
>
> ```bash theme={"system"}
> baseten sandbox process stop --name "$SANDBOX_NAME" --process-name worker
> ```
>
> To force a process to stop, use `baseten sandbox process kill` with the
> same flags.

For more information, see
[`baseten sandbox process`](https://docs.baseten.co/reference/cli/baseten/sandbox#process) and the
[Sandbox runtime API reference](https://docs.baseten.co/reference/sandbox-api/overview.md).

## Read and write files

Write a file into the sandbox and read it back. Files in a sandbox last until
the sandbox is deleted or expires; see
[Local data](https://docs.baseten.co/sandboxes/lifecycle.md#local-data).

**To write and read a file**:

> [tab] TypeScript
>
> Run the following code:
>
> ```typescript theme={"system"}
> import { SandboxClient } from "@basetenlabs/sandbox";
>
> const client = new SandboxClient({ apiKey: process.env.BASETEN_API_KEY! });
> const sandbox = await client.get({ name: "hello-world" });
> await sandbox.fs.write({ path: "/tmp/hello.txt", content: "hello" });
> console.log(await sandbox.fs.read({ path: "/tmp/hello.txt" }));
> ```

> [tab] Python
>
> Run the following code:
>
> ```python theme={"system"}
> import os
>
> from baseten.sandbox import SandboxClient
>
> with SandboxClient(api_key=os.environ["BASETEN_API_KEY"]) as client:
>     sandbox = client.get(name="hello-world")
>     sandbox.fs.write(path="/tmp/hello.txt", content="hello")
>     print(sandbox.fs.read(path="/tmp/hello.txt"))
> ```
>
> For operations the SDK doesn't wrap, `sandbox.raw_api` is the generated
> client, and `client.sandbox_from_url(url=...)` builds a sandbox from a URL
> you already have.

> [tab] Go
>
> Run the following code:
>
> ```go theme={"system"}
> package main
>
> import (
>     "context"
>     "fmt"
>     "log"
>     "os"
>
>     "github.com/basetenlabs/baseten-go/sandbox"
> )
>
> func main() {
>     ctx := context.Background()
>     client, err := sandbox.NewClient(sandbox.ClientOptions{
>         APIKey: os.Getenv("BASETEN_API_KEY"),
>     })
>     if err != nil {
>         log.Fatal(err)
>     }
>     sb, err := client.Get(ctx, sandbox.GetOptions{Name: "hello-world"})
>     if err != nil {
>         log.Fatal(err)
>     }
>     if err := sb.FS().Write(ctx, sandbox.FileSystemWriteOptions{
>         Path:    "/tmp/hello.txt",
>         Content: "hello",
>     }); err != nil {
>         log.Fatal(err)
>     }
>     content, err := sb.FS().Read(ctx, sandbox.FileSystemReadOptions{Path: "/tmp/hello.txt"})
>     if err != nil {
>         log.Fatal(err)
>     }
>     fmt.Println(content)
> }
> ```

> [tab] API
>
> 1. Run the following command to write the file:
>
>    ```bash Command theme={"system"}
>    curl --request PUT \
>      --url "${SANDBOX_URL%/}/filesystem/tmp/hello.txt" \
>      --header "Authorization: Bearer $SANDBOX_TOKEN" \
>      --header "Content-Type: application/json" \
>      --data '{"content": "hello"}'
>    ```
>
>    ```json Output theme={"system"}
>    {"path":"tmp/hello.txt","message":"File created/updated successfully"}
>    ```
>
> 2. Run the following command to read it back:
>
>    ```bash Command theme={"system"}
>    curl --url "${SANDBOX_URL%/}/filesystem/tmp/hello.txt" \
>      --header "Authorization: Bearer $SANDBOX_TOKEN"
>    ```
>
>    ```json Output theme={"system"}
>    {"path":"tmp/hello.txt","name":"hello.txt","permissions":"644","size":5,"lastModified":"2026-11-05T18:49:12.167688818Z","owner":"root","group":"root","content":"hello"}
>    ```
>
>    The file's text is in the `content` field.

> [tab] CLI
>
> The CLI doesn't have file commands. Run the following command to read a
> file with `cat`:
>
> ```bash theme={"system"}
> baseten sandbox exec --name "$SANDBOX_NAME" -- cat /tmp/hello.txt
> ```

The SDKs also list, find, search, copy, and remove files. For every file
operation, see the [Sandbox runtime API reference](https://docs.baseten.co/reference/sandbox-api/overview.md).

## Call an HTTP service in a sandbox

Start an HTTP service in the sandbox, then send requests to it through the
sandbox runtime API's `/port/<PORT>/` route with a sandbox access token. Use
this route for your own code. To open an application in a browser or share it,
create a [preview](https://docs.baseten.co/sandboxes/previews.md) instead.

Serve your application on a port other than `8080`, where the sandbox API
server listens, and `80`, which the sandbox reserves for system services. The
examples use port `8000`. The service must be listening before you send the
request.

**To call an HTTP service in the sandbox**:

> [tab] TypeScript
>
> Run the following code to start the server, wait until it listens on port
> `8000`, send a request, and stop the server:
>
> ```typescript Code theme={"system"}
> import { SandboxClient } from "@basetenlabs/sandbox";
>
> const client = new SandboxClient({ apiKey: process.env.BASETEN_API_KEY! });
> const sandbox = await client.get({ name: "hello-world" });
> await sandbox.process.exec({
>   command: "python3 -m http.server 8000",
>   name: "web",
>   waitForPorts: [8000],
> });
> try {
>   const response = await fetch(`${sandbox.url.replace(/\/$/, "")}/port/8000/`, {
>     headers: { Authorization: `Bearer ${process.env.SANDBOX_TOKEN}` },
>   });
>   console.log(await response.text());
> } finally {
>   await sandbox.process.stop({ identifier: "web" });
> }
> ```
>
> ```txt Output theme={"system"}
> <!DOCTYPE HTML>
> <html lang="en">
> <head>
> <meta charset="utf-8">
> <title>Directory listing for /</title>
> ...
> ```

> [tab] Python
>
> Run the following code to start the server, wait until it listens on port
> `8000`, send a request, and stop the server:
>
> ```python Code theme={"system"}
> import os
> from urllib.request import Request, urlopen
>
> from baseten.sandbox import SandboxClient
>
> with SandboxClient(api_key=os.environ["BASETEN_API_KEY"]) as client:
>     sandbox = client.get(name="hello-world")
>     sandbox.process.exec(
>         command="python3 -m http.server 8000",
>         name="web",
>         wait_for_ports=[8000],
>     )
>     try:
>         request = Request(
>             f"{sandbox.url.rstrip('/')}/port/8000/",
>             headers={"Authorization": f"Bearer {os.environ['SANDBOX_TOKEN']}"},
>         )
>         with urlopen(request) as response:
>             print(response.read().decode())
>     finally:
>         sandbox.process.stop(identifier="web")
> ```
>
> ```txt Output theme={"system"}
> <!DOCTYPE HTML>
> <html lang="en">
> <head>
> <meta charset="utf-8">
> <title>Directory listing for /</title>
> ...
> ```

> [tab] Go
>
> Run the following code to start the server, wait until it listens on port
> `8000`, send a request, and stop the server:
>
> ```go Code theme={"system"}
> package main
>
> import (
>     "context"
>     "io"
>     "log"
>     "net/http"
>     "os"
>     "strings"
>
>     "github.com/basetenlabs/baseten-go/sandbox"
> )
>
> func main() {
>     ctx := context.Background()
>     client, err := sandbox.NewClient(sandbox.ClientOptions{
>         APIKey: os.Getenv("BASETEN_API_KEY"),
>     })
>     if err != nil {
>         log.Fatal(err)
>     }
>     sb, err := client.Get(ctx, sandbox.GetOptions{Name: "hello-world"})
>     if err != nil {
>         log.Fatal(err)
>     }
>     _, err = sb.Process().Exec(ctx, sandbox.ProcessExecOptions{
>         Command:      "python3 -m http.server 8000",
>         Name:         "web",
>         WaitForPorts: []int{8000},
>     })
>     if err != nil {
>         log.Fatal(err)
>     }
>     defer sb.Process().Stop(ctx, sandbox.ProcessStopOptions{Identifier: "web"})
>
>     request, err := http.NewRequestWithContext(ctx, http.MethodGet, strings.TrimRight(sb.URL(), "/")+"/port/8000/", nil)
>     if err != nil {
>         log.Print(err)
>         return
>     }
>     request.Header.Set("Authorization", "Bearer "+os.Getenv("SANDBOX_TOKEN"))
>     response, err := http.DefaultClient.Do(request)
>     if err != nil {
>         log.Print(err)
>         return
>     }
>     defer response.Body.Close()
>     if _, err := io.Copy(os.Stdout, response.Body); err != nil {
>         log.Print(err)
>     }
> }
> ```
>
> ```txt Output theme={"system"}
> <!DOCTYPE HTML>
> <html lang="en">
> <head>
> <meta charset="utf-8">
> <title>Directory listing for /</title>
> ...
> ```

> [tab] API
>
> 1. Run the following command to start the server and wait until it listens
>    on port `8000`:
>
>    ```bash theme={"system"}
>    curl --request POST \
>      --url "${SANDBOX_URL%/}/process" \
>      --header "Authorization: Bearer $SANDBOX_TOKEN" \
>      --header "Content-Type: application/json" \
>      --data '{"command": "python3 -m http.server 8000", "name": "web", "waitForPorts": [8000]}'
>    ```
>
> 2. Run the following command to request the server's directory listing:
>
>    ```bash Command theme={"system"}
>    curl --url "${SANDBOX_URL%/}/port/8000/" \
>      --header "Authorization: Bearer $SANDBOX_TOKEN"
>    ```
>
>    ```txt Output theme={"system"}
>    <!DOCTYPE HTML>
>    <html lang="en">
>    <head>
>    <meta charset="utf-8">
>    <title>Directory listing for /</title>
>    ...
>    ```
>
> 3. When you're finished, run the following command to stop the server:
>
>    ```bash theme={"system"}
>    curl --request DELETE \
>      --url "${SANDBOX_URL%/}/process/web" \
>      --header "Authorization: Bearer $SANDBOX_TOKEN"
>    ```

> [tab] CLI
>
> 1. Run the following command to start the server and wait until it listens
>    on port `8000`:
>
>    ```bash theme={"system"}
>    baseten sandbox process start --name "$SANDBOX_NAME" \
>      --process-name web --wait-for-port 8000 -- python3 -m http.server 8000
>    ```
>
> 2. Run the following command to request the server's directory listing:
>
>    ```bash Command theme={"system"}
>    curl --url "${SANDBOX_URL%/}/port/8000/" \
>      --header "Authorization: Bearer $SANDBOX_TOKEN"
>    ```
>
>    ```txt Output theme={"system"}
>    <!DOCTYPE HTML>
>    <html lang="en">
>    <head>
>    <meta charset="utf-8">
>    <title>Directory listing for /</title>
>    ...
>    ```
>
> 3. When you're finished, run the following command to stop the server:
>
>    ```bash theme={"system"}
>    baseten sandbox process stop --name "$SANDBOX_NAME" --process-name web
>    ```

A successful request returns HTTP `200` with Python's directory listing.
Requests without the sandbox access token return HTTP `401`.

## Next steps

> [card] [Preview a sandbox application](https://docs.baseten.co/sandboxes/previews.md)
>
> Open a running web application in a browser or share it.

> [card] [Inspect sandbox logs](https://docs.baseten.co/sandboxes/logs.md)
>
> Read command output and the sandbox's runtime logs.
