JS SDK Reference
Use the Edgenivo Sandbox JavaScript SDK to create isolated Linux microVMs on demand. Run untrusted code, test full Linux workflows, and manage files, ports, snapshots, drives, sessions, and network policy from Node.js applications.
Install the SDK:
pnpm i @vercel/sandboxyarn add @vercel/sandboxnpm i @vercel/sandboxbun add @vercel/sandboxAfter installation, link your project and pull environment variables with vercel link and vercel env pull so the SDK can read a Edgenivo OpenID Connect (OIDC) token.
| Class | What it does | Example |
|---|---|---|
Sandbox | Creates and manages isolated microVM environments | const sandbox = await Sandbox.create() |
SandboxUser | Runs commands and file operations as a Linux user | const user = await sandbox.createUser('alice') |
Session | Represents a single running VM inside a sandbox | const session = sandbox.currentSession() |
FileSystem | Provides a node:fs/promises-compatible API | await sandbox.fs.readFile('/tmp/a.txt') |
Command | Handles running commands inside the sandbox | const cmd = await sandbox.runCommand('ls') |
CommandFinished | Contains the result after a command completes | Access cmd.exitCode and cmd.stdout() |
NetworkPolicy | Defines firewall rules for sandbox traffic | Sandbox.create({ networkPolicy: 'deny-all' }) |
Snapshot | Represents a saved sandbox state for fast restarts | const snapshot = await sandbox.snapshot() |
Drive | Represents persistent storage mounted to sandboxes | const drive = await Drive.getOrCreate() |
// 1. Create a sandbox (persistent by default)
const sandbox = await Sandbox.create({ name: 'my-sandbox' });
// 2. Run a command - it waits for completion and returns the result
const result = await sandbox.runCommand('node', ['--version']);
// 3. Check the result
console.log(result.exitCode); // 0
console.log(await result.stdout()); // v22.x.x
// 4. Later, retrieve the same sandbox by name
const same = await Sandbox.get({ name: 'my-sandbox' });The Sandbox class gives you full control over isolated Linux microVMs. Use it to create new sandboxes, retrieve existing ones, stream command output, snapshot the filesystem, and shut sessions down once your workflow is complete.
Sandboxes are persistent by default: when a sandbox stops, the SDK snapshots its filesystem and restores it on the next resume. See Persistent sandboxes for the full lifecycle model.
The name accessor returns the sandbox's unique name within the project. Use this string with Sandbox.get() to retrieve the sandbox in a later process. If you didn't pass a name to Sandbox.create(), one is generated for you.
Returns: string.
console.log(sandbox.name);Whether the sandbox automatically snapshots its filesystem on stop. Defaults to true for sandboxes created with Sandbox.create().
Returns: boolean.
console.log(sandbox.persistent);The status accessor reads cached metadata for the current session. Repeated property access doesn't poll the API. Retrieve a fresh handle with Sandbox.get({ name, resume: false }) to observe external changes without resuming the sandbox. A status check doesn't coordinate concurrent lifecycle operations; finish stop() or snapshot() before submitting more commands.
Returns: "pending" | "running" | "stopping" | "stopped" | "failed" | "aborted" | "snapshotting".
const fresh = await Sandbox.get({ name: sandbox.name, resume: false });
console.log(fresh.status);timeout is the sandbox's saved default session timeout, in milliseconds, when available. Change it with sandbox.update({ timeout }). Calling sandbox.extendTimeout() adds to the live session's deadline without changing this saved value. To read the deadline, use expiresAt.
Returns: number | undefined.
console.log(sandbox.timeout);expiresAt returns the time when the current session will stop automatically. It works with sandbox.extendTimeout() and moves forward when you extend the timeout. For milliseconds remaining, subtract the current time.
Returns: Date | undefined.
const msRemaining = sandbox.expiresAt
? sandbox.expiresAt.getTime() - Date.now()
: undefined;Key-value tags associated with the sandbox. See Tags.
Returns: Record<string, string> | undefined.
console.log(sandbox.tags);vcpus returns the number of allocated virtual CPUs. memory returns the allocated memory in MB (2048 MB per vCPU).
Returns: number | undefined.
console.log(sandbox.vcpus, sandbox.memory);Deprecated: use image for image-based sandboxes.
The runtime image used by the sandbox (for example, "node24").
Returns: string | undefined.
console.log(sandbox.runtime);The image used by the sandbox (for example, "vercel/sandbox/universal").
Returns: string | undefined.
console.log(sandbox.image);The region where the sandbox runs. Set with the region parameter of Sandbox.create(). When no region was passed, this is the project's default sandbox region, or iad1 if the project doesn't set one.
Returns: string.
console.log(sandbox.region);The additional regions this sandbox can fail over to. Returns an empty array when the sandbox has no failover regions.
Returns: string[].
console.log(sandbox.failoverRegions);The ID of the Secure Compute network assigned to this sandbox. Returns undefined when no network is assigned. An updated ID reflects the saved configuration. Once updated, a running session uses the new network after it stops and resumes.
Returns: string | undefined.
console.log(sandbox.networkId);Timestamps for when the sandbox was created and last updated.
Returns: Date.
console.log(sandbox.createdAt, sandbox.updatedAt);The ID of the snapshot the sandbox would resume from. Updated automatically when a persistent sandbox stops.
Returns: string | undefined.
console.log(sandbox.currentSnapshotId);Default expiration (in milliseconds) applied to snapshots automatically created for this sandbox. 0 means no expiration. If undefined, snapshots expire after 30 days (2,592,000,000 ms).
Returns: number | undefined.
console.log(sandbox.snapshotExpiration);Retention policy that keeps only the N most recent snapshots of this sandbox. A new snapshot is created whenever a persistent session stops or when you call sandbox.snapshot().
When a new snapshot brings the total above count for a given named sandbox, the oldest snapshots are no longer kept.
The deleteEvicted field controls what happens to them: delete them immediately, or leave them to expire on their own.
Returns: { count: number; expiration?: number; deleteEvicted?: boolean } | undefined. Returns undefined when no retention policy is set.
The policy object has the following fields:
| Field | Type | Required | Details |
|---|---|---|---|
count | number | Yes | Number of most recent snapshots to keep. Must be an integer from 1 to 10. When a new snapshot brings the total above count, the oldest snapshots are no longer kept. |
expiration | number | No | Expiration in milliseconds applied to the kept snapshots. Use 0 for no expiration. Falls back to snapshotExpiration when omitted. |
deleteEvicted | boolean | No | What happens to a snapshot once it is no longer among the count most recent. When true (the default), the snapshot is deleted immediately. When false, it is not deleted and remains until its existing expiration. |
console.log(sandbox.keepLastSnapshots);The amount of CPU used by the current session, in milliseconds. Only populated after the VM stops. Use this to track billable CPU for the latest session.
Returns: number | undefined.
console.log(sandbox.activeCpuUsageMs);The amount of network data used by the current session, in bytes. Only populated after the VM stops.
Returns: { ingress: number; egress: number } | undefined.
console.log(sandbox.networkTransfer);Cumulative usage across every session this sandbox has run. Use these for long-running, persistent sandboxes where the most recent session does not represent total usage. Network ingress and egress are usage metrics, not billing totals. See Pricing and Limits to understand which traffic is billable.
Returns: number | undefined.
console.log(sandbox.totalDurationMs, sandbox.totalActiveCpuDurationMs);
console.log(sandbox.totalIngressBytes, sandbox.totalEgressBytes);The mounts accessor returns the drives mounted on the sandbox, keyed by mount path.
Returns: SandboxMounts.
console.log(sandbox.mounts);Use Sandbox.list() to enumerate sandboxes for a project, with optional filters and cursor-based pagination. The returned value is async-iterable: iterate it directly to auto-paginate through every page, iterate result.pages() to walk page by page, or call result.toArray() to collect everything.
Omit token, teamId, and projectId to use OIDC or local development authentication. To use an access token, pass all three fields together. projectId alone does not override the OIDC project.
SandboxMetaData items are plain API metadata records, not Sandbox instances. Records identify sandboxes by name and have no instance methods. Timestamps such as createdAt are numbers. Retrieve a handle with Sandbox.get({ name: record.name }).
Returns: Promise<Paginated<{ sandboxes: SandboxMetaData[]; pagination: Pagination; }>>.
| Parameter | Type | Required | Details |
|---|---|---|---|
namePrefix | string | No | Filter sandboxes whose name begins with this prefix. Requires sortBy: "name". |
tags | Record<string, string> | No | Filter by a single tag. |
sortBy | "createdAt" | "name" | "statusUpdatedAt" | No | Sort field. Defaults to "createdAt". |
sortOrder | "asc" | "desc" | No | Sort direction. Defaults to "desc". |
limit | number | No | Maximum number of sandboxes per page. |
cursor | string | No | Pagination cursor returned by the previous page. |
token | string | No | Access token. Requires teamId and projectId when supplied. |
teamId | string | No | Team ID. Requires token and projectId when supplied. |
projectId | string | No | Project to list. Requires token and teamId when supplied. |
signal | AbortSignal | No | Cancel the request. |
const result = await Sandbox.list({
namePrefix: 'ci-',
sortBy: 'name',
tags: { env: 'staging' },
});
// Per-item iteration auto-paginates
for await (const sandbox of result) {
console.log(sandbox.name);
}To select a project with an access token, pass the complete credential set:
const result = await Sandbox.list({
token: 'your_access_token_here',
teamId: 'your_team_id_here',
projectId: 'your_project_id_here',
});
for await (const record of result) {
const sandbox = await Sandbox.get({
name: record.name,
token: 'your_access_token_here',
teamId: 'your_team_id_here',
projectId: 'your_project_id_here',
});
console.log(sandbox.name);
}Sandbox.create() launches a new microVM with your chosen image, source, and resource settings. Defaults to an empty workspace when no source is provided. Pass source.depth when cloning large repositories to shorten setup time.
The promise resolves when the sandbox is ready to run commands and access files. Creation time includes startup and, when using a snapshot, the wait to restore it. Restoring a snapshot that isn't cached can take longer.
To compare end-to-end performance, measure from the start of creation through completion of the same first command or file operation.
Sandboxes are persistent by default: when the sandbox stops, the filesystem is automatically snapshotted and restored on the next resume. Pass persistent: false to opt out.
Returns: Promise<Sandbox>.
| Parameter | Type | Required | Details |
|---|---|---|---|
name | string | No | Unique sandbox name within the project. A random name is generated if omitted. Cannot be changed after creation. |
source | git | No | Clone a Git repository. url: string username: string password: string depth?: number revision?: string |
source | tarball | No | Mount a tarball. url: string |
source | snapshot | No | Create from a snapshot. snapshotId: string |
resources.vcpus | number | No | Number of vCPUs (2048 MB RAM per vCPU). Defaults to 2. |
runtime | string | No | Deprecated: use image for image-based sandboxes. Runtime image such as "node26", "node24", "node22", or "python3.13". |
image | string | No | VCR image reference, either a Edgenivo Managed Image or custom image. Defaults to "vercel/sandbox/universal". |
ports | number[] | No | Ports to expose for sandbox.domain(). Up to 15. |
timeout | number | No | Session timeout in milliseconds. Defaults to 5 minutes. |
region | string | No | Region to create the sandbox in. Defaults to the project's default sandbox region, or iad1. |
failoverRegions | string[] | No | Additional regions the sandbox can fall back to when the main region is unavailable. Must not include the main region. Available on Pro and Enterprise plans, excluding Pro trials. |
networkPolicy | NetworkPolicy | No | Firewall rules for sandbox egress traffic. Defaults to "allow-all". |
networkId | string | No | Secure Compute network ID to use from the first session. |
env | Record<string, string> | No | Default environment variables for commands run in this sandbox. Per-command runCommand({ env }) values override these defaults. |
mounts | SandboxMounts | No | Drives to attach to the sandbox, keyed by absolute mount path. Pass a Drive for read-write access or drive.snapshot() for a point-in-time, read-only snapshot. |
tags | Record<string, string> | No | Up to five key-value tags. |
persistent | boolean | No | Auto-snapshot the filesystem on stop and restore on resume. Defaults to true. |
snapshotExpiration | number | No | Default snapshot TTL in milliseconds. Defaults to 30 days (2,592,000,000 ms). Use 0 for no expiration. |
keepLastSnapshots | object | No | Retention policy that keeps only the N most recent snapshots. { count: 1-10, expiration?: number, deleteEvicted?: boolean }. See keepLastSnapshots for field details. |
onResume | (sandbox) => Promise<void> | No | Fires whenever a session resumes, including after auto-resume. Use to restart background services or rehydrate caches. |
signal | AbortSignal | No | Cancel sandbox creation. |
For VCR repository setup and push commands, see Getting Started with Edgenivo Container Registry. For how custom images work in Sandbox, see Images.
const sandbox = await Sandbox.create({
name: 'my-sandbox',
image: 'vercel/sandbox/node:26',
networkPolicy: 'deny-all',
env: { NODE_ENV: 'production' },
tags: { env: 'staging' },
snapshotExpiration: 7 * 24 * 60 * 60 * 1000, // 7 days
});Sandbox.get() retrieves an existing sandbox by name without resuming it by default (resume: false). A stopped persistent sandbox automatically resumes on the first SDK call that needs a running session, such as runCommand. Pass resume: true to resume it before get resolves.
Returns: Promise<Sandbox>.
| Parameter | Type | Required | Details |
|---|---|---|---|
name | string | Yes | Sandbox name to retrieve. |
resume | boolean | No | Whether to resume the sandbox before get resolves. Defaults to false. A stopped sandbox still resumes automatically on the first SDK call that needs a running session. |
onResume | (sandbox) => Promise<void> | No | Fires whenever a session resumes (including after auto-resume). |
signal | AbortSignal | No | Cancel the request. |
const sandbox = await Sandbox.get({ name: 'my-sandbox' });Sandbox.getOrCreate() is the recommended pattern for long-lived sandboxes: it retrieves the sandbox if it exists, or creates it if it doesn't. By default (resume: false), an existing sandbox is retrieved without resuming it. A stopped persistent sandbox resumes on the first SDK call that needs a running session, or immediately when you pass resume: true. Use onCreate for initial setup and onResume for setup on later session starts. Creation calls onCreate only, so start services in both callbacks when they must run in every session.
Creation parameters (such as keepLastSnapshots or snapshotExpiration) apply only when getOrCreate creates the sandbox. If a sandbox with the same name already exists, getOrCreate returns it with its existing configuration and ignores the creation parameters you pass. To change the configuration of an existing sandbox, call sandbox.update().
Returns: Promise<Sandbox>.
| Parameter | Type | Required | Details |
|---|---|---|---|
name | string | No | Sandbox name. If omitted, behaves like Sandbox.create (always creates, onCreate always fires). |
resume | boolean | No | Whether to resume the sandbox immediately when an existing one is retrieved. Defaults to false. When true, the sandbox is resumed before getOrCreate resolves, and onResume is awaited before it resolves. |
onCreate | (sandbox) => Promise<void> | No | Runs once when the sandbox is freshly created. Awaited before getOrCreate resolves. |
onResume | (sandbox) => Promise<void> | No | Runs every time the session resumes (including after auto-resume). By default, getOrCreate retrieves the sandbox but does not resume it, so onResume is not awaited before it resolves; the session resumes on the first SDK call (such as runCommand), and onResume runs at that point. Pass resume: true to resume immediately and have onResume awaited before getOrCreate resolves. |
| ... | all Sandbox.create params | No | Any creation parameter is accepted and used only when the sandbox is created. Ignored when an existing sandbox is retrieved. |
Behavior:
- If a sandbox with that
nameexists,getOrCreateretrieves it without resuming it by default. The sandbox resumes on the first SDK call (such asrunCommand), andonResumefires at that point, not beforegetOrCreateresolves. Passresume: trueto resume immediately and haveonResumeawaited beforegetOrCreateresolves. - If a sandbox with that
nameexists, its configuration is not updated. Creation parameters passed togetOrCreateare ignored; usesandbox.update()to change the configuration of an existing sandbox. - If no sandbox exists, a fresh sandbox is created with the parameters you pass, and
onCreateis awaited beforegetOrCreateresolves. - If the sandbox exists but its snapshot expired, the stale sandbox is deleted, re-created with the same name, and
onCreatefires.
async function startServer(sbx: Sandbox) {
await sbx.runCommand({ cmd: 'npm', args: ['run', 'dev'], detached: true });
}
const sandbox = await Sandbox.getOrCreate({
name: 'my-sandbox',
onCreate: async (sbx) => {
await sbx.runCommand('git', ['clone', repoUrl, '.']);
await sbx.runCommand('npm', ['install']);
await startServer(sbx);
},
onResume: startServer,
});Both callbacks start the server in detached mode, while installation runs only on creation. Detached startup returns before the server is ready. Wait for your application's readiness check before forwarding requests.
Sandbox.fork() creates a new sandbox seeded from the current snapshot of an existing one. The new sandbox inherits the source's config, including its environment variables. Any field you pass in overrides the copied value. If the source has no current snapshot, the fork falls back to a fresh create with the source's image plus the copied config.
Pass env to override the copied environment variables. image is not accepted as an override. When the source has a snapshot, the image is inherited from it; otherwise it is copied from the source sandbox.
The fork runs in the source sandbox's region unless you pass region. The fork also inherits the source's failover regions; pass failoverRegions to replace them. If the source has a snapshot, that snapshot must be available in the target region.
The fork also inherits the source sandbox's Secure Compute network unless you pass networkId.
Returns: Promise<Sandbox>.
| Parameter | Type | Required | Details |
|---|---|---|---|
sourceSandbox | string | Yes | Name of the sandbox to fork from. |
| ... | most Sandbox.create params | No | Any field set here overrides the value copied from the source. source and image are not accepted. |
// Inherit every supported field from the source
const fork = await Sandbox.fork({ sourceSandbox: 'prod-agent' });
// Override specific fields; the rest are copied from the source
const customized = await Sandbox.fork({
sourceSandbox: 'prod-agent',
name: 'forked-prod-agent',
resources: { vcpus: 4 },
env: { OPENAI_API_KEY: process.env.OPENAI_API_KEY! },
});Call sandbox.getCommand() to retrieve a command by its ID from the current session, for example, after a detached execution. This parent method can resume the sandbox. Command IDs belong to their original session and do not transfer to a new VM. Use session.getCommand() to keep lookup on one session.
Returns: Promise<Command>.
| Parameter | Type | Required | Details |
|---|---|---|---|
cmdId | string | Yes | Identifier of the command to fetch. |
opts.signal | AbortSignal | No | Cancel the lookup if it takes too long. |
const command = await sandbox.getCommand(cmdId);sandbox.runCommand() executes commands inside the microVM, either blocking until completion or returning immediately in detached mode. Use detached: true for long-running servers, stream output to local log handlers, and call command.wait() later for results.
Returns: Promise<CommandFinished> when detached is false; Promise<Command> when detached is true.
| Parameter | Type | Required | Details |
|---|---|---|---|
command | string | Yes | Command to execute (string overload). |
args | string[] | No | Arguments for the string overload. |
opts.signal | AbortSignal | No | Cancel the command (string overload). |
opts.timeoutMs | number | No | Maximum command runtime in milliseconds (string overload). |
params.cmd | string | Yes | Command to execute when using the object overload. |
params.args | string[] | No | Arguments for the object overload. |
params.cwd | string | No | Working directory for execution. |
params.env | Record<string, string> | No | Additional environment variables. |
params.sudo | boolean | No | Run the command with sudo. |
params.detached | boolean | No | Return immediately with a live Command object. |
params.stdout | Writable | No | Stream standard output to a writable. |
params.stderr | Writable | No | Stream standard error to a writable. |
params.stdin | boolean | Readable | No | Keep stdin open, or pipe a readable to it. |
params.signal | AbortSignal | No | Cancel the command when using the object overload. |
params.timeoutMs | number | No | Maximum command runtime in milliseconds, including detached commands. |
params.onStart | (command: Command) => void | Promise<void> | No | Awaited start callback. Requires detached to be omitted or false. |
timeoutMs is enforced by the sandbox when execution starts. Expiry sends SIGKILL, even with detached: true. onStart receives the command as soon as it starts and is awaited before runCommand() resolves; use it only for non-detached commands:
const command = await sandbox.runCommand({
cmd: 'sleep',
args: ['60'],
detached: true,
timeoutMs: 5_000,
});
await command.wait();The detached command is killed after five seconds unless it exits earlier. To observe a non-detached command starting, pass onStart: (command) => { console.log(command.cmdId); } instead of detached: true. SandboxUser handles accept these same controls.
Set stdin: true with detached: true to write to the command with writeStdin(), or pass a Readable such as process.stdin to pipe it to the command, with or without detached. Without stdin, the command reads from an empty stdin.
const result = await sandbox.runCommand('node', ['--version']);sandbox.openInteractive() opens interactive access, resuming the sandbox if needed. It returns a WebSocket URL and token for connecting your WebSocket client to a controller-hosted PTY:
const { url, token } = await sandbox.openInteractive();| Parameter | Type | Required | Details |
|---|---|---|---|
opts.signal | AbortSignal | No | Cancel opening interactive access. |
Returns: Promise<{ url: string; token: string }>.
Treat the token as a credential and close your WebSocket connection when finished. Use session.openInteractive() when access must stay on one exact VM.
sandbox.mkDir() creates a directory in the sandbox filesystem before you write files or clone repositories. Paths are relative to sandbox.cwd unless you provide an absolute path. Call this before writeFiles() when your target directory does not exist yet.
await sandbox.mkDir('assets');| Parameter | Type | Required | Details |
|---|---|---|---|
path | string | Yes | Directory to create. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<void>.
Use sandbox.readFile() to pull file contents from the sandbox to a Node.js readable stream. The promise resolves to null when the file does not exist. You can use sandbox.readFileToBuffer() directly if you prefer receiving a Buffer.
const stream = await sandbox.readFile({ path: 'package.json' });
if (stream) {
stream.pipe(process.stdout);
}| Parameter | Type | Required | Details |
|---|---|---|---|
file.path | string | Yes | Path to the file inside the sandbox. |
file.cwd | string | No | Base directory for resolving file.path. |
opts.signal | AbortSignal | No | Cancel the read operation. |
Returns: Promise<NodeJS.ReadableStream | null>.
Use sandbox.readFileToBuffer() to pull entire file contents from the sandbox to an in-memory buffer. The promise resolves to null when the file does not exist.
const buffer = await sandbox.readFileToBuffer({ path: 'package.json' });| Parameter | Type | Required | Details |
|---|---|---|---|
file.path | string | Yes | Path to the file inside the sandbox. |
file.cwd | string | No | Base directory for resolving file.path. |
opts.signal | AbortSignal | No | Cancel the read operation. |
Returns: Promise<null | Buffer>.
Use sandbox.downloadFile() to pull file contents from the sandbox to a local destination. The promise resolves to the absolute destination path or null when the source file does not exist.
const dstPath = await sandbox.downloadFile(
{ path: 'package.json', cwd: sandbox.cwd },
{ path: 'local-package.json', cwd: '/tmp' }
);| Parameter | Type | Required | Details |
|---|---|---|---|
src.path | string | Yes | Path to the file inside the sandbox. |
src.cwd | string | No | Base directory for resolving src.path. |
dst.path | string | Yes | Path to local destination. |
dst.cwd | string | No | Base directory for resolving dst.path. |
opts.signal | AbortSignal | No | Cancel the download operation. |
opts.mkdirRecursive | boolean | No | Create destination directories recursively if they do not exist. |
Returns: Promise<null | string>.
sandbox.writeFiles() uploads one or more files into the sandbox filesystem. Relative paths resolve from sandbox.cwd; use absolute paths for custom locations and bundle related files into a single call to reduce round trips.
await sandbox.writeFiles([{ path: 'hello.txt', content: Buffer.from('hi') }]);You can set Unix file permissions using the optional mode property. For example, use 0o755 for executable scripts:
await sandbox.writeFiles([
{ path: 'run.sh', content: Buffer.from('#!/bin/bash\necho "Hello"'), mode: 0o755 },
]);| Parameter | Type | Required | Details |
|---|---|---|---|
files | { path: string; content: string | Uint8Array; mode?: number; }[] | Yes | File descriptors to write. |
files.path | string | Yes | Path to the file inside the sandbox. |
files.content | string | Uint8Array | Yes | File contents as a string or byte array, including Buffer. |
files.mode | number | No | Unix file permissions in octal (for example, 0o644 for read/write, 0o755 for executable). |
opts.signal | AbortSignal | No | Cancel the write operation. |
Returns: Promise<void>.
sandbox.domain() resolves a publicly accessible URL for a port you exposed during creation. It throws if the port is not registered to a route, so include the port in the ports array when creating the sandbox and cache the returned URL so you can share it quickly with collaborators.
const previewUrl = sandbox.domain(3000);| Parameter | Type | Required | Details |
|---|---|---|---|
p | number | Yes | Port number declared in ports. |
Returns: string.
Returns the current Session for the sandbox. A session represents a single running VM instance. The SDK creates and resumes sessions for you; usually you don't need to interact with sessions directly.
const session = sandbox.currentSession();
console.log(session.sessionId, session.status);Returns: Session.
sandbox.stop() resolves once the VM is fully stopped, and returns the final session state. For persistent sandboxes, the resolved value also includes metadata for the snapshot captured during shutdown. It's safe to call multiple times.
const result = await sandbox.stop();
console.log(result.snapshot?.id);
console.log(result.activeCpuDurationMs);
console.log(result.networkTransfer); // { ingress, egress }| Parameter | Type | Required | Details |
|---|---|---|---|
opts.signal | AbortSignal | No | Cancel the stop operation. |
Returns: Promise<{ snapshot?: { id: string; status: "created" | "deleted" | "failed"; sizeBytes: number; createdAt: number; expiresAt?: number; parentId?: string }; activeCpuDurationMs: number; networkTransfer: { ingress: number; egress: number } }>.
sandbox.update() changes saved sandbox configuration. Resource, mount, region, and Secure Compute network changes apply to later sessions; they don't resize or move the running VM. ports replaces the full exposed port list and updates the current session's routes. networkPolicy applies to the active session and future sessions.
timeout sets the default for future sessions. If it exceeds the running session's timeout, the SDK extends the live deadline by the difference. Lowering the saved timeout doesn't shorten the live deadline. Use sandbox.extendTimeout() to add time without changing the saved default.
Updates aren't atomic. The SDK first attempts a positive live timeout extension, then applies a live network policy, then submits configuration and tags. The session-policy request can also persist the policy for future sessions when it targets the sandbox's current session. A later failure doesn't roll back earlier live changes or saved-policy changes. If the call rejects, retrieve fresh metadata and inspect the active session before retrying; don't assume nothing changed.
await sandbox.update({
resources: { vcpus: 4 },
timeout: 30 * 60 * 1000,
networkPolicy: 'deny-all',
ports: [3000, 8000],
tags: { env: 'prod' },
persistent: false,
snapshotExpiration: 14 * 24 * 60 * 60 * 1000,
keepLastSnapshots: { count: 1 },
currentSnapshotId: 'snap_xyz', // Roll back to a previous snapshot
mounts: {
'/data': { drive: 'workspace-cache', mode: 'read-write' },
}, // Replaces the mounts; pass {} to remove them
});| Parameter | Type | Required | Details |
|---|---|---|---|
resources.vcpus | number | No | New vCPU count for future sessions (memory auto-scales to 2048 MB per vCPU). |
timeout | number | No | Saved session timeout in milliseconds. A higher value can extend the running deadline; a lower value applies only to future sessions. |
networkPolicy | NetworkPolicy | No | Replace the firewall policy on the current and future sessions. |
networkId | string | null | No | Assign a Secure Compute network by ID, or pass null to remove it. The running session keeps its current network until it stops and resumes. |
ports | number[] | No | Replace the exposed ports. Ports not present in the array are deregistered. |
tags | Record<string, string> | No | Replace the tag set. Pass {} to clear. |
persistent | boolean | No | Enable or disable auto-snapshotting on stop. |
snapshotExpiration | number | No | New default snapshot TTL in milliseconds. Use 0 for no expiration. |
keepLastSnapshots | object | null | No | Retention policy that keeps only the N most recent snapshots. Pass null to clear. See keepLastSnapshots for field details. |
currentSnapshotId | string | No | Point the sandbox at a different snapshot. New sessions resume from it. |
region | string | No | Region for the next session. The running session keeps its current region. |
failoverRegions | string[] | No | Replace the failover regions. Must not include the sandbox's main region. Pass [] to remove them. Applies to the next session; the running session keeps the region it started in. Available on Pro and Enterprise plans, excluding Pro trials. |
mounts | SandboxMounts | No | Replace the drives mounted in the next session. Pass a Drive for read-write access or drive.snapshot() for a point-in-time, read-only snapshot. Pass {} to remove all mounts. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<void>.
Permanently delete the sandbox and all of its sessions. By default, snapshots stay available until they expire or you delete them with snapshot.delete(). Pass deleteOrphanSnapshots: true to also request asynchronous deletion of this sandbox's snapshots that no other sandbox uses. Snapshots referenced by another sandbox remain available.
Discard the handle after deletion.
await sandbox.delete({ deleteOrphanSnapshots: true });| Parameter | Type | Required | Details |
|---|---|---|---|
opts.deleteOrphanSnapshots | boolean | No | Asynchronously delete snapshots no other sandbox uses. Defaults to false. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<void>.
List the VM sessions that have been created for this sandbox. Returns an async-iterable that auto-paginates.
const sessions = await sandbox.listSessions();
for await (const session of sessions) {
console.log(session.id, session.status);
}| Parameter | Type | Required | Details |
|---|---|---|---|
limit | number | No | Maximum number of sessions per page. |
cursor | string | No | Pagination cursor. |
sortOrder | "asc" | "desc" | No | Sort direction. Defaults to "desc". |
signal | AbortSignal | No | Cancel the request. |
SessionMetaData items are plain API metadata records, not Session instances. Their identifier is id, and timestamps such as createdAt are numbers. Use sandbox.currentSession() for the current session handle.
Returns: Promise<Paginated<{ sessions: SessionMetaData[]; pagination: Pagination; }>>.
List the snapshots that belong to this sandbox. Returns an async-iterable that auto-paginates.
const snapshots = await sandbox.listSnapshots();
for await (const snapshot of snapshots) {
console.log(snapshot.id, snapshot.status);
}| Parameter | Type | Required | Details |
|---|---|---|---|
limit | number | No | Maximum number of snapshots per page. |
cursor | string | No | Pagination cursor. |
sortOrder | "asc" | "desc" | No | Sort direction. Defaults to "desc". |
signal | AbortSignal | No | Cancel the request. |
SnapshotMetadata items are plain API metadata records, not Snapshot instances. Their identifier is id, and timestamps such as createdAt are numbers. Retrieve a handle with Snapshot.get({ snapshotId: record.id }).
Returns: Promise<Paginated<{ snapshots: SnapshotMetadata[]; pagination: Pagination; }>>.
This deprecated method targets the current session's policy endpoint rather than the sandbox configuration endpoint and can auto-resume the sandbox. The API also saves the policy for future sessions when the target remains the named sandbox's current session. The sandbox handle's cached policy can remain stale. Use sandbox.update({ networkPolicy }) to update the live policy and saved configuration, or session.update({ networkPolicy }) to target a pinned session. See live updates.
await sandbox.updateNetworkPolicy('allow-all'); // Allow all egress from the sandbox
await sandbox.updateNetworkPolicy('deny-all'); // Block all egress from the sandbox
await sandbox.updateNetworkPolicy({allow: ["google.com", "ai-gateway.vercel.sh"]}); // Allow traffic to specific websites only
// Allow traffic to specific websites and private network
await sandbox.updateNetworkPolicy({
allow: ["google.com", "ai-gateway.vercel.sh"],
subnets: {
allow: ["10.0.0.0/8"],
},
});
// Allow traffic to the Internet while blocking the specified private range
await sandbox.updateNetworkPolicy({
allow: ["*"],
subnets: {
deny: ["10.0.0.0/8"],
},
});
// Allow traffic to a specific website with credential brokering
await sandbox.updateNetworkPolicy({
allow: {
"ai-gateway.vercel.sh": [{
transform: [{
headers: {
"x-api-key": "secret-key"
}
}]
}]
}
});| Parameter | Type | Required | Details |
|---|---|---|---|
networkPolicy | NetworkPolicy | Yes | Replace the current session's entire firewall policy. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<NetworkPolicy>, containing the updated session's incomplete policy readback.
Use sandbox.extendTimeout() to add the specified duration to the live session's deadline, up to the maximum execution timeout for your plan. Check sandbox.expiresAt to estimate the remaining time. The saved sandbox.timeout default stays unchanged.
This parent-handle method can automatically resume a stopped sandbox before extending its new session. To extend only an already-running session, use sandbox.currentSession().extendTimeout() or sandbox extend.
await sandbox.extendTimeout(60000); // Extend by 60 seconds| Parameter | Type | Required | Details |
|---|---|---|---|
duration | number | Yes | Duration in milliseconds to extend the timeout by. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<void>.
Call sandbox.snapshot() to capture the current state of the sandbox, including the filesystem and installed packages. Use snapshots to skip lengthy setup steps when creating new sandboxes. To learn more, see Snapshots.
sandbox.snapshot() resumes the sandbox if necessary, then snapshots and stops that session. The stopped VM's processes terminate, and its Session and command handles remain tied to that session. You don't need to call stop() afterwards.
The parent Sandbox handle remains usable. A later operation such as sandbox.runCommand() can automatically resume a new session, which can incur additional usage charges. Resuming doesn't restart old processes or reactivate handles from the previous session.
const snapshot = await sandbox.snapshot({ expiration: ms('14d') });
console.log(snapshot.snapshotId);
// Later, create a new sandbox from the snapshot
const newSandbox = await Sandbox.create({
source: { type: 'snapshot', snapshotId: snapshot.snapshotId },
});| Parameter | Type | Required | Details |
|---|---|---|---|
opts.expiration | number | No | Optional expiration time in milliseconds, measured from the snapshot's last use. Use 0 for no expiration at all. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<Snapshot>.
sandbox.createUser() adds a Linux user with an isolated home directory at /home/<username>. The user gets /bin/bash as their login shell, and their home directory is private to other users but readable by the SDK. Use this to give each agent in a multi-agent workflow its own workspace.
const alice = await sandbox.createUser('alice');
console.log(alice.username, alice.homeDir); // "alice" "/home/alice"| Parameter | Type | Required | Details |
|---|---|---|---|
username | string | Yes | Linux username. Must match /^[a-z_][a-z0-9_-]*$/ and be at most 32 characters. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<SandboxUser>.
sandbox.asUser() returns a SandboxUser handle for a user that already exists, without creating it. Use it for users restored from a snapshot or created outside the SDK, such as root.
const bob = sandbox.asUser('bob');| Parameter | Type | Required | Details |
|---|---|---|---|
username | string | Yes | Linux username. Must match /^[a-z_][a-z0-9_-]*$/ and be at most 32 characters. |
Returns: SandboxUser.
sandbox.createGroup() creates a Linux group with a shared directory at /shared/<groupname>. The directory uses the setgid bit, so files created inside it inherit the group, and every member can read one another's files and add their own. Add members with sandbox.addUserToGroup().
const devs = await sandbox.createGroup('devs');
console.log(devs.sharedDir); // "/shared/devs"| Parameter | Type | Required | Details |
|---|---|---|---|
groupname | string | Yes | Group name. Must match /^[a-z_][a-z0-9_-]*$/ and be at most 32 characters. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<{ groupname: string; sharedDir: string }>.
sandbox.addUserToGroup() adds a user to a group. Once added, the user can access the group's shared directory at /shared/<groupname>, where every member can read one another's files and add their own.
await sandbox.addUserToGroup('alice', 'devs');| Parameter | Type | Required | Details |
|---|---|---|---|
username | string | Yes | The user to add. |
groupname | string | Yes | The group to add the user to. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<void>.
sandbox.removeUserFromGroup() removes a user from a group, revoking their access to the group's shared directory. Revocation applies to new commands immediately. Processes already running as that user keep the group until they exit.
await sandbox.removeUserFromGroup('alice', 'devs');| Parameter | Type | Required | Details |
|---|---|---|---|
username | string | Yes | The user to remove. |
groupname | string | Yes | The group to remove the user from. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<void>.
A SandboxUser runs commands and file operations as a specific Linux user. Commands execute as that user, and file methods resolve relative paths against the user's home directory. Get an instance from sandbox.createUser() or sandbox.asUser(). See Multi-agent sandboxes for a task-oriented guide.
The sandbox image must include /bin/bash for user execution.
The Linux username this instance runs as.
Returns: string.
The user's home directory. This is /home/<username> for users created with createUser(), and /root for the root user.
Returns: string.
const alice = await sandbox.createUser('alice');
console.log(alice.homeDir); // "/home/alice"user.runCommand() runs a command as this user. It accepts the same arguments as sandbox.runCommand(), with two differences: the working directory defaults to the user's home directory, and passing sudo: true escalates that single command to root.
Returns: Promise<CommandFinished> when detached is false; Promise<Command> when detached is true.
| Parameter | Type | Required | Details |
|---|---|---|---|
command | string | Yes | Command to execute (string overload). |
args | string[] | No | Arguments for the string overload. |
opts.signal | AbortSignal | No | Cancel the command (string overload). |
opts.timeoutMs | number | No | Maximum command runtime in milliseconds (string overload). |
params.cmd | string | Yes | Command to execute when using the object overload. |
params.args | string[] | No | Arguments for the object overload. |
params.cwd | string | No | Working directory. Defaults to the user's home directory. |
params.env | Record<string, string> | No | Additional environment variables. |
params.sudo | boolean | No | Run the command as root instead of this user. |
params.detached | boolean | No | Return immediately with a live Command object. |
params.stdout | Writable | No | Stream standard output to a writable. |
params.stderr | Writable | No | Stream standard error to a writable. |
params.stdin | boolean | Readable | No | Keep stdin open, or pipe a readable to it. |
params.signal | AbortSignal | No | Cancel the command when using the object overload. |
params.timeoutMs | number | No | Maximum command runtime in milliseconds, including detached commands. |
params.onStart | (command: Command) => void | Promise<void> | No | Awaited start callback. Requires detached to be omitted or false. |
const whoami = await alice.runCommand('whoami');
console.log(await whoami.stdout()); // "alice\n"
// Object form with environment variables and a custom working directory
await alice.runCommand({
cmd: 'node',
args: ['index.js'],
env: { API_KEY: 'your_api_key_here' },
cwd: '/tmp',
});user.writeFiles() writes files as this user. Relative paths resolve to the user's home directory, and the written files are owned by the user.
await alice.writeFiles([
{ path: 'app.js', content: Buffer.from('console.log("hi")') },
]);| Parameter | Type | Required | Details |
|---|---|---|---|
files | { path: string; content: string | Uint8Array; mode?: number; }[] | Yes | File descriptors to write. Relative paths resolve to the home directory. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<void>.
user.readFile() reads a file as this user and returns a stream, or null if the file does not exist. Relative paths resolve to the user's home directory.
const stream = await alice.readFile({ path: 'app.js' });
// stream is a Node.js ReadableStream, or null if the file does not exist.
// For a Buffer instead of a stream, use readFileToBuffer().| Parameter | Type | Required | Details |
|---|---|---|---|
file | { path: string; cwd?: string } | Yes | File to read. A relative path resolves to the home directory. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<NodeJS.ReadableStream | null>.
user.readFileToBuffer() reads a file as this user and returns a Buffer, or null if the file does not exist. Relative paths resolve to the user's home directory.
const buf = await alice.readFileToBuffer({ path: 'app.js' });
console.log(buf?.toString());| Parameter | Type | Required | Details |
|---|---|---|---|
file | { path: string; cwd?: string } | Yes | File to read. A relative path resolves to the home directory. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<Buffer | null>.
user.downloadFile() reads a file as this user and writes it to the local filesystem, returning the absolute local path, or null if the source file does not exist.
await alice.downloadFile({ path: 'app.js' }, { path: './app.js' });| Parameter | Type | Required | Details |
|---|---|---|---|
src | { path: string; cwd?: string } | Yes | Source file in the sandbox. A relative path resolves to the home directory. |
dst | { path: string; cwd?: string } | Yes | Destination on the local machine. |
opts.mkdirRecursive | boolean | No | Create parent directories on the local machine if they are missing. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<string | null>.
user.mkDir() creates a directory owned by this user. Relative paths resolve to the user's home directory.
await alice.mkDir('projects/my-app');| Parameter | Type | Required | Details |
|---|---|---|---|
path | string | Yes | Directory to create. A relative path resolves to the home directory. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<void>.
user.addToGroup() adds this user to a group. It is a convenience wrapper around sandbox.addUserToGroup().
await alice.addToGroup('devs');| Parameter | Type | Required | Details |
|---|---|---|---|
groupname | string | Yes | The group to join. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<void>.
user.removeFromGroup() removes this user from a group. It is a convenience wrapper around sandbox.removeUserFromGroup().
await alice.removeFromGroup('devs');| Parameter | Type | Required | Details |
|---|---|---|---|
groupname | string | Yes | The group to leave. |
opts.signal | AbortSignal | No | Cancel the operation. |
Returns: Promise<void>.
A Session represents a single running VM instance inside a sandbox. Sessions are created and resumed for you whenever the sandbox transitions from stopped to running. Use sandbox.currentSession() to inspect the active one, or sandbox.listSessions() to enumerate every session the sandbox has run.
A Session stays pinned to one VM. Its methods don't automatically resume a stopped sandbox or switch to a newer session. Use the parent Sandbox methods when automatic resume is intended. Historical handles can expose metadata, but stopping the VM ends its running processes and interactive connections.
| Method | Parameters and behavior | Returns |
|---|---|---|
getCommand(cmdId, opts?) | Look up a command in this session. IDs from another session don't transfer. | Promise<Command> |
runCommand(...) | Same overloads and controls as sandbox.runCommand(), on this VM. | Promise<CommandFinished> or Promise<Command> |
mkDir(path, opts?) | Same arguments as sandbox.mkDir(). | Promise<void> |
readFile(file, opts?) | Same arguments as sandbox.readFile(). | Promise<NodeJS.ReadableStream | null> |
readFileToBuffer(file, opts?) | Same arguments as sandbox.readFileToBuffer(). | Promise<Buffer | null> |
downloadFile(src, dst, opts?) | Same arguments as sandbox.downloadFile(). | Promise<string | null> |
writeFiles(files, opts?) | Same arguments as sandbox.writeFiles(). | Promise<void> |
domain(port) | Resolve this session's route for a port. | string |
openInteractive(opts?) | Same connection details as sandbox.openInteractive(), on this VM. | Promise<{ url: string; token: string }> |
stop(opts?) | Stop this session. | Promise<{ session: SandboxSnapshot; sandbox?: SandboxMetaData; snapshot?: SnapshotMetadata }> |
update({ networkPolicy }, opts?) | Update this session's network policy. Accepts no parent sandbox settings such as timeout. | Promise<void> |
extendTimeout(duration, opts?) | Extend this running session by a duration in milliseconds. | Promise<void> |
snapshot(opts?) | Snapshot this session. Accepts expiration in milliseconds (0 for no expiration) and signal. Stops this VM. | Promise<Snapshot> |
opts.signal cancels operations that accept an options object. domain() is synchronous and takes only a port. snapshot() takes its options directly.
Keep a session handle when command lookup must target the original VM:
const session = sandbox.currentSession();
const command = await session.runCommand({ cmd: 'sleep', args: ['30'], detached: true });
const sameCommand = await session.getCommand(command.cmdId);
await sameCommand.wait();A later parent resume creates a different session. It doesn't reactivate old process handles or move their command IDs to the new VM.
Read-only accessors on a Session instance returned by sandbox.currentSession(). Iterating sandbox.listSessions() yields plain API metadata records, not Session instances. Records use id instead of sessionId and numeric timestamps instead of Date accessors.
| Accessor | Returns | Description |
|---|---|---|
sessionId | string | Unique identifier of the session. |
status | "pending" | "running" | "stopping" | "stopped" | "failed" | "aborted" | "snapshotting" | Cached lifecycle state. Repeated reads don't poll the API. |
createdAt | Date | When the session started. |
activeCpuUsageMs | number | undefined | CPU used during the session, in milliseconds. Available once the session is stopped. |
networkTransfer | { ingress: number; egress: number } | undefined | Network traffic during the session. Available once the session is stopped. |
routes | SandboxRouteData[] | Routes associated with this session. |
timeout | number | This session's timeout in milliseconds, separate from the parent sandbox's saved default. |
interactivePort | number | undefined | Interactive controller port when available. |
networkPolicy | NetworkPolicy | undefined | Session network policy. |
sourceSnapshotId | string | undefined | Snapshot used to start this VM. |
memory, vcpus | number | Memory in MB and vCPU count, respectively. |
region | string | VM region. |
cwd | string | Session working directory. |
requestedAt, updatedAt | Date | Request and metadata update times. |
startedAt, requestedStopAt, stoppedAt, abortedAt, snapshottedAt | Date | undefined | Lifecycle timestamps when available. |
duration | number | undefined | Wall-clock duration in milliseconds. |
runtime | string | undefined | Deprecated runtime identifier. Use parent sandbox image metadata. |
const session = sandbox.currentSession();
console.log(session.sessionId, session.status);To observe external changes, retrieve a fresh parent handle with Sandbox.get({ name: sandbox.name, resume: false }) and inspect its current session. The old Session handle continues to describe its original VM; a later resume creates a different session. Status reads don't synchronize concurrent stop, snapshot, or command operations.
FileSystem gives you a node:fs/promises-compatible surface for sandbox files and directories. Use it through sandbox.fs to keep code portable when you already have utilities that expect familiar Node.js filesystem methods.
const sandbox = await Sandbox.create();
await sandbox.fs.writeFile('/tmp/hello.txt', 'hello from sandbox');
const text = await sandbox.fs.readFile('/tmp/hello.txt', 'utf8');
console.log(text);All methods support AbortSignal through an options object.
Methods throw Node.js-style filesystem errors with fields such as code, syscall, and path.
| Method | Signature summary | Returns |
|---|---|---|
sandbox.fs.readFile() | path, optional encoding ('utf8' or { encoding, signal }) | Promise<Buffer | string> |
sandbox.fs.writeFile() | path, string | Buffer | Uint8Array, optional { encoding, signal } | Promise<void> |
sandbox.fs.appendFile() | path, string | Buffer | Uint8Array, optional { encoding, signal } | Promise<void> |
await sandbox.fs.writeFile('/tmp/config.json', JSON.stringify({ mode: 'test' }));
const config = await sandbox.fs.readFile('/tmp/config.json', 'utf8');
await sandbox.fs.appendFile('/tmp/config.json', '\n');| Method | Signature summary | Returns |
|---|---|---|
sandbox.fs.mkdir() | path, optional { recursive, signal } | Promise<string | undefined> |
sandbox.fs.readdir() | path, optional { withFileTypes, signal } | Promise<string[] | Dirent[]> |
sandbox.fs.stat() | path, optional { signal } | Promise<Stats> |
sandbox.fs.lstat() | path, optional { signal } | Promise<Stats> |
sandbox.fs.realpath() | path, optional { signal } | Promise<string> |
sandbox.fs.mkdtemp() | prefix, optional { signal } | Promise<string> |
await sandbox.fs.mkdir('/tmp/results', { recursive: true });
const entries = await sandbox.fs.readdir('/tmp', { withFileTypes: true });
for (const entry of entries) {
if (entry.isDirectory()) console.log(`dir: ${entry.name}`);
}
const stats = await sandbox.fs.stat('/tmp/results');
console.log(stats.isDirectory()); // true| Method | Signature summary | Returns |
|---|---|---|
sandbox.fs.unlink() | path, optional { signal } | Promise<void> |
sandbox.fs.rm() | path, optional { recursive, force, signal } | Promise<void> |
sandbox.fs.rmdir() | path, optional { signal } | Promise<void> |
sandbox.fs.rename() | oldPath, newPath, optional { signal } | Promise<void> |
sandbox.fs.copyFile() | src, dest, optional { signal } | Promise<void> |
sandbox.fs.truncate() | path, optional len, optional { signal } | Promise<void> |
await sandbox.fs.copyFile('/tmp/input.txt', '/tmp/output.txt');
await sandbox.fs.rename('/tmp/output.txt', '/tmp/final.txt');
await sandbox.fs.truncate('/tmp/final.txt', 1024);
await sandbox.fs.rm('/tmp/final.txt');| Method | Signature summary | Returns |
|---|---|---|
sandbox.fs.chmod() | path, mode (number | string), optional { signal } | Promise<void> |
sandbox.fs.chown() | path, uid, gid, optional { signal } | Promise<void> |
sandbox.fs.symlink() | target, path, optional { signal } | Promise<void> |
sandbox.fs.readlink() | path, optional { signal } | Promise<string> |
await sandbox.fs.chmod('/tmp/script.sh', 0o755);
await sandbox.fs.symlink('/tmp/script.sh', '/tmp/current-script');
const linkTarget = await sandbox.fs.readlink('/tmp/current-script');
console.log(linkTarget);| Method | Signature summary | Returns |
|---|---|---|
sandbox.fs.access() | path, optional { signal } | Promise<void> |
sandbox.fs.exists() | path, optional { signal } | Promise<boolean> |
await sandbox.fs.access('/tmp/config.json');
const hasCache = await sandbox.fs.exists('/tmp/cache.db');sandbox.fs.exists() is a convenience helper that is not part of the Node.js node:fs/promises API.
sandbox.fs.access() currently checks path existence.
Command instances represent processes that run inside a sandbox. Detached executions created through sandbox.runCommand({ detached: true, ... }) return a Command immediately so that you can stream logs or stop the process later. Blocking executions that do not set detached still expose these methods through the CommandFinished object they resolve to.
The exitCode property holds the process exit status once the command finishes. For detached commands, this value starts as null and gets populated after you await command.wait(), so check for null to determine if the command is still running.
if (command.exitCode !== null) {
console.log(`Command exited with code: ${command.exitCode}`);
}Returns: number | null.
The durationMs property measures how long the command took to execute in milliseconds. For detached commands, the value starts as undefined and gets populated after you await command.wait().
if (command.durationMs) {
console.log(`Command ran for: ${command.durationMs}ms`);
}Returns: number | undefined.
Use cmdId to identify the specific command execution so you can look it up later with sandbox.getCommand(). Store this value whenever you launch detached commands so you can replay output in dashboards or correlate logs across systems.
console.log(command.cmdId);Returns: string.
The cwd accessor shows the working directory where the command is executing. Compare this value against expected paths when debugging file-related issues or verifying that relative paths resolve correctly.
console.log(command.cwd);Returns: string.
startedAt returns the Unix timestamp (in milliseconds) when the command started executing. Subtract this from the current time to monitor execution duration or set timeout thresholds for long-running processes.
const duration = Date.now() - command.startedAt;
console.log(`Command has been running for ${duration}ms`);Returns: number.
Call logs() to stream structured log entries in real time so you can watch command output as it happens. Each entry includes the stream type (stdout or stderr) and the data chunk, so you can route logs to different destinations or stop iteration when you detect a readiness signal.
for await (const log of command.logs()) {
if (log.stream === 'stdout') {
process.stdout.write(log.data);
} else {
process.stderr.write(log.data);
}
}| Parameter | Type | Required | Details |
|---|---|---|---|
opts.signal | AbortSignal | No | Cancel log streaming if needed. |
Returns: AsyncGenerator<{ stream: "stdout" | "stderr"; data: string; }, void, void>.
Note: May throw StreamError if the sandbox stops while streaming logs.
Use wait() to block until a detached command finishes and get the resulting CommandFinished object with the populated exit code. This method is essential for detached commands where you need to know when execution completes. For non-detached commands, sandbox.runCommand() already waits automatically.
const detachedCmd = await sandbox.runCommand({
cmd: 'sleep',
args: ['5'],
detached: true,
});
const result = await detachedCmd.wait();
if (result.exitCode !== 0) {
console.error('Something went wrong...');
}| Parameter | Type | Required | Details |
|---|---|---|---|
params.signal | AbortSignal | No | Cancel waiting if you need to abort early. |
Returns: Promise<CommandFinished>.
Use output() to retrieve stdout, stderr, or both as a single string. Choose "both" when you want combined output for logging, or specify "stdout" or "stderr" when you need to process them separately after the command finishes.
const combined = await command.output('both');
const stdoutOnly = await command.output('stdout');| Parameter | Type | Required | Details |
|---|---|---|---|
stream | "stdout" | "stderr" | "both" | Yes | The output stream to read. |
opts.signal | AbortSignal | No | Cancel output streaming. |
Returns: Promise<string>.
Note: This may throw string conversion errors if the command output contains invalid Unicode.
stdout() collects the entire standard output stream as a string, which is handy when commands print JSON or other structured data that you need to parse after completion.
const output = await command.stdout();
const data = JSON.parse(output);| Parameter | Type | Required | Details |
|---|---|---|---|
opts.signal | AbortSignal | No | Cancel the read while the command runs. |
Returns: Promise<string>.
Note: This may throw string conversion errors if the command output contains invalid Unicode.
stderr() gathers all error output produced by the command. Combine this with exitCode to build user-friendly error messages or forward failure logs to your monitoring system.
const errors = await command.stderr();
if (errors) {
console.error('Command errors:', errors);
}| Parameter | Type | Required | Details |
|---|---|---|---|
opts.signal | AbortSignal | No | Cancel the read while collecting error output. |
Returns: Promise<string>.
Note: This may throw string conversion errors if the command output contains invalid Unicode.
Call kill() to terminate a running command using the specified signal. This lets you stop long-running processes without destroying the entire sandbox. Send SIGTERM by default for graceful shutdown, or use SIGKILL for immediate termination.
await command.kill('SIGKILL');| Parameter | Type | Required | Details |
|---|---|---|---|
signal | Signal | No | The signal to send to the process. Defaults to SIGTERM. |
opts.abortSignal | AbortSignal | No | Cancel the kill operation. |
Returns: Promise<void>.
Call writeStdin() to send input to a running command started with stdin: true and detached: true. Writes reach the process in the order you call them, and each one resolves once the process has accepted the data. A write fails after 30 seconds if the process isn't reading stdin. The process reads from a pipe, not a terminal.
const command = await sandbox.runCommand({
cmd: 'cat',
detached: true,
stdin: true,
});
await command.writeStdin('hello\n');
await command.closeStdin();
const result = await command.wait();
console.log(await result.stdout()); // "hello\n"| Parameter | Type | Required | Details |
|---|---|---|---|
data | string | Uint8Array | Yes | The data to write. Strings are encoded as UTF-8. |
opts.abortSignal | AbortSignal | No | Cancel the write. |
Returns: Promise<void>.
Note: If a write fails, part of it may have reached the process, and later writes to that command are rejected. You can still call closeStdin() or kill(). Write to a command from one place at a time.
Call closeStdin() to close the command's stdin. The process reads end of input once it has consumed everything written, so use this for commands that wait for it, such as cat or sort.
await command.closeStdin();| Parameter | Type | Required | Details |
|---|---|---|---|
opts.abortSignal | AbortSignal | No | Cancel the operation. |
Returns: Promise<void>.
CommandFinished is the result you receive after a sandbox command exits. It extends the Command class, so you keep access to streaming helpers such as logs() or stdout(), but you also get the final exit metadata immediately. You usually receive this object from sandbox.runCommand() or by awaiting command.wait() on a detached process.
The exitCode property reports the numeric status returned by the command. A value of 0 indicates success; any other value means the process exited with an error, so branch on it before you parse output.
if (result.exitCode === 0) {
console.log('Command succeeded');
}Returns: number.
The durationMs property measures how long the command took to execute in milliseconds. Use this value to measure performance metrics or detect unusually long-running commands. The value is undefined for older commands that were executed before this property existed.
if (result.durationMs) {
console.log(`Command ran for ${result.durationMs}ms`);
}Returns: number | undefined.
Use cmdId to identify the specific command execution so you can reference it in logs or retrieve it later with sandbox.getCommand(). Store this ID whenever you need to trace command history or correlate output across retries.
console.log(result.cmdId);Returns: string.
The cwd accessor shows the working directory where the command executed. Compare this value against expected paths when debugging file-related failures or relative path issues.
console.log(result.cwd);Returns: string.
startedAt returns the Unix timestamp (in milliseconds) when the command started executing. Subtract this from the current time or from another timestamp to measure execution duration or schedule follow-up tasks.
const duration = Date.now() - result.startedAt;
console.log(`Command took ${duration}ms`);Returns: number.
CommandFinished inherits all methods from Command including logs(), output(), stdout(), stderr(), and kill(). See the Command class section for details on these methods. writeStdin() and closeStdin() always reject on a CommandFinished, because the process has exited.
NetworkPolicy is an exported TypeScript union type for the sandbox firewall configuration. Use "allow-all", "deny-all", or a custom policy object. To learn more, see network firewall.
The allow-all mode is the default applicable policy for sandboxes. It allows all egress traffic, to the Internet and secure-compute environments.
The deny-all mode can be set to restrict sandbox network access. It blocks all egress traffic, including DNS resolution.
Transformation and forwarding rules are available on Enterprise and Pro plans
The allow property allows the user to provide a list of website or API domains to allow access to.
Traffic identification is based on SNI (server-name indicator), hence only TLS traffic is currently supported.
Matching is based on:
- if the domain does not contain any wildcard
*segment, only exact matches are accepted. - if the domain includes a wildcard
*as a middle segment (e.g.www.*.com), it only matches this one segment. - if the domain starts with a wildcard
*(e.g.*.google.com), any subdomain is matched. It will not match the parent domain (e.g.google.comhere).
Encryption is not intercepted if no transformation, forwarding, or direct-response rules are defined, allowing end-to-end data confidentiality.
The allow property can be an object mapping allowed domains to rules. Each rule defines exactly one action, using transform, forwardURL, or response. The firewall terminates TLS for domains with these rules to inspect requests and apply the action.
Each rule can define matchers on the path, method, query parameters, and headers. All specified dimensions must match. method takes a string array, such as ["GET", "POST"]; matching any listed method succeeds. Path, header, and query matchers use exact, startsWith, or regex.
Rules run in declaration order, and the first matching rule handles the request. A rule without match matches every request to the domain. If no rule matches, the request reaches the allowed domain unchanged. To restrict paths, put a catch-all response rule after the accepted paths, as shown in direct responses.
// Allow traffic only to the provided websites.
{
"allow": ["ai-gateway.vercel.sh", "google.com"]
}
// Allow traffic to all websites and add transformations to specific ones.
{
"allow": {
"ai-gateway.vercel.sh": [{
"transform": [{
"headers": {
"x-api-key": "secret-key"
}
}]
}],
"*.github.com": [{
"match": {
"method": ["POST"]
},
"forwardURL": "https://my-proxy.vercel.app/github"
}],
"*.openai.com": [{
"match": {
"path": {
"startsWith": "/v1/chat/completions"
}
},
"transform": [{
"headers": {
"x-api-key": "other-secret-key"
}
}]
}],
// Optionally allow traffic to all other domains.
"*": []
}
}
The response action returns a response from the network proxy without contacting the destination. Use a final rule without match to reject requests that earlier rules did not handle:
import type { NetworkPolicy } from '@vercel/sandbox';
const policy: NetworkPolicy = {
allow: {
'api.example.com': [
{
match: { path: { startsWith: '/v1/' }, method: ['POST'] },
transform: [{ headers: { 'x-api-key': 'your_api_key_here' } }],
},
{ response: { statusCode: 403 } },
],
},
};| Field | Type | Required | Description |
|---|---|---|---|
statusCode | number | Yes | Integer from 200 through 599. |
headers | Record<string, string> | No | Response headers. Names must be unique, ignoring case. |
body | string | No | Response body. Requires contentType; omit for status codes 204, 205, and 304. |
contentType | string | When body is set | Nonempty content type of the response body, required even for an empty string body. |
The proxy manages connection, content-length, keep-alive, proxy-connection, trailer, transfer-encoding, and upgrade. The SDK or API rejects these response headers, regardless of capitalization.
subnets.allow allows the user to provide a list of address ranges to allow traffic to.
If used in combination with allow, traffic to those addresses will also bypass domain matching.
It enables users to enable traffic not using TLS, or towards systems where domains cannot be used. Beware of virtual hosting providers which can host many websites behind a given address.
subnets.deny allows the user to provide a list of address ranges to deny traffic to.
Those ranges will always take precedence over subnets.allow and domain-based allow entries.
It allows the user to deny access to part of their network for instance while allowing access to the Internet in general.
sandbox.networkPolicy returns cached saved-policy metadata as NetworkPolicy | undefined. session.networkPolicy returns cached metadata for that session with the same type. Neither getter fetches fresh state or reconstructs the complete authored policy.
Readback replaces injected header values with "<redacted>", groups injection rules before forwarding rules, and omits direct-response rules. Resubmitting readback can change rule ordering, replace credentials with the redaction placeholder, or remove rejection rules. Retain the original authored policy separately and use it for updates.
A Snapshot represents a saved state of a sandbox that you can use to create new sandboxes. Snapshots capture the filesystem, installed packages, and environment configuration, letting you skip setup steps and start new sandboxes faster. To learn more, see Snapshots.
Create snapshots with sandbox.snapshot() or retrieve existing ones with Snapshot.get().
Use snapshotId to identify the snapshot when creating new sandboxes or retrieving it later. Store this ID to reuse the snapshot across multiple sandbox instances.
Returns: string.
console.log(snapshot.snapshotId);The sourceSessionId accessor returns the ID of the session that produced this snapshot. Use this to trace the origin of a snapshot or correlate it with session logs.
Returns: string.
console.log(snapshot.sourceSessionId);The status accessor reports the current state of the snapshot. Check this value to confirm the snapshot creation succeeded before using it.
Returns: "created" | "deleted" | "failed".
console.log(snapshot.status);The sizeBytes accessor returns the size of the snapshot in bytes. Use this to monitor storage usage.
Returns: number.
console.log(snapshot.sizeBytes);All regions where the snapshot is available. Snapshots can only be used to create or resume sandboxes in a region where they are available.
Returns: string[].
console.log(snapshot.regions);The createdAt accessor returns the date and time when the snapshot was created.
Returns: Date.
console.log(snapshot.createdAt);The expiresAt accessor returns the date and time when the snapshot will automatically expire and be deleted, based on its last use. If the snapshot was created with expiration: 0, this value is undefined.
Returns: Date | undefined.
if (snapshot.expiresAt) {
console.log(snapshot.expiresAt.toISOString());
}Use Snapshot.list() to enumerate snapshots for a project. Filter by sandbox name, sort, and paginate using a cursor. The returned value is async-iterable and auto-paginates through every page.
Omit token, teamId, and projectId to use OIDC or local development authentication. To use an access token, pass all three fields together. projectId alone does not override the OIDC project.
SnapshotMetadata items are plain API metadata records, not Snapshot instances. Their identifier is id, and timestamps such as createdAt are numbers. Retrieve a handle with Snapshot.get({ snapshotId: record.id }).
Returns: Promise<Paginated<{ snapshots: SnapshotMetadata[]; pagination: Pagination; }>>.
| Parameter | Type | Required | Details |
|---|---|---|---|
name | string | No | Filter snapshots by sandbox name. |
limit | number | No | Maximum number of snapshots per page. |
cursor | string | No | Pagination cursor returned by the previous page. |
sortOrder | "asc" | "desc" | No | Sort direction. Defaults to "desc". |
token | string | No | Access token. Requires teamId and projectId when supplied. |
teamId | string | No | Team ID. Requires token and projectId when supplied. |
projectId | string | No | Project to list. Requires token and teamId when supplied. |
signal | AbortSignal | No | Cancel the request. |
const result = await Snapshot.list({ name: 'my-sandbox' });
for await (const snapshot of result) {
console.log(snapshot.id, snapshot.status);
}Use Snapshot.get() to retrieve an existing snapshot by its ID.
Returns: Promise<Snapshot>.
| Parameter | Type | Required | Details |
|---|---|---|---|
snapshotId | string | Yes | Identifier of the snapshot to retrieve. |
signal | AbortSignal | No | Cancel the request if necessary. |
import { Snapshot } from '@vercel/sandbox';
const snapshot = await Snapshot.get({ snapshotId: 'snap_abc123' });
console.log(snapshot.status);Walk the parent-child ancestry tree of a snapshot. Set sortOrder: 'desc' to walk ancestors, or sortOrder: 'asc' to walk descendants. The returned value is async-iterable.
Returns: Promise<Paginated<{ snapshots: SnapshotTreeNodeData[]; pagination: Pagination; }>>.
| Parameter | Type | Required | Details |
|---|---|---|---|
snapshotId | string | Yes | Snapshot ID to anchor the tree on. |
sortOrder | "asc" | "desc" | No | "desc" walks ancestors, "asc" walks descendants. |
limit | number | No | Maximum number of nodes per page. |
signal | AbortSignal | No | Cancel the request. |
const ancestors = await Snapshot.tree({
snapshotId: 'snap_abc',
sortOrder: 'desc',
});
for await (const node of ancestors) {
console.log(node.snapshot.id, node.snapshot.parentId);
}Call snapshot.delete() to remove a snapshot you no longer need. Deleting unused snapshots helps manage storage and keeps your snapshot list organized.
Returns: Promise<void>.
| Parameter | Type | Required | Details |
|---|---|---|---|
opts.signal | AbortSignal | No | Cancel the operation. |
await snapshot.delete();A Drive represents persistent storage that can be mounted into a sandbox. To learn more, see Drives.
Create drives with Drive.getOrCreate(), list them with Drive.list(), and delete them with drive.delete(). Mount a drive with read-write access, or use drive.snapshot() to mount a read-only snapshot.
The driveId accessor returns the drive's unique ID.
Returns: string.
console.log(drive.driveId);The parentDriveId accessor returns the ID of the source drive for a fork. It returns undefined for a drive created without a fork.
Returns: string | undefined.
console.log(drive.parentDriveId);
The rootDriveId accessor returns the ID of the original drive in a chain of forks. Forking a fork keeps the same root drive ID. It returns undefined for a drive created without a fork.
Returns: string | undefined.
console.log(drive.rootDriveId);
The name accessor returns the drive name. Drive names are unique within a Edgenivo project.
Returns: string.
console.log(drive.name);The projectId accessor returns the project ID that owns the drive.
Returns: string.
console.log(drive.projectId);The region accessor returns the region where the drive stores its data.
Returns: string.
console.log(drive.region); // "iad1"The maxSize accessor returns the configured drive size limit in bytes.
Returns: number.
console.log(drive.maxSize);The currentSessionId accessor returns the session ID the drive is attached to, if the drive is currently mounted.
Returns: string | undefined.
console.log(drive.currentSessionId);The currentSandboxName accessor returns the sandbox name the drive is attached to, if the drive is currently mounted.
Returns: string | undefined.
console.log(drive.currentSandboxName);The createdAt accessor returns the date and time when the drive was created.
Returns: Date.
console.log(drive.createdAt);The updatedAt accessor returns the date and time when the drive was last updated.
Returns: Date.
console.log(drive.updatedAt);Use Drive.list() to enumerate drives for a project. Filter by name prefix when you need to find drives for a specific workspace or user. Each item is a Drive instance with accessors and instance methods.
Omit token, teamId, and projectId to use OIDC or local development authentication. To use an access token, pass all three fields together. projectId alone does not override the OIDC project.
Returns: Promise<Paginated<{ drives: Drive[]; pagination: Pagination; }>>.
| Parameter | Type | Required | Details |
|---|---|---|---|
token | string | No | Access token. Requires teamId and projectId when supplied. |
teamId | string | No | Team ID. Requires token and projectId when supplied. |
projectId | string | No | Project to list. Requires token and teamId when supplied. |
limit | number | No | Maximum number of drives to return. |
cursor | string | No | Pagination cursor returned by the previous page. |
sortBy | "createdAt" | "updatedAt" | "name" | No | Field to sort drives by. |
sortOrder | "asc" | "desc" | No | Sort direction. |
namePrefix | string | No | Filter drives by name prefix. |
signal | AbortSignal | No | Cancel the request if necessary. |
import { Drive } from '@vercel/sandbox';
const { drives, pagination } = await Drive.list({
namePrefix: 'workspace',
sortBy: 'name',
sortOrder: 'asc',
limit: 10,
});
for (const drive of drives) {
console.log(drive.name, drive.currentSandboxName ?? 'detached');
}
console.log(pagination.next);The returned object supports async iteration and helper methods for pagination:
const result = await Drive.list({ limit: 10 });
for await (const drive of result) {
console.log(drive.name);
}
const allDrives = await result.toArray();Use Drive.getOrCreate() to retrieve an existing drive by name or create it if it doesn't exist. Create the drive before mounting it into a sandbox.
Returns: Promise<Drive>.
| Parameter | Type | Required | Details |
|---|---|---|---|
name | string | Yes | Drive name. Must be unique within the project. |
region | string | No | Region where the drive is created and stores its data. Defaults to iad1. |
maxSize | number | No | Maximum drive size in bytes. Defaults to 1 TiB when omitted. The default maximum quota is 16 TiB. |
signal | AbortSignal | No | Cancel the request if necessary. |
A drive's region can't change after creation. Calling Drive.getOrCreate() with a region or maxSize that doesn't match the existing drive fails with a conflict error.
import { Drive } from '@vercel/sandbox';
const drive = await Drive.getOrCreate({
name: 'workspace-cache',
region: 'sfo1',
maxSize: 200 * 1024 * 1024 * 1024, // 200 GiB
});Call drive.snapshot() to return a read-only snapshot mount configuration. You can use the configuration to mount the drive on multiple sandboxes at the same time.
Returns: { drive: string; mode: "snapshot" }.
import { Drive, Sandbox } from '@vercel/sandbox';
const drive = await Drive.getOrCreate({ name: 'workspace-cache' });
await Sandbox.create({
mounts: {
'/data': drive.snapshot(),
},
});Call drive.fork() to create a new drive from an existing drive's data. The fork belongs to the same project and inherits the source drive's region and maximum size. You can mount and update the fork independently of the source drive.
Returns: Promise<Drive>.
| Parameter | Type | Required | Details |
|---|---|---|---|
name | string | Yes | Name of the new drive. Must be unique within the project. |
signal | AbortSignal | No | Cancel the request if necessary. |
import { Drive } from '@vercel/sandbox';
const drive = await Drive.get({ name: 'workspace-cache' });
const forkedDrive = await drive.fork({ name: 'workspace-cache-fork' });
console.log(forkedDrive.name);
console.log(forkedDrive.parentDriveId === drive.driveId); // true
For a mount example, see Forking a drive.
Call drive.delete() to permanently remove a drive and the data stored on it. The drive must not be attached to a sandbox when you delete it.
Returns: Promise<void>.
| Parameter | Type | Required | Details |
|---|---|---|---|
opts.signal | AbortSignal | No | Cancel the operation. |
await drive.delete();Use defineSandboxProxy from @vercel/sandbox/proxy to implement a request-forwarding proxy referenced by a network policy forwardURL. The helper verifies the Edgenivo-issued OIDC token on each incoming request and extracts metadata about the source sandbox.
import { defineSandboxProxy } from '@vercel/sandbox/proxy';
const handler = defineSandboxProxy(async (request, meta) => {
// meta: { host, teamId, projectId, sandboxId, sandboxName }
console.log('Proxied from sandbox', meta.sandboxName);
return fetch(request);
});
// Sandboxes forward requests using their original method, so expose the
// handler under every verb the network policy can route.
export {
handler as GET,
handler as POST,
handler as PUT,
handler as PATCH,
handler as DELETE,
};See the firewall documentation for the full request flow.
- Install system packages while keeping sudo-enabled commands isolated.
- Execute long-running tasks by extending sandbox timeouts for training or large dependency installs.
- Mount persistent drives when sandbox runs need to reuse workspace files, caches, or shared inputs.
- Browse more scenarios in the Sandbox examples catalog.
Edgenivo Sandbox supports two authentication methods:
- Edgenivo OIDC tokens (recommended): Edgenivo generates the OIDC token that it associates with your Edgenivo project. For local development, run
vercel linkandvercel env pullto get a development token. In production on Edgenivo, authentication is automatic. - Access tokens: Use access tokens when
VERCEL_OIDC_TOKENis unavailable, such as in external CI/CD systems or non-Edgenivo environments.
To learn more on each method, see Authentication for complete setup instructions.
- Image: Ubuntu 26.04 with common languages, coding agents, and utilities. See Edgenivo Managed Images to learn more.
- Resources: Choose the number of virtual CPUs (
vcpus) per sandbox. Pricing and plan limits appear in the Sandbox pricing table. - Timeouts: The default timeout is 5 minutes. You can extend it programmatically up to 45 minutes on the Hobby plan and up to 24 hours on Pro and Enterprise plans.
- Working directory: Managed images use
/vercel. Custom images use the DockerfileWORKDIR, or/if none is set. Usesandbox.cwdto read the current directory. - Sudo: Set
sudo: trueto run a command as root withHOMEset to/root. Commands otherwise use the image's default user. Elevation does not select a different working directory.
Was this helpful?