Skip to main content
Templates provide a code-first approach to defining sandbox environments. Instead of configuring images manually, you define them programmatically using the SDK. The system supports two workflows:
  1. Declarative images — build images with varying dependencies on demand when creating sandboxes
  2. Pre-built snapshots — create and register ready-to-use snapshots that can be shared across multiple sandboxes

Declarative image building

Build images on-the-fly when creating sandboxes. Ideal for iterating quickly without creating separate snapshots. Declarative images are cached by content hash — identical manifests produce the same image. Subsequent runs reuse the cached image instantly.
from opencomputer import Sandbox, Image

# Define an image with packages, env vars, and files
image = (
    Image.base()
    .apt_install(["curl", "jq"])
    .pip_install(["requests", "pandas"])
    .env({"PROJECT_ROOT": "/workspace"})
    .workdir("/workspace")
)

# Create a sandbox — the image is built on first run, cached after
sandbox = await Sandbox.create(
    image=image,
    timeout=300,
    on_build_log=lambda log: print(f"build: {log}"),
)

result = await sandbox.commands.run("which curl")
print(result.exit_code)  # 0

Sandbox.create(image=..., on_build_log=...)

When you pass an image to Sandbox.create(), the server:
  1. Hashes the image manifest to compute a cache key
  2. If cached, creates the sandbox from the existing checkpoint instantly
  3. If not cached, boots a build sandbox, executes each step, checkpoints the result, then creates your sandbox from it
image
Image
A declarative image definition built with the Image builder.
on_build_log
Callable[[str], None]
Callback for streaming build log messages via SSE. Receives step-by-step progress updates during image building.

Creating pre-built snapshots

Create named snapshots that persist permanently and can be shared across sandboxes. Snapshots are visible in the dashboard and don’t need to be rebuilt.
from opencomputer import Image, Snapshots

snapshots = Snapshots()

# Define the image
image = (
    Image.base()
    .apt_install(["python3-pip"])
    .pip_install(["pandas", "numpy", "scikit-learn"])
    .workdir("/workspace")
)

# Create a named snapshot with build log streaming
await snapshots.create(
    name="data-science",
    image=image,
    on_build_logs=lambda log: print(f"build: {log}"),
)

# Now create sandboxes from the snapshot — instant, no build step
sandbox = await Sandbox.create(snapshot="data-science")

Snapshots(api_key=..., api_url=...)

api_key
str
API key. Falls back to OPENCOMPUTER_API_KEY env var.
api_url
str
API base URL. Falls back to OPENCOMPUTER_API_URL env var.

await snapshots.create(name, image, on_build_logs=None)

Creates a pre-built snapshot from a declarative image.
name
str
required
Unique name for this snapshot.
image
Image
required
Declarative image definition.
on_build_logs
Callable[[str], None]
Callback for streaming build log messages.
Returns: dict with snapshot info (id, name, status, etc.)

await snapshots.list()

Returns all named snapshots for the current organization.
snapshot_list = await snapshots.list()
for s in snapshot_list:
    print(f"{s['name']}{s['status']}")
Returns: list[dict]

await snapshots.get(name)

Gets a snapshot by name.
snapshot = await snapshots.get("data-science")
print(snapshot["status"])  # "ready"
name
str
required
Snapshot name.
Returns: dict

await snapshots.delete(name)

Deletes a named snapshot. Existing sandboxes created from it are not affected.
await snapshots.delete("data-science")
name
str
required
Snapshot name to delete.
Returns: None

Sandbox.create(snapshot=...)

Create a sandbox from a pre-built snapshot by name.
sandbox = await Sandbox.create(snapshot="data-science")
snapshot
str
Name of a pre-built snapshot to create the sandbox from.
Returns: Sandbox

Image configuration

The Image class provides a fluent, immutable API for defining sandbox environments. Each method returns a new Image instance — the original is never modified.

Image.base()

Creates a new image starting from the default OpenSandbox environment (Ubuntu 22.04 with Python, Node.js, build tools, and common utilities).
image = Image.base()

