| name | sandbox |
| description | Creates isolated Linux MicroVMs using Vercel Sandbox SDK. Use when building code execution environments, running untrusted code, spinning up dev servers, testing in isolation, or when the user mentions "sandbox", "microvm", "isolated execution", or "@vercel/sandbox". |
| metadata | {"author":"Vercel Inc.","version":"1.0"} |
CRITICAL: Always Use Correct @vercel/sandbox Documentation
Your knowledge of @vercel/sandbox may be outdated.
Follow these instructions before starting on any sandbox-related tasks:
Official Resources
Quick Reference
Essential imports:
import { Sandbox, Snapshot, Command, CommandFinished } from '@vercel/sandbox';
import { APIError, StreamError } from '@vercel/sandbox';
import type { NetworkPolicyRule, NetworkTransformer } from '@vercel/sandbox';
import ms from 'ms';
Available runtimes:
type RUNTIMES = 'node24' | 'node22' | 'python3.13';
Creating Sandboxes
Basic Creation
import { Sandbox } from '@vercel/sandbox';
const sandbox = await Sandbox.create({
runtime: 'node24',
resources: { vcpus: 4 },
ports: [3000],
timeout: ms('10m'),
env: { NODE_ENV: 'production' }
});
With Git Source
const sandbox = await Sandbox.create({
source: {
type: 'git',
url: 'https://github.com/vercel/sandbox-example-next.git',
depth: 1,
revision: 'main'
},
runtime: 'node24',
ports: [3000]
});
With Private Git Repository
const sandbox = await Sandbox.create({
source: {
type: 'git',
url: 'https://github.com/org/private-repo.git',
username: process.env.GIT_USERNAME!,
password: process.env.GIT_TOKEN!
},
runtime: 'node24'
});
From Tarball
const sandbox = await Sandbox.create({
source: {
type: 'tarball',
url: 'https://example.com/project.tar.gz'
},
runtime: 'node24',
ports: [3000]
});
From Snapshot
const sandbox = await Sandbox.create({
source: {
type: 'snapshot',
snapshotId: 'snap_abc123'
},
ports: [3000]
});
Auto-Dispose Pattern
Use await using for automatic cleanup:
async function runInSandbox() {
await using sandbox = await Sandbox.create();
await sandbox.runCommand('echo', ['Hello']);
}
Running Commands
Basic Command Execution
const result = await sandbox.runCommand('npm', ['install']);
if (result.exitCode !== 0) {
console.error('Install failed:', await result.stderr());
}
With Options
const result = await sandbox.runCommand({
cmd: 'npm',
args: ['run', 'build'],
cwd: '/vercel/sandbox/app',
env: { NODE_ENV: 'production' },
sudo: false,
stdout: process.stdout,
stderr: process.stderr
});
Detached Commands (Background Processes)
const devServer = await sandbox.runCommand({
cmd: 'npm',
args: ['run', 'dev'],
detached: true,
stdout: process.stdout
});
const finished = await devServer.wait();
await devServer.kill('SIGTERM');
Root Access
await sandbox.runCommand({
cmd: 'dnf',
args: ['install', '-y', 'golang'],
sudo: true
});
File Operations
Write Files
await sandbox.writeFiles([
{
path: '/vercel/sandbox/config.json',
content: Buffer.from(JSON.stringify({ key: 'value' }))
},
{
path: '/vercel/sandbox/script.sh',
content: Buffer.from("#!/bin/bash\necho 'Hello'")
}
]);
Read Files
const buffer = await sandbox.readFileToBuffer({
path: '/vercel/sandbox/output.txt'
});
const stream = await sandbox.readFile({
path: '/vercel/sandbox/large-file.bin'
});
Download Files
const localPath = await sandbox.downloadFile(
{ path: '/vercel/sandbox/report.pdf' },
{ path: './downloads/report.pdf' },
{ mkdirRecursive: true }
);
Create Directories
await sandbox.mkDir('/vercel/sandbox/my-app/src');
Network Policy
Full Internet Access (Default)
const sandbox = await Sandbox.create({
networkPolicy: 'allow-all'
});
No Network Access
const sandbox = await Sandbox.create({
networkPolicy: 'deny-all'
});
Restricted Access (Simple Domain List)
const sandbox = await Sandbox.create({
networkPolicy: {
allow: ['*.npmjs.org', 'github.com', 'registry.yarnpkg.com'],
subnets: {
allow: ['10.0.0.0/8'],
deny: ['10.1.0.0/16']
}
}
});
await sandbox.updateNetworkPolicy({
allow: ['api.openai.com']
});
Restricted Access with Credential Brokering
const sandbox = await Sandbox.create({
networkPolicy: {
allow: {
'ai-gateway.vercel.sh': [
{
transform: [
{
headers: { authorization: 'Bearer ...' }
}
]
}
],
'*': []
}
}
});
Snapshots
Snapshots save the entire sandbox filesystem to be reused later on, for any number of sandboxes.
Create a Snapshot
const sandbox = await Sandbox.create({ runtime: 'node24' });
await sandbox.runCommand('npm', ['install']);
const snapshot = await sandbox.snapshot({
expiration: ms('14d')
});
console.log('Snapshot ID:', snapshot.snapshotId);
List and Manage Snapshots
const { snapshots, pagination } = await Snapshot.list();
const snapshot = await Snapshot.get({ snapshotId: 'snap_abc123' });
await snapshot.delete();
Exposed Ports
const sandbox = await Sandbox.create({
ports: [3000, 8080]
});
const url = sandbox.domain(3000);
spawn('open', [url]);
Timeout Management
const sandbox = await Sandbox.create({
timeout: ms('10m')
});
await sandbox.extendTimeout(ms('5m'));
Authentication
Vercel OIDC Token (Recommended)
vercel link
vercel env pull
The SDK automatically uses VERCEL_OIDC_TOKEN from environment.
Access Token (Alternative)
const sandbox = await Sandbox.create({
teamId: process.env.VERCEL_TEAM_ID!,
projectId: process.env.VERCEL_PROJECT_ID!,
token: process.env.VERCEL_TOKEN!
});
Error Handling
import { APIError, StreamError } from '@vercel/sandbox';
try {
const sandbox = await Sandbox.create();
} catch (error) {
if (error instanceof APIError) {
console.error('API Error:', error.message, error.statusCode);
} else if (error instanceof StreamError) {
console.error('Stream Error:', error.message);
}
throw error;
}
Cancellation with AbortSignal
const controller = new AbortController();
setTimeout(() => controller.abort(), 30000);
const sandbox = await Sandbox.create({
signal: controller.signal
});
const result = await sandbox.runCommand({
cmd: 'npm',
args: ['test'],
signal: controller.signal
});
Limitations
| Limitation | Details |
|---|
| Max vCPUs | 8 vCPUs (2048 MB RAM per vCPU) |
| Max ports | 15 exposed ports |
| Max timeout | 5 hours (Pro/Enterprise), 45 minutes (Hobby) |
| Default timeout | 5 minutes |
| Base system | Amazon Linux 2023 |
| User context | vercel-sandbox user |
| Writable path | /vercel/sandbox |
System Packages
Pre-installed: git, tar, gzip, unzip, curl, openssl, procps, findutils, which.
Install additional packages with sudo:
await sandbox.runCommand({
cmd: 'dnf',
args: ['install', '-y', 'package-name'],
sudo: true
});
CLI Quick Reference
pnpm i -g sandbox
sandbox login
sandbox logout
sandbox create --connect
sandbox ls
sandbox exec <sandbox-id> -- npm install
sandbox run -- node -e "console.log('hello')"
sandbox connect <sandbox-id>
sandbox cp local-file.txt <sandbox-id>:/vercel/sandbox/
sandbox stop <sandbox-id>
sandbox snapshot <sandbox-id>
sandbox snapshots ls
sandbox snapshots get <snapshot-id>
sandbox snapshots rm <snapshot-id>
sandbox config network-policy <sandbox-id> --network-policy deny-all
Common Patterns
Dev Server Pattern
const sandbox = await Sandbox.create({
source: { type: 'git', url: 'https://github.com/org/repo.git' },
ports: [3000],
timeout: ms('30m')
});
await sandbox.runCommand('npm', ['install']);
await sandbox.runCommand({ cmd: 'npm', args: ['run', 'dev'], detached: true });
await new Promise((r) => setTimeout(r, 2000));
console.log('App running at:', sandbox.domain(3000));
Build and Test Pattern
await using sandbox = await Sandbox.create({
source: { type: 'git', url: repoUrl }
});
const install = await sandbox.runCommand('npm', ['ci']);
if (install.exitCode !== 0) throw new Error('Install failed');
const build = await sandbox.runCommand('npm', ['run', 'build']);
if (build.exitCode !== 0) throw new Error('Build failed');
const test = await sandbox.runCommand('npm', ['test']);
process.exit(test.exitCode);
Snapshot Warm Start Pattern
async function createBaseSnapshot() {
const sandbox = await Sandbox.create({ runtime: 'node24' });
await sandbox.runCommand('npm', ['install', '-g', 'typescript', 'tsx']);
const snapshot = await sandbox.snapshot();
return snapshot.snapshotId;
}
async function runFromSnapshot(snapshotId: string, code: string) {
await using sandbox = await Sandbox.create({
source: { type: 'snapshot', snapshotId }
});
await sandbox.writeFiles([{ path: '/vercel/sandbox/index.ts', content: Buffer.from(code) }]);
return sandbox.runCommand('tsx', ['index.ts']);
}
Beta: Persistent Sandboxes (@vercel/sandbox@beta and sandbox@beta)
The beta introduces persistent, long-lived sandboxes with a new Session layer. Install with:
pnpm i @vercel/sandbox@beta
pnpm i -g sandbox@beta
IMPORTANT:
- This is a beta, not a stable version. Do not use for production.
- If the user had installed a previous major version (
@vercel/sandbox@1, sandbox@1, sandbox@2), make it clear that sandboxes are by default persistent: they will automatically create snapshots to preserve the state.
Key Concepts
- Sandbox = a persistent, named entity that survives across multiple VM boots.
- Session = a running VM instance within a sandbox. Sessions are created/resumed automatically and are identified by ID.
- Sandboxes are identified by name (not ID). Names are unique per project.
- When a sandbox stops, it will automatically snapshot and restore the state on the next resume (with
persistent: true, the default).
- Migration: Old V1 sandboxes are backfilled with
sandboxId as their name (e.g., sbx_123), so the only change needed is using name instead of sandboxId.
New Exports
import { Session } from '@vercel/sandbox';
Migration from Stable (1.x) to Beta (2.x)
Creating sandboxes — new name and persistent params
const sandbox = await Sandbox.create({ runtime: 'node24' });
console.log(sandbox.sandboxId);
const sandbox = await Sandbox.create({
name: 'my-dev-env',
runtime: 'node24',
persistent: true
});
console.log(sandbox.name);
Retrieving sandboxes — name replaces sandboxId
const sandbox = await Sandbox.get({ sandboxId: 'sbx_abc123' });
const sandbox = await Sandbox.get({ name: 'my-dev-env' });
const sandbox = await Sandbox.get({ name: 'my-dev-env', resume: false });
Listing sandboxes — pagination and filtering changes
const {
json: { sandboxes }
} = await Sandbox.list({ since, until });
const { sandboxes, pagination } = await Sandbox.list({
cursor: pagination.next,
namePrefix: 'my-app-',
sortBy: 'name'
});
Listing snapshots — new name filter
const { snapshots } = await Snapshot.list({
name: 'my-dev-env'
});
Auto-resume for persistent sandboxes
If a sandbox created with persistent: true is stopped, and you call
runCommand, writeFiles, or similar SDK methods with the same sandbox name, the SDK automatically
starts a new session and retries the operation. You do not need to resume
manually.
New Session class
const session = sandbox.currentSession();
console.log(session.sessionId);
console.log(session.status);
New sandbox.update() method (replaces updateNetworkPolicy)
await sandbox.updateNetworkPolicy('deny-all');
await sandbox.update({
networkPolicy: 'deny-all',
persistent: false,
resources: { vcpus: 4 },
timeout: ms('30m')
});
New sandbox.delete() method
await sandbox.delete();
New sandbox.listSessions() and sandbox.listSnapshots()
const sessions = await sandbox.listSessions();
const snapshots = await sandbox.listSnapshots();
CLI Changes (3.0.0-beta)
Key differences from the stable CLI:
- All commands now use sandbox name instead of sandbox ID.
sandbox rm / sandbox remove permanently deletes the sandbox.
- New:
sandbox sessions command to manage sessions.
- New:
sandbox create --name <name> to set a sandbox name.
- New:
sandbox create --non-persistent to disable state persistence.
- New:
sandbox run --stop to stop the session when the command exits.
- New:
sandbox run --name <name> resumes from an existing sandbox if it exists.
- Breaking:
sandbox run --rm now deletes the sandbox (previously just stopped it).
- New:
sandbox snapshots list --name <name> to filter snapshots by sandbox name.
- New:
sandbox config list <name> to view sandbox configuration.
- New:
sandbox config vcpus <name> <count> to update vCPUs.
- New:
sandbox config timeout <name> <duration> to update timeout.
- New:
sandbox config persistent <name> <true|false> to toggle persistence.
sandbox cp now uses <sandbox_name>:path instead of <sandbox_id>:path.
sandbox ls supports --name-prefix and --sort-by filtering.