Skip to main content

SDK for Chalk sandboxes, containers, and volumes

Project description

Chalk Sandbox SDK

Python SDK for the Chalk Sandbox gRPC service. Create sandboxes, execute commands, and stream output over bidirectional gRPC streams.

Install

pip install grpcio protobuf

Quick start

from sandbox import SandboxClient

client = SandboxClient("localhost:50051")

# Create a sandbox from a pre-built image
sandbox = client.create(image="ubuntu:latest")

# Run a command
result = sandbox.exec("echo", "hello world")
print(result.stdout_text)  # "hello world"
print(result.exit_code)    # 0

# Clean up
sandbox.terminate()

Declarative images

Build custom container images with a fluent API instead of writing Dockerfiles. The image spec is serialized as protobuf and transmitted to the sandbox service, which builds and caches the image before starting the container.

from sandbox import SandboxClient
from image import Image

client = SandboxClient("localhost:50051")

# Build a data-science image declaratively
img = (
    Image.debian_slim()
    .pip_install(["pandas", "numpy", "scikit-learn"])
    .run_commands(
        "apt-get update && apt-get install -y git curl",
    )
    .workdir("/home/user/app")
    .env({"PYTHONDONTWRITEBYTECODE": "1"})
)

sandbox = client.create(image=img)
result = sandbox.exec("python", "-c", "import pandas; print(pandas.__version__)")
print(result.stdout_text)

Base images

# Arbitrary base image
img = Image.base("node:25-trixie-slim")

# Convenience: python + debian slim
img = Image.debian_slim()  # python:3.14-slim-trixie

# From an existing Dockerfile (contents are inlined, so you can chain more steps)
img = Image.from_dockerfile("Dockerfile").pip_install(["extra-dep"])

Build steps

img = (
    Image.debian_slim()
    # Install Python packages
    .pip_install(["requests", "flask"])

    # Install from a requirements.txt (read locally, inlined into the spec)
    .pip_install_from_requirements("requirements.txt")

    # Run shell commands (each becomes a Docker RUN layer)
    .run_commands(
        "apt-get update && apt-get install -y git",
        "mkdir -p /app/data",
    )

    # Add local files into the image
    .add_local_file("config.yaml", "/app/config.yaml")
    .add_local_file("entrypoint.sh", "/app/entrypoint.sh", mode=0o755)
    .add_local_dir("src", "/app/src")

    # Raw Dockerfile instructions
    .dockerfile_commands(["EXPOSE 8080", "HEALTHCHECK CMD curl -f http://localhost:8080/"])

    # Image-level configuration
    .workdir("/app")
    .env({"FLASK_APP": "app:create_app"})
    .entrypoint(["/app/entrypoint.sh"])
    .cmd(["serve"])
)

Immutable composition

Each builder method returns a new Image, so intermediate images can be shared:

base = Image.debian_slim().pip_install(["requests"])

# Two different images that share the same base
api_image = base.pip_install(["flask"]).workdir("/api")
worker_image = base.pip_install(["celery"]).workdir("/worker")

api_sandbox = client.create(image=api_image)
worker_sandbox = client.create(image=worker_image)

Connecting

from sandbox import SandboxClient
import grpc

# Insecure (local dev)
client = SandboxClient("localhost:50051")

# With TLS
creds = grpc.ssl_channel_credentials()
client = SandboxClient("sandbox.example.com:443", credentials=creds)

# As a context manager
with SandboxClient("localhost:50051") as client:
    ...

Sandbox lifecycle

# Create with resource limits
sandbox = client.create(
    image="ubuntu:latest",
    cpu="2",
    memory="4Gi",
    env={"DEBIAN_FRONTEND": "noninteractive"},
)

# List all sandboxes
for info in client.list():
    print(f"{info.id} {info.state} {info.name}")

# Get a handle to an existing sandbox by ID
sandbox = client.get(id="550e8400-e29b-41d4-a716-446655440000")

# Fetch info from server
print(sandbox.info.state)
sandbox.refresh()  # force re-fetch

