Installation
npm install @opencomputer/sdk
import { Sandbox } from "@opencomputer/sdk" ;
import { Image } from "@opencomputer/sdk/dist/image.js" ;
import { Snapshots } from "@opencomputer/sdk/dist/snapshot.js" ;
Sandbox
Static Methods
Sandbox.create(opts?): Promise<Sandbox>
Create a new sandbox.
Parameter Type Default Description templatestring "base"Template name timeoutnumber 300Idle timeout in seconds apiKeystring env var API key apiUrlstring env var API URL envsRecord<string, string> — Environment variables metadataRecord<string, string> — Arbitrary metadata cpuCountnumber — CPU cores (max 4) memoryMBnumber — Memory in MB (max 2048) imageImage — Declarative image definition (see Image ) snapshotstring — Name of a pre-built snapshot onBuildLog(log: string) => void— Build log callback (when using image)
const sandbox = await Sandbox . create ({ template: "my-stack" , timeout: 600 });
Sandbox.connect(sandboxId, opts?): Promise<Sandbox>
Connect to an existing sandbox.
Parameter Type Description sandboxIdstring Sandbox ID apiKeystring API key (optional) apiUrlstring API URL (optional)
const sandbox = await Sandbox . connect ( "sb-abc123" );
Sandbox.createFromCheckpoint(checkpointId, opts?): Promise<Sandbox>
Create a new sandbox from a checkpoint.
Parameter Type Default Description checkpointIdstring — Checkpoint ID (required ) timeoutnumber 300Idle timeout apiKeystring env var API key apiUrlstring env var API URL
const forked = await Sandbox . createFromCheckpoint ( "cp-abc123" );
Sandbox.createCheckpointPatch(checkpointId, opts): Promise<PatchResult>
Create a patch for a checkpoint.
Parameter Type Required Description checkpointIdstring Yes Target checkpoint scriptstring Yes Bash script descriptionstring No Description apiKeystring No API key apiUrlstring No API URL
const result = await Sandbox . createCheckpointPatch ( "cp-abc" , { script: "apt install -y curl" });
Sandbox.listCheckpointPatches(checkpointId, opts?): Promise<PatchInfo[]>
const patches = await Sandbox . listCheckpointPatches ( "cp-abc" );
Sandbox.deleteCheckpointPatch(checkpointId, patchId, opts?): Promise<void>
await Sandbox . deleteCheckpointPatch ( "cp-abc" , "pa-xyz" );
Instance Methods
sandbox.kill(): Promise<void>
Terminate the sandbox.
sandbox.isRunning(): Promise<boolean>
Check if the sandbox is running.
sandbox.hibernate(): Promise<void>
Snapshot VM state and stop. No compute cost while hibernated.
sandbox.wake(opts?): Promise<void>
Resume a hibernated sandbox.
Parameter Type Default Description timeoutnumber 300Idle timeout after wake
sandbox.setTimeout(timeout): Promise<void>
Update the idle timeout.
Parameter Type Description timeoutnumber New timeout in seconds
sandbox.createCheckpoint(name): Promise<CheckpointInfo>
Create a named checkpoint.
sandbox.listCheckpoints(): Promise<CheckpointInfo[]>
List all checkpoints for the sandbox.
sandbox.restoreCheckpoint(checkpointId): Promise<void>
Revert in-place to a checkpoint.
sandbox.deleteCheckpoint(checkpointId): Promise<void>
Delete a checkpoint.
sandbox.createPreviewURL(opts): Promise<PreviewURLResult>
Parameter Type Required Description portnumber Yes Container port (1–65535) domainstring No Custom domain authConfigRecord<string, unknown> No Auth configuration
sandbox.listPreviewURLs(): Promise<PreviewURLResult[]>
sandbox.deletePreviewURL(port): Promise<void>
Properties
Property Type Description sandboxIdstring Sandbox ID (readonly) statusstring Current status (readonly) agentAgent Agent sessions execExec Command execution filesFilesystem File operations ptyPty Terminal sessions commandsExec Deprecated — alias for exec
Types
SandboxOpts
interface SandboxOpts {
template ?: string ;
timeout ?: number ;
apiKey ?: string ;
apiUrl ?: string ;
envs ?: Record < string , string >;
metadata ?: Record < string , string >;
cpuCount ?: number ;
memoryMB ?: number ;
image ?: Image ;
snapshot ?: string ;
onBuildLog ?: ( log : string ) => void ;
}
CheckpointInfo
interface CheckpointInfo {
id : string ;
sandboxId : string ;
orgId : string ;
name : string ;
sandboxConfig : object ;
status : string ; // "processing" | "ready" | "failed"
sizeBytes : number ;
createdAt : string ;
}
PatchInfo
interface PatchInfo {
id : string ;
checkpointId : string ;
sequence : number ;
script : string ;
description : string ;
strategy : string ; // "on_wake"
createdAt : string ;
}
PatchResult
interface PatchResult {
patch : PatchInfo ;
}
PreviewURLResult
interface PreviewURLResult {
id : string ;
sandboxId : string ;
orgId : string ;
hostname : string ;
customHostname ?: string ;
port : number ;
cfHostnameId ?: string ;
sslStatus : string ;
authConfig ?: object ;
createdAt : string ;
}
Agent
Accessed via sandbox.agent.
sandbox.agent.start(opts?): Promise<AgentSession>
Start an agent session.
Parameter Type Description promptstring Initial prompt modelstring Claude model systemPromptstring System prompt allowedToolsstring[] Restrict tools permissionModestring Permission mode maxTurnsnumber Max turns (default: 50) cwdstring Working directory mcpServersRecord<string, McpServerConfig> MCP servers resumestring Resume session ID onEvent(event: AgentEvent) => void Event callback onError(data: string) => void Stderr callback onExit(exitCode: number) => void Exit callback onScrollbackEnd() => void Scrollback done callback
const session = await sandbox . agent . start ({
prompt: "Build a todo app" ,
onEvent : ( e ) => console . log ( e . type ),
});
sandbox.agent.attach(sessionId, opts?): Promise<AgentSession>
Reconnect to a running agent session. Accepts onEvent, onError, onExit, onScrollbackEnd.
sandbox.agent.list(): Promise<AgentSessionInfo[]>
List all agent sessions.
AgentSession
Member Type Description sessionIdstring Session ID donePromise<number> Resolves with exit code sendPrompt(text)method Send follow-up prompt interrupt()method Interrupt current turn configure(config)method Update agent configuration kill(signal?)Promise<void> Kill agent process close()method Close WebSocket
Types
AgentEvent
interface AgentEvent {
type : string ;
[ key : string ] : unknown ;
}
McpServerConfig
interface McpServerConfig {
command : string ;
args ?: string [];
env ?: Record < string , string >;
}
Exec
Accessed via sandbox.exec.
sandbox.exec.run(command, opts?): Promise<ProcessResult>
Run a command synchronously.
Parameter Type Default Description commandstring — Shell command (required ) timeoutnumber 60Timeout in seconds envRecord<string, string> — Environment variables cwdstring — Working directory
const result = await sandbox . exec . run ( "npm test" , { cwd: "/app" });
sandbox.exec.start(command, opts?): Promise<ExecSession>
Start a long-running command with streaming.
Parameter Type Description commandstring Command (required ) argsstring[] Arguments envRecord<string, string> Environment variables cwdstring Working directory timeoutnumber Timeout in seconds maxRunAfterDisconnectnumber Seconds to keep running after disconnect onStdout(data: Uint8Array) => void Stdout callback onStderr(data: Uint8Array) => void Stderr callback onExit(exitCode: number) => void Exit callback
const session = await sandbox . exec . start ( "node server.js" , {
onStdout : ( data ) => process . stdout . write ( data ),
});
sandbox.exec.attach(sessionId, opts?): Promise<ExecSession>
Reconnect to a running exec session.
Parameter Type Description sessionIdstring Session ID (required ) onStdout(data: Uint8Array) => void Stdout callback onStderr(data: Uint8Array) => void Stderr callback onExit(exitCode: number) => void Exit callback onScrollbackEnd() => void Scrollback replay done
sandbox.exec.list(): Promise<ExecSessionInfo[]>
List all exec sessions.
sandbox.exec.kill(sessionId, signal?): Promise<void>
Kill an exec session. Default signal: 9 (SIGKILL).
ExecSession
Member Type Description sessionIdstring Session ID donePromise<number> Resolves with exit code sendStdin(data)method Send input (string or Uint8Array) kill(signal?)Promise<void> Kill process close()method Close WebSocket
Types
ProcessResult
interface ProcessResult {
exitCode : number ;
stdout : string ;
stderr : string ;
}
ExecSessionInfo
interface ExecSessionInfo {
sessionID : string ;
sandboxID : string ;
command : string ;
args : string [];
running : boolean ;
exitCode ?: number ;
startedAt : string ;
attachedClients : number ;
}
Filesystem
Accessed via sandbox.files.
sandbox.files.read(path): Promise<string>
Read a file as a UTF-8 string.
sandbox.files.readBytes(path): Promise<Uint8Array>
Read a file as raw bytes.
sandbox.files.write(path, content): Promise<void>
Write content to a file. Accepts string or Uint8Array.
sandbox.files.list(path?): Promise<EntryInfo[]>
List directory contents. Default path: "/".
sandbox.files.makeDir(path): Promise<void>
Create a directory (recursive).
sandbox.files.remove(path): Promise<void>
Delete a file or directory.
sandbox.files.exists(path): Promise<boolean>
Check if a path exists. Client-side wrapper — attempts a read and returns false on error.
Types
EntryInfo
interface EntryInfo {
name : string ;
isDir : boolean ;
path : string ;
size : number ;
}
Pty
Accessed via sandbox.pty.
sandbox.pty.create(opts?): Promise<PtySession>
Create an interactive terminal session.
Parameter Type Default Description colsnumber 80Terminal columns rowsnumber 24Terminal rows onOutput(data: Uint8Array) => void — Output callback
PtySession
Member Type Description sessionIdstring Session ID send(data)method Send input (string or Uint8Array) close()method Close the PTY
Image
Fluent, immutable builder for declarative sandbox images. Each method returns a new Image instance.
Image.base(): Image
Start from the default OpenSandbox environment (Ubuntu 22.04, Python, Node.js, build tools).
import { Image } from "@opencomputer/sdk" ;
const image = Image . base ()
. aptInstall ([ 'curl' , 'jq' ])
. pipInstall ([ 'requests' , 'pandas' ])
. env ({ PROJECT_ROOT: '/workspace' })
. workdir ( '/workspace' );
Builder Methods
Method Parameters Description aptInstall(packages)string[]Install system packages via apt-get pipInstall(packages)string[]Install Python packages via pip runCommands(...cmds)string[]Run shell commands during build env(vars)Record<string, string>Set environment variables workdir(path)stringSet default working directory addFile(remotePath, content)string, stringEmbed a file with inline content addLocalFile(localPath, remotePath)string, stringRead a local file into the image addLocalDir(localPath, remotePath)string, stringRead a local directory into the image
image.toJSON(): ImageManifest
Returns the image manifest as a plain object.
image.cacheKey(): string
Computes a deterministic SHA-256 hash of the manifest for cache lookups.
Snapshots
Standalone class — not a property on Sandbox.
new Snapshots(opts?)
import { Snapshots } from "@opencomputer/sdk" ;
const snapshots = new Snapshots ();
// or with explicit config:
const snapshots = new Snapshots ({ apiKey: "..." , apiUrl: "..." });
Parameter Type Description apiKeystring API key (falls back to OPENCOMPUTER_API_KEY env var) apiUrlstring API URL (falls back to OPENCOMPUTER_API_URL env var)
snapshots.create(opts): Promise<SnapshotInfo>
Create a pre-built snapshot from a declarative image.
Parameter Type Required Description namestring Yes Unique snapshot name imageImage Yes Declarative image definition onBuildLogs(log: string) => voidNo Build log streaming callback
snapshots.list(): Promise<SnapshotInfo[]>
List all snapshots for the current organization.
snapshots.get(name): Promise<SnapshotInfo>
Get a snapshot by name.
snapshots.delete(name): Promise<void>
Delete a snapshot. Existing sandboxes created from it are not affected.
Types
SnapshotInfo
interface SnapshotInfo {
id : string ;
name : string ;
status : string ; // "building" | "ready" | "failed"
contentHash : string ;
checkpointId : string ;
manifest : object ;
createdAt : string ;
lastUsedAt : string ;
}
Secret Stores
SecretStore.create(opts)
Create a new secret store.
import { SecretStore } from '@opencomputer/sdk' ;
const store = await SecretStore . create ({
name: 'my-agent-secrets' ,
egressAllowlist: [ 'api.anthropic.com' ],
});
opts
CreateSecretStoreOpts
required
Store name (unique per organization).
Allowed egress hosts (e.g. ["api.anthropic.com"]).
Returns: Promise<SecretStoreInfo>
SecretStore.list(opts?)
List all secret stores.
const stores = await SecretStore . list ();
Returns: Promise<SecretStoreInfo[]>
SecretStore.get(storeId, opts?)
Get a secret store by ID.
const store = await SecretStore . get ( 'store-uuid' );
UUID of the secret store.
Returns: Promise<SecretStoreInfo>
SecretStore.update(storeId, opts)
Partial updates — only the fields you pass are changed.
const updated = await SecretStore . update ( 'store-uuid' , {
name: 'new-name' ,
egressAllowlist: [ 'api.anthropic.com' , '*.openai.com' ],
});
UUID of the store to update.
opts
UpdateSecretStoreOpts
required
New allowed egress hosts.
Returns: Promise<SecretStoreInfo>
SecretStore.delete(storeId, opts?)
Deletes the store and all its secrets. Running sandboxes are not affected.
await SecretStore . delete ( 'store-uuid' );
Returns: Promise<void>
SecretStore.setSecret(storeId, name, value, opts?)
Set a secret in a store. Secrets are encrypted at rest. The value is never returned by the API.
await SecretStore . setSecret ( 'store-uuid' , 'ANTHROPIC_API_KEY' , 'sk-ant-...' );
Optionally restrict which hosts can receive this secret:
await SecretStore . setSecret ( 'store-uuid' , 'ANTHROPIC_API_KEY' , 'sk-ant-...' , {
allowedHosts: [ 'api.anthropic.com' ],
});
UUID of the secret store.
Secret name (used as the env var name in sandboxes).
Secret value (encrypted at rest, never returned by API).
Returns: Promise<void>
SecretStore.listSecrets(storeId, opts?)
Returns secret metadata only. Values are never exposed.
const entries = await SecretStore . listSecrets ( 'store-uuid' );
// [{ name: 'ANTHROPIC_API_KEY', allowedHosts: ['api.anthropic.com'], ... }, ...]
Returns: Promise<SecretEntryInfo[]>
SecretStore.deleteSecret(storeId, name, opts?)
await SecretStore . deleteSecret ( 'store-uuid' , 'DATABASE_URL' );
Returns: Promise<void>
Creating a Sandbox with a Secret Store
Pass the secretStore option to Sandbox.create() to inject the store’s secrets:
import { Sandbox } from '@opencomputer/sdk' ;
const sandbox = await Sandbox . create ({
secretStore: 'my-agent-secrets' ,
timeout: 600 ,
});
// Secrets are available as sealed env vars
const result = await sandbox . commands . run ( 'echo $ANTHROPIC_API_KEY' );
// stdout: "osb_sealed_abc123..." (sealed, not the real key)
// But outbound HTTPS requests get the real value substituted by the proxy
const apiResult = await sandbox . commands . run (
'curl -s https://api.anthropic.com/v1/messages -H "x-api-key: $ANTHROPIC_API_KEY" ...'
);
// The proxy replaces the sealed token with the real key before it hits Anthropic
Types
SecretStoreInfo
Property Type Description idstringStore UUID orgIdstringOrganization UUID namestringStore name egressAllowliststring[]Allowed egress hosts createdAtstringISO 8601 timestamp updatedAtstringISO 8601 timestamp
SecretEntryInfo
Property Type Description idstringEntry UUID storeIdstringParent store UUID namestringSecret name (env var name) allowedHostsstring[]Host restrictions for this secret createdAtstringISO 8601 timestamp updatedAtstringISO 8601 timestamp