Skip to main content

Runbox Python Client

Official Python client for Runbox - a fast, secure API for running code in isolated containers.

PyPI version CI License: MIT

Installation

pip install runbox-py

Quick Start

from runbox_client import Client

# Create a client
client = Client(
    url="http://localhost:8080",
    api_key="your-api-key"
)

# Step 1: Set up a container and get environment info
setup = client.setup(
    identifier="my-session",
    language="python"
)

print(setup.container_id)  # => "runbox-my-session-python"
print(setup.environment_snapshot.runtime_version)  # => "3.11.6"
print(setup.environment_snapshot.packages["requests"])  # => "2.31.0"

# Step 2: Run code in the container
result = client.run(
    container_id=setup.container_id,
    files=[{"path": "main.py", "content": "print('Hello!')"}],
    run_command="python main.py"
)

print(result.stdout)  # => "Hello!\n"
print(result.success)  # => True

Configuration

Using Environment Variables

export RUNBOX_URL=http://localhost:8080
export RUNBOX_API_KEY=your-api-key
from runbox_client import Client

# Will use environment variables
client = Client()

Explicit Configuration

client = Client(
    url="http://localhost:8080",
    api_key="your-api-key",
    timeout=120  # HTTP timeout in seconds
)

Usage

Setting Up a Container

setup = client.setup(
    identifier="session-123",
    language="python",
    env={"API_KEY": "secret"},      # Optional: environment variables
    memory="512m",                   # Optional: memory limit
    network_allow=["api.stripe.com"] # Optional: allowed network destinations
)

# Access environment information
print(setup.container_id)  # => "runbox-session-123-python"
print(setup.cached)        # => False (True if container was reused)

env = setup.environment_snapshot
print(env.os_name)          # => "debian"
print(env.os_version)       # => "12"
print(env.runtime_name)     # => "python"
print(env.runtime_version)  # => "3.11.6"
print(env.packages)         # => {"pip": "23.0.1", "requests": "2.31.0", ...}

Running Code

result = client.run(
    container_id="runbox-session-123-python",
    files=[{"path": "main.py", "content": "print('Hello!')"}],
    run_command="python main.py",
    env={"DEBUG": "true"},  # Optional: runtime environment variables
    timeout=30              # Optional: execution timeout in seconds
)

print(result.success)          # => True
print(result.exit_code)        # => 0
print(result.stdout)           # => "Hello!\n"
print(result.stderr)           # => ""
print(result.execution_time_ms) # => 42
print(result.timed_out)        # => False

Installing Dependencies On-The-Fly

Install new dependencies before running code:

# Python example
result = client.run(
    container_id=container_id,
    files=[{"path": "main.py", "content": "import requests; print(requests.__version__)"}],
    run_command="python main.py",
    new_dependencies=["requests==2.31.0", "pytest"]
)

print(result.packages)  # => {"pip": "23.0.1", "requests": "2.31.0", "pytest": "7.4.0", ...}

# Ruby example
result = client.run(
    container_id=container_id,
    files=[{"path": "main.rb", "content": "require 'rake'; puts Rake::VERSION"}],
    run_command="ruby main.rb",
    new_dependencies=["rake", "rspec"]
)

# Shell example (uses apk)
result = client.run(
    container_id=container_id,
    files=[{"path": "script.sh", "content": "#!/bin/sh\ncurl --version"}],
    run_command="sh script.sh",
    new_dependencies=["curl", "jq", "git"]
)

Note: The packages field is only included in the result when new_dependencies are provided.

Async Support

import asyncio
from runbox_client import AsyncClient

async def main():
    async with AsyncClient(url="http://localhost:8080", api_key="your-api-key") as client:
        # Setup container
        setup = await client.setup(
            identifier="session-123",
            language="python"
        )
        
        # Run code
        result = await client.run(
            container_id=setup.container_id,
            files=[{"path": "main.py", "content": "print('Hello!')"}],
            run_command="python main.py"
        )
        
        print(result.stdout)

asyncio.run(main())

Cleanup Containers

deleted = client.delete_containers("session-123")
print(deleted)  # => ["runbox-session-123-python"]

