Docs
Serverless Python on hardware you own. Decorate, run, record.
Install
roost is a Python package. The only requirement on the client is Python 3.9+; fleet nodes need Python 3 and SSH access.
# from PyPI pip install roost # or from source git clone https://github.com/memjar/roost pip install -e roost
Your first run
Write a function, decorate it with an app, and run it. roost ships the source to the target, builds the environment once, and streams the output back.
# train.py import roost app = roost.App("probe") image = roost.Image.debian_slim().pip_install("numpy") @app.function(image=image, gpu="fleet:jl1", timeout=300) def train(epochs=5): import os, numpy as np print(f"[boot] on {os.uname().nodename}") return {"epochs": epochs}
roost run train.py::train '{"epochs": 5}'
Run targets
The gpu argument decides where a function executes. roost never hides the host — a fleet run records the node it ran on.
Runs in an isolated subprocess on this machine. Zero network. Good for local iteration.
Same as None — explicit local execution.
Ships the call to node jl1 over SSH, provisions the venv, runs, and copies the result back.
Fan work across the fleet, or detach a call and collect it later with .get().
Primitives
Image
roost.Image.debian_slim().pip_install(...) describes an environment. It hashes to a content-addressed digest that names a cached venv on each node — build once, reuse forever.
Volume
roost.Volume.from_name(name) gives durable storage mounted into the function. Persist with vol.commit(). Volumes live under ~/.roost/volumes.
App & function
app = roost.App("name") then @app.function(...). For one-off scripts, @roost.function(...) binds to a default app.
The ledger
Every run writes to ~/.roost/runs/<runid>/: a meta.json (status, target, duration, host, result) plus stdout.log and stderr.log. This is the source of truth — the CLI and console both read straight from it. It's local, it's plain JSON, and it's yours.
~/.roost/runs/train-fleet-jl1-1756-4821-0/ ├── meta.json # status, target, duration_s, remote_host, result ├── stdout.log └── stderr.log
CLI
roost run file.py::fn [json-args] # run on the fleet roost runs -n 20 # list the ledger roost logs <runid> # meta + stdout/stderr roost serve --port 8787 # the console + JSON API
The console
Run roost serve and open the console. It serves a dashboard and a JSON API over your local ledger — per-call telemetry, live metrics, streamed logs, and full run detail. Nothing leaves your machine.
The console at roost.computer/console.html auto-connects to http://127.0.0.1:8787. Point it elsewhere with the endpoint field or ?api=. Without a daemon it shows demo data so you can see the shape.
API
GET /api/runs # the full ledger GET /api/runs/<id> # one run + logs GET /api/stats # aggregate metrics
MCP server
roost ships a Model Context Protocol server so any MCP client (Claude Code, etc.) can run functions and read the ledger. It's a native binary distributed via npx.
// mcp config { "mcpServers": { "roost": { "command": "npx", "args": ["-y", "@glenmaura/roost-mcp"] } } }
Tools: roost_run, roost_runs, roost_logs. See the package.