# Terminate
sandbox.terminate()
sandbox.terminate(grace_period_seconds=30)

Executing commands

Run and wait

result = sandbox.exec("ls", "-la", "/tmp")
for line in result.stdout:
    print(line)
for line in result.stderr:
    print(f"ERR: {line}")
print(f"exit code: {result.exit_code}")

# Or get the full text at once
print(result.stdout_text)
print(result.stderr_text)

Stream output in real time

for event in sandbox.exec_stream("make", "build", workdir="/app"):
    if event.stdout:
        print(event.stdout, end="")
    if event.stderr:
        print(event.stderr, end="", file=sys.stderr)
    if event.is_exited:
        print(f"\nDone: exit code {event.exit_code}")

Interactive processes (stdin + signals)

process = sandbox.exec_start("bash")

process.write_stdin("echo hello\n")
process.write_stdin("exit\n")
process.close_stdin()

for event in process.output():
    if event.stdout:
        print(event.stdout, end="")

Send signals to running processes:

import signal

process = sandbox.exec_start("sleep", "300")
process.send_signal(signal.SIGTERM)
result = process.wait()

Options

All exec methods accept the same keyword arguments:

result = sandbox.exec(
    "python", "train.py",
    workdir="/app",                     # working directory
    timeout_secs=3600,                  # kill after 1 hour
    env={"CUDA_VISIBLE_DEVICES": "0"},  # environment variables
)

Examples

Clone a GitHub repo into a sandbox

from sandbox import SandboxClient

client = SandboxClient("localhost:50051")
sandbox = client.create(image="ubuntu:latest")

# Install git
sandbox.exec("apt-get", "update")
sandbox.exec("apt-get", "install", "-y", "git")

# Clone
result = sandbox.exec(
    "git", "clone", "https://github.com/chalk-ai/chalk.git", "/workspace/chalk"
)
if result.exit_code != 0:
    print(f"Clone failed: {result.stderr_text}")
else:
    # List what we got
    result = sandbox.exec("ls", "-la", "/workspace/chalk")
    for line in result.stdout:
        print(line)

Spawn an OpenCode agent in a sandbox

OpenCode is a terminal-based AI coding agent. You can run it inside a sandbox to give it an isolated environment to work in.

from sandbox import SandboxClient

client = SandboxClient("localhost:50051")
sandbox = client.create(
    image="ubuntu:latest",
    cpu="2",
    memory="4Gi",
    env={
        "ANTHROPIC_API_KEY": "sk-ant-...",
    },
)

# Install dependencies
sandbox.exec("apt-get", "update")
sandbox.exec("apt-get", "install", "-y", "git", "curl", "build-essential")

# Install Go (opencode is a Go binary)
sandbox.exec("bash", "-c", "curl -fsSL https://go.dev/dl/go1.26.3.linux-amd64.tar.gz | tar -C /usr/local -xz")
sandbox.exec("bash", "-c", "echo 'export PATH=$PATH:/usr/local/go/bin:/root/go/bin' >> /root/.bashrc")

# Install opencode
sandbox.exec("bash", "-c", "export PATH=$PATH:/usr/local/go/bin:/root/go/bin && go install github.com/opencode-ai/opencode@latest")

# Clone a repo to work on
sandbox.exec("git", "clone", "https://github.com/your-org/your-repo.git", "/workspace/repo")

# Run opencode non-interactively with a prompt
result = sandbox.exec(
    "bash", "-c",
    "export PATH=$PATH:/usr/local/go/bin:/root/go/bin && cd /workspace/repo && opencode -p 'fix the failing tests in pkg/auth'",
    timeout_secs=600,
)
print(result.stdout_text)

# Or run it interactively and feed it commands
process = sandbox.exec_start(
    "bash", "-c",
    "export PATH=$PATH:/usr/local/go/bin:/root/go/bin && cd /workspace/repo && opencode",
)

# Stream its output
for event in process.output():
    if event.stdout:
        print(event.stdout, end="")
    if event.stderr:
        print(event.stderr, end="", file=sys.stderr)
    if event.is_exited:
        break

