sandbox
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCRITICAL: Always Use Correct @vercel/sandbox
Documentation
@vercel/sandbox重要提示: 务必使用正确的@vercel/sandbox
文档
@vercel/sandboxYour knowledge of may be outdated.
Follow these instructions before starting on any sandbox-related tasks:
@vercel/sandbox你所掌握的相关知识可能已过时。
在开始任何与沙箱相关的任务前,请遵循以下说明:
@vercel/sandboxOfficial Resources
官方资源
- Documentation: https://vercel.com/docs/vercel-sandbox
- Documentation (beta): https://vercel.com/docs/vercel-sandbox/concepts/persistent-sandboxes
- SDK Reference: https://vercel.com/docs/vercel-sandbox/sdk-reference
- CLI Reference: https://vercel.com/docs/vercel-sandbox/cli-reference
- GitHub: https://github.com/vercel/sandbox
- REST API: https://vercel.com/docs/rest-api/sandboxes
- REST API (Beta): https://vercel.com/docs/rest-api/sandboxes-v2-beta
- 文档: https://vercel.com/docs/vercel-sandbox
- 测试版文档: https://vercel.com/docs/vercel-sandbox/concepts/persistent-sandboxes
- SDK参考: https://vercel.com/docs/vercel-sandbox/sdk-reference
- CLI参考: https://vercel.com/docs/vercel-sandbox/cli-reference
- GitHub: https://github.com/vercel/sandbox
- REST API: https://vercel.com/docs/rest-api/sandboxes
- 测试版REST API: https://vercel.com/docs/rest-api/sandboxes-v2-beta
Quick Reference
快速参考
Essential imports:
typescript
// Core SDK
import { Sandbox, Snapshot, Command, CommandFinished } from "@vercel/sandbox";
import { APIError, StreamError } from "@vercel/sandbox";
// For advanced network policy with credential brokering
import type { NetworkPolicyRule, NetworkTransformer } from "@vercel/sandbox";
// For timeouts
import ms from "ms"; // e.g., ms("5m"), ms("1h")Available runtimes:
typescript
type RUNTIMES = "node24" | "node22" | "python3.13";必要导入:
typescript
// Core SDK
import { Sandbox, Snapshot, Command, CommandFinished } from "@vercel/sandbox";
import { APIError, StreamError } from "@vercel/sandbox";
// For advanced network policy with credential brokering
import type { NetworkPolicyRule, NetworkTransformer } from "@vercel/sandbox";
// For timeouts
import ms from "ms"; // e.g., ms("5m"), ms("1h")可用运行时:
typescript
type RUNTIMES = "node24" | "node22" | "python3.13";Creating Sandboxes
创建沙箱
Basic Creation
基础创建
typescript
import { Sandbox } from "@vercel/sandbox";
const sandbox = await Sandbox.create({
runtime: "node24",
resources: { vcpus: 4 }, // 2048 MB RAM per vCPU
ports: [3000], // Expose up to 15 ports
timeout: ms("10m"), // Default: 5 minutes
env: { NODE_ENV: "production" }, // Env vars inherited by all commands
});typescript
import { Sandbox } from "@vercel/sandbox";
const sandbox = await Sandbox.create({
runtime: "node24",
resources: { vcpus: 4 }, // 每个vCPU对应2048 MB内存
ports: [3000], // 最多暴露15个端口
timeout: ms("10m"), // 默认:5分钟
env: { NODE_ENV: "production" }, // 所有命令继承的环境变量
});With Git Source
基于Git源
typescript
const sandbox = await Sandbox.create({
source: {
type: "git",
url: "https://github.com/vercel/sandbox-example-next.git",
depth: 1, // Shallow clone (optional)
revision: "main", // Branch, tag, or commit (optional)
},
runtime: "node24",
ports: [3000],
});typescript
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
基于私有Git仓库
typescript
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!, // Use PAT for password
},
runtime: "node24",
});typescript
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!, // 使用PAT作为密码
},
runtime: "node24",
});From Tarball
基于压缩包
typescript
const sandbox = await Sandbox.create({
source: {
type: "tarball",
url: "https://example.com/project.tar.gz",
},
runtime: "node24",
ports: [3000],
});typescript
const sandbox = await Sandbox.create({
source: {
type: "tarball",
url: "https://example.com/project.tar.gz",
},
runtime: "node24",
ports: [3000],
});From Snapshot
基于快照
typescript
const sandbox = await Sandbox.create({
source: {
type: "snapshot",
snapshotId: "snap_abc123",
},
ports: [3000],
});typescript
const sandbox = await Sandbox.create({
source: {
type: "snapshot",
snapshotId: "snap_abc123",
},
ports: [3000],
});Auto-Dispose Pattern
自动销毁模式
Use for automatic cleanup:
await usingtypescript
async function runInSandbox() {
await using sandbox = await Sandbox.create();
// Sandbox automatically stopped when scope exits
await sandbox.runCommand("echo", ["Hello"]);
}使用实现自动清理:
await usingtypescript
async function runInSandbox() {
await using sandbox = await Sandbox.create();
// 沙箱会在作用域退出时自动停止
await sandbox.runCommand("echo", ["Hello"]);
}Running Commands
运行命令
Basic Command Execution
基础命令执行
typescript
const result = await sandbox.runCommand("npm", ["install"]);
if (result.exitCode !== 0) {
console.error("Install failed:", await result.stderr());
}typescript
const result = await sandbox.runCommand("npm", ["install"]);
if (result.exitCode !== 0) {
console.error("安装失败:", await result.stderr());
}With Options
带选项的命令
typescript
const result = await sandbox.runCommand({
cmd: "npm",
args: ["run", "build"],
cwd: "/vercel/sandbox/app",
env: { NODE_ENV: "production" },
sudo: false,
stdout: process.stdout, // Stream output
stderr: process.stderr,
});typescript
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)
分离命令(后台进程)
typescript
// Start dev server in background
const devServer = await sandbox.runCommand({
cmd: "npm",
args: ["run", "dev"],
detached: true, // Returns immediately
stdout: process.stdout,
});
// Later: wait for completion or kill
const finished = await devServer.wait();
// Supported signals: SIGHUP, SIGINT, SIGQUIT, SIGKILL, SIGTERM, SIGCONT, SIGSTOP (or numeric)
await devServer.kill("SIGTERM");typescript
// 在后台启动开发服务器
const devServer = await sandbox.runCommand({
cmd: "npm",
args: ["run", "dev"],
detached: true, // 立即返回
stdout: process.stdout,
});
// 后续:等待完成或终止
const finished = await devServer.wait();
// 支持的信号:SIGHUP, SIGINT, SIGQUIT, SIGKILL, SIGTERM, SIGCONT, SIGSTOP(或数字)
await devServer.kill("SIGTERM");Root Access
根权限
typescript
await sandbox.runCommand({
cmd: "dnf",
args: ["install", "-y", "golang"],
sudo: true, // Execute as root
});typescript
await sandbox.runCommand({
cmd: "dnf",
args: ["install", "-y", "golang"],
sudo: true, // 以root身份执行
});File Operations
文件操作
Write Files
写入文件
typescript
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'"),
},
]);typescript
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
读取文件
typescript
// Returns a Buffer object
const buffer = await sandbox.readFileToBuffer({
path: "/vercel/sandbox/output.txt",
});
// Returns a NodeJS.ReadableStream
const stream = await sandbox.readFile({
path: "/vercel/sandbox/large-file.bin",
});typescript
// 返回Buffer对象
const buffer = await sandbox.readFileToBuffer({
path: "/vercel/sandbox/output.txt",
});
// 返回NodeJS.ReadableStream
const stream = await sandbox.readFile({
path: "/vercel/sandbox/large-file.bin",
});Download Files
下载文件
typescript
const localPath = await sandbox.downloadFile(
{ path: "/vercel/sandbox/report.pdf" }, // source path on the sandbox
{ path: "./downloads/report.pdf" }, // destination path on the local machine
{ mkdirRecursive: true },
);typescript
const localPath = await sandbox.downloadFile(
{ path: "/vercel/sandbox/report.pdf" }, // 沙箱中的源路径
{ path: "./downloads/report.pdf" }, // 本地机器的目标路径
{ mkdirRecursive: true },
);Create Directories
创建目录
typescript
await sandbox.mkDir("/vercel/sandbox/my-app/src");typescript
await sandbox.mkDir("/vercel/sandbox/my-app/src");Network Policy
网络策略
Full Internet Access (Default)
完全互联网访问(默认)
typescript
const sandbox = await Sandbox.create({
networkPolicy: "allow-all",
});typescript
const sandbox = await Sandbox.create({
networkPolicy: "allow-all",
});No Network Access
禁止网络访问
typescript
const sandbox = await Sandbox.create({
networkPolicy: "deny-all",
});typescript
const sandbox = await Sandbox.create({
networkPolicy: "deny-all",
});Restricted Access (Simple Domain List)
受限访问(简单域名列表)
typescript
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"], // Takes precedence over allowed
},
},
});
// Update policy at runtime
await sandbox.updateNetworkPolicy({
allow: ["api.openai.com"],
});typescript
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
带凭证代理的受限访问
typescript
const sandbox = await Sandbox.create({
networkPolicy: {
allow: {
"ai-gateway.vercel.sh": [
{
transform: [
{
headers: { authorization: "Bearer ..." },
},
],
},
],
"*": [], // Allow all other domains without transforms
},
},
});typescript
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
创建快照
typescript
const sandbox = await Sandbox.create({ runtime: "node24" });
// Install dependencies
await sandbox.runCommand("npm", ["install"]);
// Create snapshot (stops the sandbox)
const snapshot = await sandbox.snapshot({
expiration: ms("14d"), // Default: 30 days, use 0 for no expiration
});
console.log("Snapshot ID:", snapshot.snapshotId);typescript
const sandbox = await Sandbox.create({ runtime: "node24" });
// 安装依赖
await sandbox.runCommand("npm", ["install"]);
// 创建快照(会停止沙箱)
const snapshot = await sandbox.snapshot({
expiration: ms("14d"), // 默认:30天,设为0表示永不过期
});
console.log("快照ID:", snapshot.snapshotId);List and Manage Snapshots
列出和管理快照
typescript
// List snapshots
const { snapshots, pagination } = await Snapshot.list();
// Get a specific snapshot
const snapshot = await Snapshot.get({ snapshotId: "snap_abc123" });
// Delete snapshot
await snapshot.delete();typescript
// 列出快照
const { snapshots, pagination } = await Snapshot.list();
// 获取特定快照
const snapshot = await Snapshot.get({ snapshotId: "snap_abc123" });
// 删除快照
await snapshot.delete();Exposed Ports
暴露端口
typescript
const sandbox = await Sandbox.create({
ports: [3000, 8080],
});
// Get public URL for a port
const url = sandbox.domain(3000);
// Returns: https://subdomain.vercel.run
// Open in browser
spawn("open", [url]);typescript
const sandbox = await Sandbox.create({
ports: [3000, 8080],
});
// 获取端口的公开URL
const url = sandbox.domain(3000);
// 返回:https://subdomain.vercel.run
// 在浏览器中打开
spawn("open", [url]);Timeout Management
超时管理
typescript
const sandbox = await Sandbox.create({
timeout: ms("10m"), // Initial timeout, default of 5 minutes
});
// Extend timeout by 5 more minutes
await sandbox.extendTimeout(ms("5m"));
// New total: 15 minutestypescript
const sandbox = await Sandbox.create({
timeout: ms("10m"), // 初始超时,默认5分钟
});
// 延长超时5分钟
await sandbox.extendTimeout(ms("5m"));
// 新总时长:15分钟Authentication
身份验证
Vercel OIDC Token (Recommended)
Vercel OIDC令牌(推荐)
bash
undefinedbash
undefinedPull development credentials
获取开发凭证
vercel link
vercel env pull
The SDK automatically uses `VERCEL_OIDC_TOKEN` from environment.vercel link
vercel env pull
SDK会自动使用环境变量中的`VERCEL_OIDC_TOKEN`。Access Token (Alternative)
访问令牌(替代方案)
typescript
const sandbox = await Sandbox.create({
teamId: process.env.VERCEL_TEAM_ID!,
projectId: process.env.VERCEL_PROJECT_ID!,
token: process.env.VERCEL_TOKEN!,
// ... other options
});typescript
const sandbox = await Sandbox.create({
teamId: process.env.VERCEL_TEAM_ID!,
projectId: process.env.VERCEL_PROJECT_ID!,
token: process.env.VERCEL_TOKEN!,
// ... 其他选项
});Error Handling
错误处理
typescript
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;
}typescript
import { APIError, StreamError } from "@vercel/sandbox";
try {
const sandbox = await Sandbox.create();
} catch (error) {
if (error instanceof APIError) {
console.error("API错误:", error.message, error.statusCode);
} else if (error instanceof StreamError) {
console.error("流错误:", error.message);
}
throw error;
}Cancellation with AbortSignal
使用AbortSignal取消操作
typescript
const controller = new AbortController();
// Cancel after 30 seconds
setTimeout(() => controller.abort(), 30000);
const sandbox = await Sandbox.create({
signal: controller.signal,
});
const result = await sandbox.runCommand({
cmd: "npm",
args: ["test"],
signal: controller.signal,
});typescript
const controller = new AbortController();
// 30秒后取消
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 | |
| Writable path | |
| 限制项 | 详情 |
|---|---|
| 最大vCPU数 | 8个vCPU(每个vCPU对应2048 MB内存) |
| 最大端口数 | 15个暴露端口 |
| 最大超时时间 | 5小时(专业版/企业版),45分钟(免费版) |
| 默认超时时间 | 5分钟 |
| 基础系统 | Amazon Linux 2023 |
| 用户上下文 | |
| 可写入路径 | |
System Packages
系统包
Pre-installed: , , , , , , , , .
gittargzipunzipcurlopensslprocpsfindutilswhichInstall additional packages with sudo:
typescript
await sandbox.runCommand({
cmd: "dnf",
args: ["install", "-y", "package-name"],
sudo: true,
});预安装包:, , , , , , , , 。
gittargzipunzipcurlopensslprocpsfindutilswhich使用sudo安装额外包:
typescript
await sandbox.runCommand({
cmd: "dnf",
args: ["install", "-y", "package-name"],
sudo: true,
});CLI Quick Reference
CLI快速参考
bash
undefinedbash
undefinedInstall CLI
安装CLI
pnpm i -g sandbox
pnpm i -g sandbox
Login / Logout
登录/登出
sandbox login
sandbox logout
sandbox login
sandbox logout
Create and connect
创建并连接
sandbox create --connect
sandbox create --connect
List sandboxes
列出沙箱
sandbox ls
sandbox ls
Execute command
执行命令
sandbox exec <sandbox-id> -- npm install
sandbox exec <sandbox-id> -- npm install
Run a command in a new sandbox (create + exec in one step)
在新沙箱中运行命令(一步完成创建+执行)
sandbox run -- node -e "console.log('hello')"
sandbox run -- node -e "console.log('hello')"
Start an interactive shell
启动交互式shell
sandbox connect <sandbox-id>
sandbox connect <sandbox-id>
Copy files
复制文件
sandbox cp local-file.txt <sandbox-id>:/vercel/sandbox/
sandbox cp local-file.txt <sandbox-id>:/vercel/sandbox/
Stop sandbox
停止沙箱
sandbox stop <sandbox-id>
sandbox stop <sandbox-id>
Snapshots
快照操作
sandbox snapshot <sandbox-id>
sandbox snapshots ls
sandbox snapshots get <snapshot-id>
sandbox snapshots rm <snapshot-id>
sandbox snapshot <sandbox-id>
sandbox snapshots ls
sandbox snapshots get <snapshot-id>
sandbox snapshots rm <snapshot-id>
Update network policy
更新网络策略
sandbox config network-policy <sandbox-id> --network-policy deny-all
undefinedsandbox config network-policy <sandbox-id> --network-policy deny-all
undefinedCommon Patterns
常见模式
Dev Server Pattern
开发服务器模式
typescript
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 });
// Wait for server to start
await new Promise((r) => setTimeout(r, 2000));
console.log("App running at:", sandbox.domain(3000));typescript
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("应用运行地址:", sandbox.domain(3000));Build and Test Pattern
构建与测试模式
typescript
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);typescript
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("安装失败");
const build = await sandbox.runCommand("npm", ["run", "build"]);
if (build.exitCode !== 0) throw new Error("构建失败");
const test = await sandbox.runCommand("npm", ["test"]);
process.exit(test.exitCode);Snapshot Warm Start Pattern
快照预热启动模式
typescript
// First time: create snapshot with dependencies installed
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;
}
// Subsequent runs: fast start from snapshot
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"]);
}typescript
// 首次执行:创建已安装依赖的快照
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
)
@vercel/sandbox@betasandbox@beta测试版:持久化沙箱(@vercel/sandbox@beta
和 sandbox@beta
)
@vercel/sandbox@betasandbox@betaThe beta introduces persistent, long-lived sandboxes with a new Session layer. Install with:
bash
pnpm i @vercel/sandbox@beta # SDK 2.0.0-beta.x
pnpm i -g sandbox@beta # CLI 3.0.0-beta.xIMPORTANT:
- 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), make it clear that sandboxes are by default persistent: they will automatically create snapshots to preserve the state.sandbox@2
测试版引入了带有新Session层的持久化、长期运行沙箱。安装方式:
bash
pnpm i @vercel/sandbox@beta # SDK 2.0.0-beta.x
pnpm i -g sandbox@beta # CLI 3.0.0-beta.x重要提示:
- 这是测试版,非稳定版本。请勿用于生产环境。
- 如果用户已安装过旧主版本(,
@vercel/sandbox@1,sandbox@1),需明确告知:沙箱默认是持久化的,它们会自动创建快照以保留状态。sandbox@2
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 , the default).
persistent: true - Migration: Old V1 sandboxes are backfilled with as their
sandboxId(e.g.,name), so the only change needed is usingsbx_123instead ofname.sandboxId
- Sandbox = 持久化的命名实体,可跨多个VM启动存活。
- Session = 沙箱内的运行VM实例。Session会自动创建/恢复,并通过ID标识。
- 沙箱通过名称(而非ID)标识。名称在每个项目中唯一。
- 当沙箱停止时,若设置(默认值),会自动创建快照,并在下次恢复时还原状态。
persistent: true - 迁移:旧版V1沙箱会自动以作为
sandboxId(例如name),因此只需将sbx_123替换为sandboxId即可。name
New Exports
新增导出
typescript
import { Session } from "@vercel/sandbox";typescript
import { Session } from "@vercel/sandbox";Migration from Stable (1.x
) to Beta (2.x
)
1.x2.x从稳定版(1.x)迁移到测试版(2.x)
Creating sandboxes — new name
and persistent
params
namepersistent创建沙箱 — 新增name
和persistent
参数
namepersistenttypescript
// Stable (1.x): anonymous, ephemeral sandboxes identified by sandboxId
const sandbox = await Sandbox.create({ runtime: "node24" });
console.log(sandbox.sandboxId);
// Beta (2.x): persistent sandboxes identified by name
const sandbox = await Sandbox.create({
name: "my-dev-env", // Optional, random if omitted. Unique per project.
runtime: "node24",
persistent: true, // Default: true. Auto-snapshots on shutdown and restores on resume.
snapshotExpiration: ms("7d"), // Optional. Default TTL for snapshots. Use 0 for no expiration.
});
console.log(sandbox.name);typescript
// 稳定版(1.x):匿名、临时沙箱,通过sandboxId标识
const sandbox = await Sandbox.create({ runtime: "node24" });
console.log(sandbox.sandboxId);
// 测试版(2.x):持久化沙箱,通过名称标识
const sandbox = await Sandbox.create({
name: "my-dev-env", // 可选,若省略则随机生成。每个项目中唯一。
runtime: "node24",
persistent: true, // 默认:true。关闭时自动快照,恢复时自动还原。
snapshotExpiration: ms("7d"), // 可选。快照默认过期时间。设为0表示永不过期。
});
console.log(sandbox.name);Retrieving sandboxes — name
replaces sandboxId
namesandboxId获取沙箱 — name
替代sandboxId
namesandboxIdtypescript
// Stable (1.x)
const sandbox = await Sandbox.get({ sandboxId: "sbx_abc123" });
// Beta (2.x) — retrieves by name.
const sandbox = await Sandbox.get({ name: "my-dev-env" });
// Pass `resume: true` to to automatically resume the sandbox. Otherwise, it will
// be resumed when the next command is run.
const sandbox = await Sandbox.get({ name: "my-dev-env", resume: false });typescript
// 稳定版(1.x)
const sandbox = await Sandbox.get({ sandboxId: "sbx_abc123" });
// 测试版(2.x)— 通过名称获取。
const sandbox = await Sandbox.get({ name: "my-dev-env" });
// 传入`resume: true`可自动恢复沙箱。否则,会在下次运行命令时自动恢复。
const sandbox = await Sandbox.get({ name: "my-dev-env", resume: false });Listing sandboxes — pagination and filtering changes
列出沙箱 — 分页和过滤方式变更
typescript
// Stable (1.x): used since/until for pagination
const {
json: { sandboxes },
} = await Sandbox.list({ since, until });
// Beta (2.x): cursor-based pagination, new filtering params
const { sandboxes, pagination } = await Sandbox.list({
cursor: pagination.next, // string token (replaces since/until)
namePrefix: "my-app-", // Filter by name prefix
sortBy: "name", // "createdAt" (default) or "name"
});typescript
// 稳定版(1.x):使用since/until进行分页
const {
json: { sandboxes },
} = await Sandbox.list({ since, until });
// 测试版(2.x):基于游标分页,新增过滤参数
const { sandboxes, pagination } = await Sandbox.list({
cursor: pagination.next, // 字符串令牌(替代since/until)
namePrefix: "my-app-", // 按名称前缀过滤
sortBy: "name", // "createdAt"(默认)或"name"
});Listing snapshots — new name
filter
name列出快照 — 新增name
过滤器
nametypescript
// Beta (2.x): filter snapshots by sandbox name
const { snapshots } = await Snapshot.list({
name: "my-dev-env", // Only snapshots belonging to this sandbox
});typescript
// 测试版(2.x):按沙箱名称过滤快照
const { snapshots } = await Snapshot.list({
name: "my-dev-env", // 仅显示属于该沙箱的快照
});Auto-resume for persistent sandboxes
持久化沙箱的自动恢复
If a sandbox created with is stopped, and you call
, , 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.
persistent: truerunCommandwriteFiles若使用创建的沙箱已停止,当你调用、或类似SDK方法并指定相同沙箱名称时,SDK会自动启动新Session并重试操作。无需手动恢复。
persistent: truerunCommandwriteFilesNew Session
class
Session新增Session
类
Sessiontypescript
// Access the current running VM session
const session = sandbox.currentSession();
console.log(session.sessionId);
console.log(session.status); // "pending" | "running" | "stopping" | "stopped" | ...typescript
// 获取当前运行的VM会话
const session = sandbox.currentSession();
console.log(session.sessionId);
console.log(session.status); // "pending" | "running" | "stopping" | "stopped" | ...New sandbox.update()
method (replaces updateNetworkPolicy
)
sandbox.update()updateNetworkPolicy新增sandbox.update()
方法(替代updateNetworkPolicy
)
sandbox.update()updateNetworkPolicytypescript
// Stable (1.x)
await sandbox.updateNetworkPolicy("deny-all");
// Beta (2.x) — updateNetworkPolicy still works but is deprecated
await sandbox.update({
networkPolicy: "deny-all",
persistent: false,
resources: { vcpus: 4 },
timeout: ms("30m"),
snapshotExpiration: ms("14d"), // Update default snapshot TTL. Use 0 for no expiration.
});typescript
// 稳定版(1.x)
await sandbox.updateNetworkPolicy("deny-all");
// 测试版(2.x)— updateNetworkPolicy仍可用但已废弃
await sandbox.update({
networkPolicy: "deny-all",
persistent: false,
resources: { vcpus: 4 },
timeout: ms("30m"),
snapshotExpiration: ms("14d"), // 更新快照默认过期时间。设为0表示永不过期。
});New sandbox.delete()
method
sandbox.delete()新增sandbox.delete()
方法
sandbox.delete()typescript
// Permanently remove a sandbox and all its snapshots
await sandbox.delete();typescript
// 永久删除沙箱及其所有快照
await sandbox.delete();New sandbox.listSessions()
and sandbox.listSnapshots()
sandbox.listSessions()sandbox.listSnapshots()新增sandbox.listSessions()
和sandbox.listSnapshots()
sandbox.listSessions()sandbox.listSnapshots()typescript
// List all VM sessions for this sandbox
const sessions = await sandbox.listSessions();
// List snapshots belonging to this sandbox
const snapshots = await sandbox.listSnapshots();typescript
// 列出该沙箱的所有VM会话
const sessions = await sandbox.listSessions();
// 列出属于该沙箱的快照
const snapshots = await sandbox.listSnapshots();CLI Changes (3.0.0-beta)
CLI变更(3.0.0-beta)
Key differences from the stable CLI:
- All commands now use sandbox name instead of sandbox ID.
- /
sandbox rmpermanently deletes the sandbox.sandbox remove - New: command to manage sessions.
sandbox sessions - New: to set a sandbox name.
sandbox create --name <name> - New: to set default snapshot TTL.
sandbox create --snapshot-expiration <duration|none> - New: to disable state persistence.
sandbox create --non-persistent - New: to stop the session when the command exits.
sandbox run --stop - New: resumes from an existing sandbox if it exists.
sandbox run --name <name> - Breaking: now deletes the sandbox (previously just stopped it).
sandbox run --rm - New: to filter snapshots by sandbox name.
sandbox snapshots list --name <name> - New: to view sandbox configuration.
sandbox config list <name> - New: to update vCPUs.
sandbox config vcpus <name> <count> - New: to update timeout.
sandbox config timeout <name> <duration> - New: to toggle persistence.
sandbox config persistent <name> <true|false> - New: to set default snapshot TTL.
sandbox config snapshot-expiration <name> <duration|none> - now uses
sandbox cpinstead of<sandbox_name>:path.<sandbox_id>:path - supports
sandbox lsand--name-prefixfiltering.--sort-by
与稳定版CLI的主要差异:
- 所有命令现在使用沙箱名称而非沙箱ID。
- /
sandbox rm会永久删除沙箱。sandbox remove - 新增:命令用于管理会话。
sandbox sessions - 新增:设置沙箱名称。
sandbox create --name <name> - 新增:设置快照默认过期时间。
sandbox create --snapshot-expiration <duration|none> - 新增:禁用状态持久化。
sandbox create --non-persistent - 新增:在命令退出时停止会话。
sandbox run --stop - 新增:若沙箱已存在则从其恢复。
sandbox run --name <name> - 破坏性变更:现在会删除沙箱(之前仅停止沙箱)。
sandbox run --rm - 新增:按沙箱名称过滤快照。
sandbox snapshots list --name <name> - 新增:查看沙箱配置。
sandbox config list <name> - 新增:更新vCPU数量。
sandbox config vcpus <name> <count> - 新增:更新超时时间。
sandbox config timeout <name> <duration> - 新增:切换持久化状态。
sandbox config persistent <name> <true|false> - 新增:设置快照默认过期时间。
sandbox config snapshot-expiration <name> <duration|none> - 现在使用
sandbox cp而非<sandbox_name>:path。<sandbox_id>:path - 支持
sandbox ls和--name-prefix过滤。--sort-by