> ## Documentation Index
> Fetch the complete documentation index at: https://porter-mintlify-ad55ccfe.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# TypeScript Sandbox SDK quickstart

> Create and manage Porter Sandboxes from TypeScript

The TypeScript Sandbox SDK is published as `porter-sandbox`. Use it from application code running in your sandbox-enabled Porter cluster.

<Warning>
  Sandboxes are in a private beta. Please reach out to us at [support@porter.run](mailto:support@porter.run) or over Slack if you are interested in joining.
</Warning>

## Install

Add the SDK to your application:

```bash theme={null}
npm install porter-sandbox
```

## Create your first sandbox

Create a sandbox, execute a command, print the command output, and terminate the sandbox when the work is done:

```typescript theme={null}
import { Porter } from "porter-sandbox";

const porter = new Porter();

const sandbox = await porter.sandboxes.create({
  image: "python:3.12-slim",
  name: "typescript-quickstart",
  tags: { example: "typescript-quickstart" },
});

try {
  const result = await sandbox.exec(["python", "-c", "print('hello from porter')"]);
  console.log(result.stdout);
} finally {
  await sandbox.terminate();
  porter.close();
}
```

The SDK connects to the in-cluster Sandbox API automatically when this code runs as a Porter Application in the same cluster where sandboxes are enabled.

If you need to invoke sandboxes from outside that cluster, pass an API token to the SDK. You can create an API token from **Settings > API tokens** in the Porter Dashboard. Creating API tokens requires admin permissions.

Use sandbox names when you need to fetch, inspect, exec into, or terminate a sandbox later. Sandbox names must be unique within a cluster and currently cannot be reused, even after the sandbox is terminated.

## Fetch logs

Logs are returned as structured log lines:

```typescript theme={null}
import { Porter } from "porter-sandbox";

const porter = new Porter();
const sandbox = await porter.sandboxes.create({
  image: "python:3.12-slim",
  name: "typescript-logs-demo",
});

try {
  await sandbox.exec(["python", "-c", "print('log me')"]);

  const logs = await sandbox.logs({ limit: 100 });
  for (const line of logs) {
    console.log(`${line.timestamp} [${line.level}] ${line.line}`);
  }
} finally {
  await sandbox.terminate();
  porter.close();
}
```

## Get a sandbox by name

```typescript theme={null}
import { Porter } from "porter-sandbox";

const porter = new Porter();
const sandbox = await porter.sandboxes.get("typescript-quickstart");

console.log(sandbox.phase);
porter.close();
```

## List sandboxes

Use tags to find sandboxes created by a workflow:

```typescript theme={null}
import { Porter } from "porter-sandbox";

const porter = new Porter();

const sandboxes = await porter.sandboxes.list({
  tags: { workflow: "agent-run" },
});

for (const sandbox of sandboxes) {
  console.log(sandbox.phase);
}

porter.close();
```

## Concurrent sandboxes

All TypeScript Sandbox SDK methods are promise-based, so you can fan out with `Promise.all`:

```typescript theme={null}
const sandboxes = await Promise.all(
  Array.from({ length: 10 }, (_, index) =>
    porter.sandboxes.create({
      image: "python:3.12-slim",
      name: `batch-demo-${index}`,
      tags: { batch: "demo" },
    }),
  ),
);
```

## Next steps

* [TypeScript Sandbox SDK reference](/sandbox/sdk/typescript/reference)
* [TypeScript Sandbox SDK volumes](/sandbox/sdk/typescript/volumes)
* [TypeScript Sandbox SDK errors](/sandbox/sdk/typescript/errors)
* [Sandboxes getting started](/sandboxes/getting-started)
