Skip to main content
A sandbox is an isolated workspace for commands and files. Private always-on sandboxes retain workspace files across runtime restarts. Use it for code generation, repo inspection, file transformation, or script execution that you do not want to run in your trusted runtime. The sandbox client talks to an authenticated sandbox API. You need either Veryfront Cloud credentials or your own compatible backing service for /sandboxes.

Prerequisites

  • A reachable /sandboxes API and credentials for that API.
  • Outside a scoped Veryfront Cloud request, set both VERYFRONT_API_URL and VERYFRONT_API_TOKEN, or pass apiUrl and authToken explicitly.
  • A reachable network from the process that calls Sandbox.create().

Create a sandbox

Use Sandbox.create() with sandbox API credentials. In local development, self-hosted apps, CI, and other runtimes outside a Veryfront-hosted request, set both the API URL and credentials. The client has no default API URL:
Terminal
Inside a scoped Veryfront Cloud request, the client uses the request’s API URL and credentials. You do not need separate environment values for that request.
sandbox-create.ts
Verify the sandbox with a command before doing longer work:
sandbox-check.ts
You can also reconnect to an existing sandbox:
sandbox-reconnect.ts
If you already know both the sandbox ID and its runtime endpoint, attach without doing a reconnect lookup:
sandbox-attach.ts
To defer sandbox creation until the first command or file operation, use the lazy client:
sandbox-lazy.ts
For custom runtime routing, resolveRuntimeEndpoint receives { endpoint, sandboxId } and returns the runtime URL. Supply an explicit authToken; custom routing does not use stored login credentials. Use getProjectId() when the billing project is selected at runtime. It is read when the sandbox is created:
sandbox-dynamic-project.ts
To override the resolved credentials, pass authToken explicitly. This can be a JWT or a Studio-generated API key. Pass projectReference when creating a sandbox to select its billing project.
sandbox-project.ts

Run commands

Buffered execution:
sandbox-command.ts
Streaming execution:
sandbox-stream.ts

Read and write files

sandbox-files.ts

Lifecycle best practices

  • Always call await sandbox.close() in finally blocks.
  • Prefer Sandbox.createLazy() for agent-style workflows that may not need a sandbox every run.
  • Use sandbox.heartbeat() during long operations to avoid idle timeouts.
  • Persist sandbox.id only when you need reconnect semantics.
  • Keep auth tokens and API keys server-side only. Do not expose them to browsers.

Example with cleanup

sandbox-cleanup.ts

Verify it worked

Run the example above in a Node script with the env vars set. A working sandbox:
  • Prints ready to stdout from runCommand.
  • Returns exitCode: 0 from the command result.
  • Deletes its temporary sandbox on sandbox.close().
If Sandbox.create() throws a 401, double-check the API token. If cleanup fails, find the sandbox by ID in Studio and delete it.

Use a private always-on workspace

Private access requires creator-owned credentials. Always-on workspaces use the project’s existing entitlement, capacity and billing rules.
sandbox-persistent.ts
Closing a persistent or always-on client keeps the workspace by default, including persistent workspaces with timed cleanup. A lazy client deletes a newly created temporary workspace on close by default. Set deleteOnClose: false to retain it. For a lazy client, set deleteOnClose: true to delete a persistent or always-on workspace on close. The explicit flag also applies when storage metadata is missing or unknown; without an override, cleanup requires confirmed ephemeral storage and a returned temporary lifetime. Missing or invalid lifetime metadata retains the workspace. Files and user-installed tools under /workspace survive runtime replacement. Running processes and changes outside /workspace do not persist. Use sandbox.delete() to delete the sandbox and its workspace files. If an always-on lifetime update fails or its response is lost, close() preserves the workspace. Confirm its policy before changing it back to temporary cleanup or deleting it. Supplied creation selectors and project list filters must be non-empty. Omit an optional selector instead of passing an empty configuration value. Each requested file write requires a matching receipt, including repeated paths. Sandbox.list() returns access, storage and lifetime metadata. Storage and lifetime are separate policies. Changing cleanup does not migrate temporary files to persistent storage. The SDK uses /sandboxes. Command IDs come from command_id; command collections use data and page_info. Per-file write failures are reported even when the HTTP request succeeds.

Inspect and manage a workspace

sandbox-inspect.ts
checkHealth() and checkReadiness() do not record activity. heartbeat() records activity but does not extend fixed expiry. getEnvironment() returns redacted values. A creation response must explicitly identify ephemeral storage before automatic cleanup can delete its workspace. Missing or incompatible storage metadata makes close() detach and preserve the workspace. Closing a client obtained through get() or attach() leaves the sandbox available. Use delete() when you intend to remove it. A retained always-on workspace is not replaced automatically after a missing, inaccessible or unhealthy runtime response. Its ID stays available on the client so you can inspect it or reconnect with renewed credentials. Create a new workspace explicitly when you intend to replace it.

Handle request failures

With SDK 0.1.1273, use error.status to classify a failed HTTP request. These failures retain the SDK’s request-error slug and SERVER category. Read error.context.responseProblem, when present, for canonical API classification such as validation-failed and VALIDATION, or authentication-required and AUTH. Replace the placeholder with the ID of a sandbox you can access.
sandbox-request-error.ts
Use error.status as the fallback when canonical problem metadata is absent. Malformed, truncated or unreadable response bodies may omit responseProblem. An HTTP failure can follow command dispatch. This SDK version surfaces command HTTP failures without automatically replaying the command, including responses with status 502, 503 or 504. A synchronous runCommand() result has no command ID or status lookup. After an uncertain failure, verify expected files, external effects or application state before retrying. If you cannot establish the outcome, leave it unknown and do not retry automatically. For work that needs status recovery, use startBackgroundCommand(). Keep the returned command ID and inspect it with getBackgroundCommand() or getBackgroundCommandOutput(). If the start response is lost before the ID is returned, inspect listBackgroundCommands() and the expected effects rather than blindly starting another command. The SDK can retry a connection-setup failure when the request has not been dispatched. A reset, broken pipe, lost response or timeout with an uncertain dispatch outcome does not authorize replay or workspace replacement. The SDK also does not replay a command because reading its response body failed. Keep the workspace ID. Use the background command ID when available, or verify synchronous effects before deciding to run the command again.

Migrate from the previous sandbox SDK

Deploy the canonical /sandboxes API before upgrading SDK consumers. This SDK requires that API contract, including the validated camelCase workspace metadata and command responses described in this guide. The API and SDK do not negotiate versions. A missing route or an incompatible response fails with a request or response-validation error. Before publishing the SDK, verify sandbox.checkReadiness(), Sandbox.capabilities() and sandbox.runCommand("pwd") against the deployed API in the target environment. Verify that close() preserves a persistent workspace by reconnecting with Sandbox.get(id). Keep the release blocked until these checks pass. Update callers to these names. This release removes the old names without aliases. createProjectScopedExecOptions() is removed. Set projectReference when creating the sandbox; commands use the sandbox scope and do not accept a per-command project reference. Replace legacy JavaScript options explicitly, because an unrecognized option does not configure the command timeout. SandboxDetails uses camelCase metadata fields, including shortId, createdAt, workspaceStorage and ttlMode. Command IDs remain opaque strings. Review cleanup calls when upgrading. close() detaches from existing and persistent workspaces. Use delete() when you intend to remove the sandbox and its files. Remove old server contracts only after every caller and runtime image uses the canonical API.