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
from fermion_sandbox import decode_base64url
# Execute code without full sandbox
result = await sandbox.quick_run(
runtime='Python',
source_code='print("Hello, World!")'
)
if result.run_result and result.run_result.program_run_data:
stdout = decode_base64url(result.run_result.program_run_data.stdout_base64_url_encoded)
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, decode_base64url
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_result.run_status}")
stdout = decode_base64url(result.run_result.program_run_data.stdout_base64_url_encoded)
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 operationsstreaming_command.py- Real-time streaming outputquick_run.py- Quick code executionweb_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
- Node.js SDK - Official TypeScript/JavaScript SDK
- Documentation - Full API documentation
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file fermion_sandbox-0.1.0.tar.gz.
File metadata
- Download URL: fermion_sandbox-0.1.0.tar.gz
- Upload date:
- Size: 29.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c662477384e9c07c2c56a3db2e8575f3899feba109a2628e0ee8abc9e29382ae
|
|
| MD5 |
7193878c3cdffeb4e0f169fb28398dba
|
|
| BLAKE2b-256 |
7c0b77905966b2900c1fe8d14c518dce524b8e0ca5985c9adeab42df4bfba501
|
File details
Details for the file fermion_sandbox-0.1.0-py3-none-any.whl.
File metadata
- Download URL: fermion_sandbox-0.1.0-py3-none-any.whl
- Upload date:
- Size: 23.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aed9a93d720219cadfb67a705699b13487cca27ce6bc462c59ca7b94347c0ad3
|
|
| MD5 |
35abe443c03be705ca70d26d75a641b0
|
|
| BLAKE2b-256 |
676688af6de8b9b3d6434ca5fca0641723d90b51f192be8e0de31c2ac43d7bd4
|