Long-running build with real-time output

sandbox = client.create(image="node:25-trixie-slim")

sandbox.exec("git", "clone", "https://github.com/your-org/frontend.git", "/app")
sandbox.exec("npm", "install", workdir="/app")

# Stream the build output as it happens
for event in sandbox.exec_stream("npm", "run", "build", workdir="/app"):
    if event.stdout:
        print(event.stdout, end="")
    if event.stderr:
        print(event.stderr, end="", file=sys.stderr)
    if event.is_exited and event.exit_code != 0:
        print(f"Build failed with exit code {event.exit_code}")

sandbox.terminate()

CLI tools

sandbox_exec.py - Run a command

python sandbox_exec.py --target localhost:50051 --sandbox-id <id> --exec "ls -la"

sandbox_stdout.py - Interactive shell

echo "echo hello" | python sandbox_stdout.py --target localhost:50051 --sandbox-id <id> --exec "bash"

Regenerating proto stubs

If the proto definition changes, regenerate the Python stubs:

pip install grpcio-tools
./generate.sh

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

chalkcompute-1.5.15.tar.gz (193.5 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

chalkcompute-1.5.15-cp314-cp314-manylinux_2_28_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.28+ x86-64

chalkcompute-1.5.15-cp314-cp314-macosx_11_0_arm64.whl (2.7 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

chalkcompute-1.5.15-cp313-cp313-manylinux_2_28_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.28+ x86-64

chalkcompute-1.5.15-cp313-cp313-macosx_11_0_arm64.whl (2.7 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

chalkcompute-1.5.15-cp312-cp312-manylinux_2_28_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.28+ x86-64

chalkcompute-1.5.15-cp312-cp312-macosx_11_0_arm64.whl (2.7 MB view details)

Uploaded CPython 3.12macOS 11.0+ ARM64

chalkcompute-1.5.15-cp311-cp311-manylinux_2_28_x86_64.whl (2.9 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.28+ x86-64

chalkcompute-1.5.15-cp311-cp311-macosx_11_0_arm64.whl (2.7 MB view details)

Uploaded CPython 3.11macOS 11.0+ ARM64

File details

Details for the file chalkcompute-1.5.15.tar.gz.

File metadata

  • Download URL: chalkcompute-1.5.15.tar.gz
  • Upload date:
  • Size: 193.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for chalkcompute-1.5.15.tar.gz
Algorithm Hash digest
SHA256 ce5da38025bcd75b4f47641904cdf9a23371f34e3cf07ea47c1e71b7847bc499
MD5 108ffe114639b734ab94f38caa0e1ad4
BLAKE2b-256 0a762ca0e5087fc824f55b47aa72653ada26b97ee3c2e7297f02722e663ffd64

See more details on using hashes here.

Provenance

The following attestation bundles were made for chalkcompute-1.5.15.tar.gz:

Publisher: release.yml on chalk-ai/chalk-sandbox-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file chalkcompute-1.5.15-cp314-cp314-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for chalkcompute-1.5.15-cp314-cp314-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 05df1959b0138182bc87338d7aa77752bcc526b5b1f1149eeb7aa870b5701f22
MD5 b89797319f383d940e2054e17135654d
BLAKE2b-256 3480ba2770baca350df40487e1c5ee7d282938cc94e638ea808908f828fde09c

See more details on using hashes here.

Provenance

The following attestation bundles were made for chalkcompute-1.5.15-cp314-cp314-manylinux_2_28_x86_64.whl:

Publisher: release.yml on chalk-ai/chalk-sandbox-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file chalkcompute-1.5.15-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for chalkcompute-1.5.15-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 064e7edd93362a62ef4c5bb6ce9c4ff7bbf27fa9ce0b1d866d100c77204e82f4
MD5 0d2fc5dfda242643e80590f4c01ed8cf
BLAKE2b-256 62d81ccde830e0edc2c583fbcd7c56e92f75a6e29a2afb280bd934f1faf2b54d

See more details on using hashes here.

Provenance

The following attestation bundles were made for chalkcompute-1.5.15-cp314-cp314-macosx_11_0_arm64.whl:

Publisher: release.yml on chalk-ai/chalk-sandbox-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file chalkcompute-1.5.15-cp313-cp313-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for chalkcompute-1.5.15-cp313-cp313-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e33567e5d164aad522a7a469315b715046f88795de2636b566316bac56bfc660
MD5 856a5387c53f92efac13df2b09e9bd3d
BLAKE2b-256 131ef05c1a62402ff47269d84ca15ee4a903484b8509f253b67452695708cd0c

See more details on using hashes here.

Provenance

The following attestation bundles were made for chalkcompute-1.5.15-cp313-cp313-manylinux_2_28_x86_64.whl:

Publisher: release.yml on chalk-ai/chalk-sandbox-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file chalkcompute-1.5.15-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for chalkcompute-1.5.15-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 2a878c9e216af47759c4af5c6458cd98012385412439991177151afd60fa8509
MD5 9acf25f894fcf68d9a73742aae7dd519
BLAKE2b-256 dcc2a0b3af665ddf71ae9878834d9c93cbb913d23316b4e3adbecbc2fee2529a

See more details on using hashes here.

Provenance

The following attestation bundles were made for chalkcompute-1.5.15-cp313-cp313-macosx_11_0_arm64.whl:

Publisher: release.yml on chalk-ai/chalk-sandbox-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file chalkcompute-1.5.15-cp312-cp312-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for chalkcompute-1.5.15-cp312-cp312-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 c7c9811d735693ffbe99bd5ce47491481773a5fedcf6d16aed5eeafae159d500
MD5 1c95253fee422c599104906657e5a895
BLAKE2b-256 2453a619fdd7b06339d722d8fcfc3897f65b922cf6fb47907c0eaaa52b4e7a38

See more details on using hashes here.

Provenance

The following attestation bundles were made for chalkcompute-1.5.15-cp312-cp312-manylinux_2_28_x86_64.whl:

Publisher: release.yml on chalk-ai/chalk-sandbox-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file chalkcompute-1.5.15-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for chalkcompute-1.5.15-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 882573b87432ccde82e528dbae3e8f4594e8a32f6e52529f2de161899dc92ef3
MD5 2c32fe22022b67db370a2d5f99ca44b3
BLAKE2b-256 99817a2531b48fdbcbe27612e86bf8e66c29ae56a43adbcc17bfb40a3bd33ce7

See more details on using hashes here.

Provenance

The following attestation bundles were made for chalkcompute-1.5.15-cp312-cp312-macosx_11_0_arm64.whl:

Publisher: release.yml on chalk-ai/chalk-sandbox-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file chalkcompute-1.5.15-cp311-cp311-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for chalkcompute-1.5.15-cp311-cp311-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 aeb0a68a9df5dc483330927395e908bae702e624813750863cc49d7fbe83dda9
MD5 110567b9d307bae7d62589d4da783a84
BLAKE2b-256 efda53946dfcad10e069f016207871dde0e6ec39390af60e5f6cf46466cdd3ca

See more details on using hashes here.

Provenance

The following attestation bundles were made for chalkcompute-1.5.15-cp311-cp311-manylinux_2_28_x86_64.whl:

Publisher: release.yml on chalk-ai/chalk-sandbox-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file chalkcompute-1.5.15-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for chalkcompute-1.5.15-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 08e566069adab4f650d2980c302bbc9aa68cc6d479b6d85331e7f249819128ba
MD5 ef17bbecb84804fd8b45b91ed85c2695
BLAKE2b-256 42a1f467d1971c8239dfafb14dd2ed2ba8b88198fe80acbb26dab72c05ae7c9e

See more details on using hashes here.

Provenance

The following attestation bundles were made for chalkcompute-1.5.15-cp311-cp311-macosx_11_0_arm64.whl:

Publisher: release.yml on chalk-ai/chalk-sandbox-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page