Agent sandboxes· soon
Read the docssoon
~/api — russel — zsh

Same build, same config, same CLI.
Only the isolation changes.

Everything in one Russelfile

Runtime, resources, routing and secrets, versioned next to your code. Apps run unprivileged by default.

Russelfile.toml
[service]
name = "api"
source = "."
port = 3000
memory = "256mb"
type = "microvm"
cpus = 2
[ingress]
host = "api.example.com"
port = 8080
[service.env]
API_KEY = "secret://API_KEY"

name · Service id: 1–128 of A–Z, a–z, 0–9, _ and -.

Isolation you pick per service

Containers share the host kernel. microVMs get their own, behind a hardware boundary.

containermicroVMapiworkerdbpodmanshared kernelapikernelworkerkerneldbkernelKVMyour hardwaretype = "container" | "microvm"

Switch in one line

Redeploy, and the new version takes traffic before the old one drains.

# Russelfile.toml
- type = "container"
+ type = "microvm"
v1
v2
deployreadydrained

Isolation costs, measured.
Against rootless Podman, same host.

deploy → first response
container microVM rootless podman
basic-http
Go, stdlib HTTP
812 ms6.4×
1,445 ms3.6×
5,228 ms
microvm-http
Rust, virtio-net TAP
813 ms10.1×
867 ms9.5×
8,196 ms
hello-rust
static Rust binary
924 ms5.4×
1,061 ms4.7×
4,969 ms
env-config
Node.js
778 ms8.1×
874 ms7.2×
6,288 ms
shortlink
URL shortener
602 ms10.4×
825 ms7.6×
6,277 ms
static-test
static files
873 ms1.5×
1,057 ms1.3×
1,331 ms
filebrowser
read-only virtiofs
1,223 ms6.9×
1,291 ms6.5×
8,387 ms

× = times faster than rootless podman

Up to 10.4× faster.
9.5× even with a kernel per VM.

Most of the gap with Podman is build time. microVM time includes Cloud Hypervisor init, virtio-fs and the guest kernel boot; the container is a direct rootfs bind.

median of 7 workloads
813 ms
1,057 ms
6,277 ms
containermicroVMrootless podman

bare metal · warm cache

Yours to run.
Reproducible, self-hosted, reversible.

$ nix build .#apibuilding api-0.4.2…$ nix path-info .#api/nix/store/9f2c…e41-api$laptop/nix/store/9f2c…e41-apiserver/nix/store/9f2c…e41-apiidentical · 0% drift

Builds that never drift

Every service is a hash-pinned Nix package, bit-for-bit the same on your laptop and the server.

build
nix
pin
commit + Russelfile
bare metal

Runs on machines you own

Bare metal, an edge box, or a cloud account you control.

container
any VPS, rootless Podman
microvm
needs /dev/kvm
api · generationsstep 5/5
  • gen 1 container● serving
  • gen 2 container● serving
  • build failed rolled_back● serving
  • gen 3 microvm● serving
$ russel rollback api --version 2
✓ deployed

Every deploy is a generation

Pinned to its commit and Russelfile, runtime included. A failed redeploy rolls itself back.

kept
last 20 generations
undo
russel rollback api

The control plane can go down.
Your services don't notice.

russel-ctrl builds, deploys and supervises, but it never sits in the request path. Workloads run detached, Traefik routes from files on disk, and a restarted ctrl re-adopts whatever is still running.

all 3 services serving
control planedata planeroutessupervise/var/lib/russelmetadata.jsonrussel-ctrl● upclientstraefik:80 :443api● servingmicrovmweb● servingcontainerdocs● servingcontainer
host · journalserved while ctrl was down 0
  1. +0.0s3 services serving

Skip the cluster.
Keep the box.

Russel sits between a Compose file and a cluster: your machines, your isolation choice, one config.

RusselDocker ComposeKubernetesCoolify / DokployManaged PaaS
Runs on hardware you own
microVM per serviceone lineKata add-onprovider decides
Rootless by defaultopt-inopt-inn/a
Reproducible buildsNix, hash-pinnedimage tagsimage tagsimage tagsbuildpacks
Zero-downtime cutover
One-command rollback
Config lives inone RusselfileYAML + Dockerfilemanifests + chartsweb UIdashboard
Moving parts to runrussel-ctrlDocker daemona clusterDocker + panelnone, billed

Managed PaaS = Vercel, Render, Fly and the like. Defaults as shipped; most gaps can be closed with enough setup.

Agent sandboxes.
Coming next.

Hand a coding agent its own machine on your server. It does the work, you keep the result, and the machine disappears.

Try every idea at once

One prompt, several sandboxes. Each attempt gets its own machine; you keep the one that works and the rest are deleted.

You, to Claude Code

sbx-1creating

retry the payment call