image.apt_install(packages)

Install system packages via apt-get.
image = Image.base().apt_install(["curl", "git", "jq"])
packages
list[str]
required
List of apt package names to install.

image.pip_install(packages)

Install Python packages via pip.
image = Image.base().pip_install(["requests", "pandas", "numpy"])
packages
list[str]
required
List of pip package names to install.

image.run_commands(*commands)

Run one or more shell commands during image build.
image = Image.base().run_commands(
    "mkdir -p /workspace/project",
    "echo 'Hello' > /workspace/welcome.txt",
)
commands
str (variadic)
required
Shell commands to execute sequentially.

image.env(vars)

Set environment variables. Written to /etc/environment so they’re available in all sessions.
image = Image.base().env({
    "PROJECT_ROOT": "/workspace",
    "NODE_ENV": "production",
})
vars
dict[str, str]
required
Key-value pairs of environment variables.

image.workdir(path)

Set the default working directory.
image = Image.base().workdir("/workspace/project")
path
str
required
Absolute path for the working directory.

image.add_file(remote_path, content)

Embed a file with inline content into the image.
image = (
    Image.base()
    .add_file("/workspace/config.json", '{"env": "production"}')
    .add_file("/workspace/setup.sh", "#!/bin/bash\necho 'Ready!'")
)
remote_path
str
required
Absolute path inside the sandbox.
content
str
required
String content of the file.

image.add_local_file(local_path, remote_path)

Read a file from the local machine and embed it into the image.
image = Image.base().add_local_file("package.json", "/workspace/package.json")
local_path
str
required
Path to the file on the local machine.
remote_path
str
required
Absolute path inside the sandbox.

image.add_local_dir(local_path, remote_path)

Recursively read a local directory and embed all files into the image.
image = Image.base().add_local_dir("src", "/workspace/src")
local_path
str
required
Path to the directory on the local machine.
remote_path
str
required
Absolute path inside the sandbox where the directory will be created.

image.to_dict()

Returns the image manifest as a plain dict. Returns: dict

image.cache_key()

Computes a deterministic SHA-256 hash of the manifest for cache lookups. Returns: str

Snapshot info fields

FieldTypeDescription
idstrUnique snapshot identifier
namestrSnapshot name
statusstr"building", "ready", or "failed"
contentHashstrSHA-256 hash of the image manifest
checkpointIdstrLinked checkpoint ID
manifestdictThe declarative image manifest
createdAtstrISO 8601 creation timestamp
lastUsedAtstrISO 8601 last usage timestamp

Complete example

import asyncio
from opencomputer import Sandbox, Image, Snapshots

async def main():
    # ── Pattern 1: On-demand image ──
    dev_image = (
        Image.base()
        .apt_install(["curl", "jq"])
        .pip_install(["requests"])
        .add_file("/workspace/config.json", '{"debug": true}')
        .env({"APP_ENV": "development"})
        .workdir("/workspace")
    )

    sandbox = await Sandbox.create(
        image=dev_image,
        on_build_log=lambda log: print(f"build: {log}"),
    )

    await sandbox.commands.run("curl --version")
    await sandbox.kill()

    # ── Pattern 2: Pre-built snapshot ──
    snapshots = Snapshots()

    prod_image = (
        Image.base()
        .apt_install(["python3-pip", "git"])
        .pip_install(["pandas", "numpy", "scikit-learn"])
        .run_commands("mkdir -p /workspace/data")
        .env({"APP_ENV": "production"})
        .workdir("/workspace")
    )

    await snapshots.create(
        name="ml-env",
        image=prod_image,
        on_build_logs=lambda log: print(f"build: {log}"),
    )

    # Instant — no build, just boot from snapshot
    ml_sandbox = await Sandbox.create(snapshot="ml-env")
    await ml_sandbox.commands.run(
        'python3 -c "import pandas; print(pandas.__version__)"'
    )
    await ml_sandbox.kill()

    # Cleanup
    await snapshots.delete("ml-env")

asyncio.run(main())