pip install pyrovm-sdk
import asyncio
from pyro_sdk import Pyro
async def main():
pyro = Pyro(api_key="pk_...", base_url="http://localhost:8080")
async with await pyro.sandbox.create(image="python") as sb:
result = await sb.run("print('Hello from Pyro!')")
print(result.stdout)
asyncio.run(main())
npm install @pyrovm/sdk
import { Pyro } from '@pyrovm/sdk'
const pyro = new Pyro({ apiKey: 'pk_...', baseUrl: 'http://localhost:8080' })
const sandbox = await pyro.sandbox.create({ image: 'python', timeout: 300 })
const result = await sandbox.run('print("Hello from Pyro!")')
console.log(result.stdout)
await sandbox.stop()
export PYRO_API_KEY=pk_...
pyro sandbox create --image python --ttl 300
pyro sandbox exec <id> python3 -c "print('hello')"
pyro sandbox kill <id>
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│ SDK / CLI │────▶│ pyro-server │────▶│ Firecracker VM │
│ │ HTTP│ (REST API) │vsock│ (pyro-agent) │
└─────────────┘ └──────────────┘ └─────────────────┘
│
┌──────┴──────┐
│ SQLite │
│ (state DB) │
└─────────────┘
| Method | Path | Description |
|---|---|---|
POST |
/api/sandboxes |
Create sandbox |
GET |
/api/sandboxes |
List sandboxes |
GET |
/api/sandboxes/{id} |
Get sandbox |
DELETE |
/api/sandboxes/{id} |
Destroy sandbox |
POST |
/api/sandboxes/{id}/exec |
Execute command |
PUT |
/api/sandboxes/{id}/files/* |
Write file |
GET |
/api/sandboxes/{id}/files/* |
Read file |
GET |
/api/sandboxes/{id}/ws |
WebSocket streaming exec |
GET |
/api/images |
List images |
POST |
/api/images |
Create image from Dockerfile |
GET |
/api/events |
SSE event stream |
GET |
/api/health |
Health check |
Requires a Linux host with KVM support.
# One-command setup (kernel, images, bridge, systemd)
sudo pyro setup
# Create an API key
pyro create-key my-key
# Start the server
systemctl start pyro
make build # build all binaries
make build-linux # cross-compile for Linux
make deploy # build + SCP to remote host
| Image | Size | Includes |
|---|---|---|
minimal |
50 MB | Alpine base, busybox |
default |
50 MB | Alpine + common tools |
ubuntu |
~512 MB | Ubuntu 24.04 + git, curl, python3 |
python |
~512 MB | Python 3.12 + pip, requests, httpx |
node |
~512 MB | Node.js 22 + npm, corepack |
Build custom images from Dockerfiles:
pyro build-image <name>
# or via API:
curl -X POST /api/images -d '{"name":"custom","dockerfile":"..."}'
| Variable | Description | Default |
|---|---|---|
PYRO_API_KEY |
API key for SDK/CLI | — |
PYRO_BASE_URL |
Server URL | http://localhost:8080 |
PYRO_DB |
SQLite database path | /opt/pyro/db/pyro.db |
PYRO_IMAGES |
Images directory | /opt/pyro/images |
--listen API listen address (default :8080)
--db SQLite path
--images-dir Base images directory
--max-sandboxes Max concurrent VMs (default 100)
--max-per-key Max VMs per API key (default 10)
--rate-limit Creates per minute per key (default 30)
--pool-size Warm snapshot pool per image (default 0)
--prometheus Enable /metrics endpoint
| SDK | Package | Docs |
|---|---|---|
| Python | pyrovm-sdk |
README |
| TypeScript | @pyrovm/sdk |
README |
MIT