readtests/checkout.test.ts
editsrc/payments/client.ts+12 −3
testnpm test checkout×20
2 vcpu · 4gb · deleted when done
sbx-2creating

fake the clock in the test

readtests/checkout.test.ts
edittests/checkout.test.ts+8 −2
testnpm test checkout×20
2 vcpu · 4gb · deleted when done
sbx-3creating

lock the cart before checkout

readsrc/cart/reserve.ts
editsrc/cart/reserve.ts+5 −1
testnpm test checkout×20
2 vcpu · 4gb · deleted when done

kept sbx-3 · patch exported to your branch · sbx-1, sbx-2 deleted

Bring the agent you already use

It stays on your machine, logged in as you, and works in the sandbox over SSH. Nothing to install or log in to inside.

  • Claude Code
  • Codex
  • opencode
  • Droid
  • Copilot CLI
  • Command Code
  • Antigravity
  • Amp

Tested first with Claude Code, Codex and opencode. Logos belong to their owners.

Keep it or throw it away

Sandboxes are deleted when the job is done. Keep one instead and its files, tools and caches are there next time, or snapshot it and fork a fresh copy.

default
deleted when done
keep
files, tools, caches
fork
from any snapshot
sandboxesstep 5/5
  • sbx-8
  • after-depssnapshot
  • sbx-9● kept
# 60 minutes later
sbx-8 deleted · sbx-9 kept
sbx-1own filessbx-2own filessbx-3own files/nix/store · read-onlynodejsgitpythonpostgrescopiedstored once

Toolchains stored once

Sandboxes take their tools from the Nix store on your server. Ten attempts on the same stack share one copy; only their files are their own.

shared
toolchains, read-only
sees
only what it needs
own
workspace and caches
ssh sbx-3
claude
$ npm run dev
✓ up on :3000
● edit cart.ts
↻ reloaded
you
$ curl :3000
ok
$ tail -f app.log
GET /cart 200
[sbx-3]2 sessions · ttl 41m

Step in next to it

SSH into the same sandbox the agent is using to look around, try the app, or take over. It keeps running after you both leave.

access
ssh, same as the agent
stays up
until its ttl or you delete it
sbx-3agent at workgateway · packagesnpm registrycloud metadatacontrol planesbx-2

You choose what it can reach

Pick a network profile per sandbox. Your server, its control plane and other sandboxes are off-limits by default.

network
offline, packages, git, web
ports
private unless you share

One file, one command.
Try it.

Describe the service in a Russelfile.toml, then russel apply it. Change the options to see both update.

Runtime
~/api — russel
[service]
name = "api"
source = "."
port = 3000
memory = "256mb"
type = "microvm"
cpus = 2
[ingress]
host = "api.example.com"
port = 8080
[service.env]
LOG_LEVEL = "info"
DATABASE_URL = "secret://DATABASE_URL"

Coming soon.
What we’re building next.

apijobgVisor · userspace kernelwrite()few, filteredhost kernelany VPS · no /dev/kvm

Hardened containers

Run untrusted code under gVisor on any VPS, no /dev/kvm required.

russelfile
isolation = "gvisor"
runtime
runsc systrap, fails closed
$ git push origin mainpushmainwebhooksigned ✓buildnixmigratebefore trafficlivegen 8trafficgen 8no CI to set up

Deploy on git push

Push to a branch and Russel builds and deploys it, with signed webhooks and no CI to set up.

trigger
signed webhook
release
migrations run before traffic moves
api.example.comtraefikapi-1api-2api-3api-4loadreplicas = 2

Replicas

Run N copies of one service behind a single hostname, then create and destroy them from load.

routing
Traefik multi-backend
scale
manual, then autoscale
api · microVMup 3d 04:12:35vcpu4 of 8memory1024 of 2048 MiB+512 MiB hotplugged✓ no reboot · no redeploy

Live resize

Give a running microVM more vCPUs or memory without a reboot or a redeploy.

microvm
cpu + memory hotplug
container
first-class cpus limit
todaybusybox initapplinux guestsystemd · pid 1app.service✓sshd.service✓cron.service✓journald✓guest = "busybox"guest = "linux"

Full Linux guests

Boot a Linux userspace with systemd inside the guest instead of the minimal busybox init.

russelfile
service.guest = "linux"
microvm
volumes + extra ports
apilivecpu47%memory199 MiBrestarts 0 · last deploy 41sGET /metrics · prometheus formatcpu_usage{service="api"} 0.47memory_bytes{service="api"} 2.09e+8restarts_total{service="api"} 0deploy_seconds{service="api"} 41

Metrics

See CPU, memory, restarts and deploy times for every service, and scrape them with Prometheus.

endpoint
GET /metrics, Prometheus format
dashboard
live CPU + memory per service