Check Health

health = client.health()
print(health.status)  # => "healthy"
print(health.version) # => "1.0.0"

API Reference

client.setup(identifier, language, **options)

Set up a container and get environment information.

Parameters:

  • identifier (str, required): Unique identifier for container reuse
  • language (str, required): Programming language ("python", "ruby", "shell")
  • env (dict, optional): Environment variables to set
  • timeout (int, optional): Default timeout in seconds
  • memory (str, optional): Memory limit (e.g., "256m", "1g")
  • network_allow (list[str], optional): Allowed network destinations

Returns: SetupResult with:

  • container_id: Container ID to use in run() calls
  • cached: Whether container was reused
  • environment_snapshot: Environment information (OS, runtime, packages)

client.run(container_id, files, run_command, **options)

Run code in a container that was set up via setup().

Parameters:

  • container_id (str, required): Container ID from setup() response
  • files (list[dict], required): Files to write before running
  • run_command (str, required): Command to run
  • env (dict, optional): Runtime environment variables
  • timeout (int, optional): Execution timeout in seconds

Returns: RunResult with:

  • success: Whether run succeeded (exit code 0)
  • exit_code: Process exit code
  • stdout: Standard output
  • stderr: Standard error
  • execution_time_ms: Execution time in milliseconds
  • timed_out: Whether run timed out

Error Handling

from runbox_client import (
    Client,
    AuthenticationError,
    NotFoundError,
    ValidationError,
    RunError,
    ConnectionError,
)

try:
    setup = client.setup(identifier="test", language="python")
    result = client.run(
        container_id=setup.container_id,
        files=[{"path": "main.py", "content": "print('hi')"}],
        run_command="python main.py"
    )
except AuthenticationError:
    print("Invalid API key")
except NotFoundError:
    print("Container not found (did you call setup first?)")
except ValidationError as e:
    print(f"Invalid request: {e}")
except RunError as e:
    print(f"Run failed: {e}")
except ConnectionError as e:
    print(f"Could not connect: {e}")

Development

Setup

python3 -m venv venv
source venv/bin/activate
pip install -e ".[dev]"

Running Tests

pytest

Running Integration Tests

Integration tests require a running Runbox server:

# Start Runbox server (in another terminal)
cd ../runbox
docker-compose up

# Run integration tests
export RUNBOX_URL=http://localhost:8080
export RUNBOX_API_KEY=your-api-key
python examples/integration_test.py

Linting & Typing

ruff check .
mypy src

CI/CD

  • CI: Runs on every push and PR

    • Tests on Python 3.9, 3.10, 3.11, 3.12
    • Linting with Ruff
    • Type checking with MyPy
    • Integration tests against live Runbox server
  • CD: Publishes to PyPI on version tags

License

MIT License - see LICENSE for details.

Metadata

Release files for runbox-py 1.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for runbox-py 1.1.1
File Size Uploaded Provenance
runbox_py-1.1.1.tar.gz 11.5 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for runbox-py 1.1.1
File Interpreter ABI Platform
runbox_py-1.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 19.1 kB

Release files / runbox_py-1.1.1.tar.gz

Download URL runbox_py-1.1.1.tar.gz
Size 11.5 kB
Tags Source
SHA-256 checksum
How to use checksums
50793a9ec82ce550941b313dffd590e072492a8be0e0b30518616fd0107d40f9
BLAKE2b-256 checksum
How to use checksums
b0ccaa239a4a70878341201f131a28494828a5e1a86c92f64d92d406a324db89
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 23, 2026.

Transparency log

Release files / runbox_py-1.1.1-py3-none-any.whl

Download URL runbox_py-1.1.1-py3-none-any.whl
Size 7.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1e0fb4724c5f901a58907d3918f9775947f070ae4e8e90a6a2aeeb9715a378aa
BLAKE2b-256 checksum
How to use checksums
dc1cc0a38a28c1ac1b6b0c513fb171c7fb2372eda165d150d28be7af65331cb2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 23, 2026.

Transparency log

Security for runbox-py 1.1.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for runbox_py-1.1.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Mar 23, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.1.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page