Skip to main content
The TypeScript Sandbox SDK is published as porter-sandbox. Use it from application code running in your sandbox-enabled Porter cluster.
Sandboxes are in a private beta. Please reach out to us at support@porter.run or over Slack if you are interested in joining.

Install

Add the SDK to your application:
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:
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, set PORTER_SANDBOX_API_KEY to a Porter API token and PORTER_CLUSTER_ID to the target cluster. The SDK reads the project from the token and builds the external Porter API URL automatically; see calling from outside the cluster for details. 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:
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

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:
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:
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