Skip to main content

Secure isolated code execution SDK for Python

Project description

fermion-sandbox

Secure isolated code execution SDK for Python. Run untrusted code, build projects, or host services in ephemeral containers.

Installation

pip install fermion-sandbox

Quick Start

import asyncio
import os
from fermion_sandbox import Sandbox

async def main():
    # Get API key from environment
    api_key = os.getenv('FERMION_API_KEY')
    if not api_key:
        raise ValueError("FERMION_API_KEY environment variable is required")

    # Create sandbox
    sandbox = Sandbox(api_key=api_key)
    await sandbox.create(should_backup_filesystem=False)

    # Execute commands
    result = await sandbox.run_command(cmd='node', args=['--version'])
    print(result.stdout)

    # Write and read files
    await sandbox.write_file(
        path='~/script.js',
        content='console.log("Hello World")'
    )

    response = await sandbox.get_file('~/script.js')
    content = response.text

    # Clean up
    await sandbox.disconnect()

asyncio.run(main())

Note: Set your API key as an environment variable: export FERMION_API_KEY='your-api-key'

Key Features

  • Isolated containers - Secure Linux environments for code execution
  • Real-time streaming - WebSocket-based command output streaming
  • File operations - Read/write files with binary support
  • Public URLs - Expose ports 3000, 1337, 1338 for web services
  • Git support - Clone repositories on container startup
  • Type safety - Full type hints with Pydantic models
  • Async/await - Built on asyncio for modern Python applications

Core API

Creating a Sandbox

sandbox = Sandbox(api_key='your-api-key')

# New container
await sandbox.create(
    should_backup_filesystem=False,  # Persist filesystem after shutdown
    git_repo_url='https://github.com/user/repo.git'  # Optional
)

# Or connect to existing
await sandbox.from_snippet('snippet-id')

Running Commands

# Quick commands (< 5 seconds)
result = await sandbox.run_command(
    cmd='ls',
    args=['-la']
)
print(result.stdout, result.stderr)

# Long-running with streaming
result = await sandbox.run_streaming_command(
    cmd='npm',
    args=['install'],
    on_stdout=lambda data: print(data),
    on_stderr=lambda data: print(data)
)
print(f"Exit code: {result.exit_code}")

File Operations

# Write file
await sandbox.write_file(
    path='~/app.js',
    content='console.log("Hello")'
)

# Read file
response = await sandbox.get_file('~/app.js')
text = response.text
binary_data = response.content

Web Services

# Start a server
asyncio.create_task(sandbox.run_streaming_command(
    cmd='node',
    args=['server.js']
))

# Get public URL
url = await sandbox.expose_port(3000)
print(f'Live at: {url}')
# https://abc123-3000.run-code.com

Quick Code Execution

# Execute code without full sandbox
result = await sandbox.quick_run(
    runtime='Python',
    source_code='print("Hello, World!")'
)

if result.program_run_data:
    stdout = result.program_run_data.stdout_base64_url_encoded or ''
    print(stdout)

Examples

Run a Node.js Project

import asyncio
from fermion_sandbox import Sandbox

async def main():
    sandbox = Sandbox(api_key='your-api-key')
    await sandbox.create(
        should_backup_filesystem=False,
        git_repo_url='https://github.com/user/node-app.git'
    )

    # Install dependencies
    await sandbox.run_streaming_command(
        cmd='npm',
        args=['install'],
        on_stdout=lambda data: print(data.strip())
    )

    # Build project
    await sandbox.run_command(cmd='npm', args=['run', 'build'])

    # Start server
    asyncio.create_task(sandbox.run_streaming_command(
        cmd='npm',
        args=['start']
    ))

    # Get public URL
    url = await sandbox.expose_port(3000)
    print(f'App running at: {url}')

    # Keep running
    await asyncio.sleep(60)
    await sandbox.disconnect()

asyncio.run(main())

Execute C++ Code

from fermion_sandbox import Sandbox

async def main():
    sandbox = Sandbox(api_key='your-api-key')

    result = await sandbox.quick_run(
        runtime='C++',
        source_code='''
            #include <iostream>
            using namespace std;
            int main() {
                int a, b;
                cin >> a >> b;
                cout << a + b << endl;
                return 0;
            }
        ''',
        stdin='5 3',
        expected_output='8'
    )

    print(f"Status: {result.run_status}")
    if result.program_run_data:
        stdout = result.program_run_data.stdout_base64_url_encoded or ''
        print(f"Output: {stdout}")

asyncio.run(main())

API Reference

Sandbox Class

Constructor

Sandbox(api_key: str)

Initialize sandbox client with API key.

Methods

async create(should_backup_filesystem: bool, git_repo_url: Optional[str] = None) -> str

  • Create new container
  • Returns: snippet ID

async from_snippet(playground_snippet_id: str) -> None

  • Connect to existing container

async run_command(cmd: str, args: Optional[list[str]] = None) -> CommandResult

  • Execute command (< 5s timeout)
  • Returns: CommandResult with stdout, stderr

async run_streaming_command(...) -> CommandResult

  • Execute with streaming output
  • Callbacks: on_stdout, on_stderr
  • Returns: CommandResult with stdout, stderr, exit_code

async write_file(path: str, content: Union[str, bytes]) -> None

  • Write file to container

async get_file(path: str) -> httpx.Response

  • Read file from container
  • Returns: Response object (use .text or .content)

async expose_port(port: Literal[3000, 1337, 1338]) -> str

  • Get public URL for port

get_public_urls() -> Dict[int, str]

  • Get all available public URLs

async disconnect() -> None

  • Clean up resources

is_connected() -> bool

  • Check connection status

async quick_run(...) -> DsaExecutionResult

  • Execute code without full sandbox
  • Supported runtimes: C, C++, Java, Python, Node.js, SQLite, MySQL, Go, Rust, .NET

File Paths

All paths must start with ~ (home) or /home/damner:

  • ~/file.js/home/damner/file.js
  • /home/damner/app/index.js → absolute path
  • /home/damner/code/app/index.js → also supported (nested under home)

Supported Ports

Public URLs available for:

  • Port 3000
  • Port 1337
  • Port 1338

Requirements

  • Python 3.8+
  • httpx
  • websockets
  • pydantic

Development

# Install with dev dependencies
pip install -e ".[dev]"

# Run tests
pytest

# Format code
black fermion_sandbox/

# Type checking
mypy fermion_sandbox/

Examples Directory

Check the examples/ directory for more usage examples:

  • basic_usage.py - Basic commands and file operations
  • streaming_command.py - Real-time streaming output
  • quick_run.py - Quick code execution
  • web_server.py - Running web servers with public URLs

Running Examples

Set your API key and run any example:

# Set API key inline (recommended)
FERMION_API_KEY='your-api-key' python examples/basic_usage.py

# Or export for current terminal session
export FERMION_API_KEY='your-api-key'
python examples/basic_usage.py

Running Tests

# Unit tests (no API key needed)
pytest tests/test_utils.py tests/test_types.py

# Integration tests (API key required)
FERMION_API_KEY='your-api-key' pytest tests/test_integration.py

# All tests
FERMION_API_KEY='your-api-key' pytest tests/

License

MIT

Support

For issues and questions, visit GitHub Issues.

Related

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

fermion_sandbox-0.1.1.tar.gz (30.1 kB view details)

Uploaded Source

Built Distribution

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

fermion_sandbox-0.1.1-py3-none-any.whl (24.7 kB view details)

Uploaded Python 3

File details

Details for the file fermion_sandbox-0.1.1.tar.gz.

File metadata

  • Download URL: fermion_sandbox-0.1.1.tar.gz
  • Upload date:
  • Size: 30.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for fermion_sandbox-0.1.1.tar.gz
Algorithm Hash digest
SHA256 673e326396d2ed841e60637434ad9ee0be6af4d37efd55ac50ea2832c2118d30
MD5 263aaa25cb1a9c537b16fcb5add201f7
BLAKE2b-256 2d26f58b300d4d4df31bc24551989fe733799828d7609c8b02d658fd99731adf

See more details on using hashes here.

File details

Details for the file fermion_sandbox-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for fermion_sandbox-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 81abd2606f2e78ed9fe1f791903517bc8c21c71aaa7d143880cadaeeb38743f4
MD5 c7c5c56c758e9a53d0a67710ec7be231
BLAKE2b-256 b778d1be338139ee08fc32a68af8c03e953bd072f043e1a15b0187e95d2fa537

See more details on using hashes here.

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