A single-binary Rust microVM for AI-agent code execution.
Rust KVM Apache-2.0 / MIT Linux
* For minimal-footprint guests. Measured on an i5 laptop, 8 GiB RAM, vanilla Linux + KVM.
Reproduce with cargo run -p bench --features kvm --release -- --count 100 --alive 50.
Every AI coding agent — Claude Code, Cursor, Devin, OpenHands, aider, SWE-bench-style evals — needs to run generated code somewhere safe and cheaply. Today the options force a bad trade-off:
A single-binary Rust VMM + guest agent + REST control plane,
snapshot-first, with snapshot → fork as a first-class primitive.
An eval pipeline can spawn 1000 variants of a base image at ~12 ms each.
The kernel keeps the shared 6–7 MiB golden image actually shared across
all of them via MAP_PRIVATE copy-on-write.
| Axis | E2B | Firecracker | rust-nano-vm |
|---|---|---|---|
| Cold start (p50) | 150–400 ms | ~125 ms | ~12 ms |
| Snapshot → fork | service-side | not native | first-class |
| Per-fork memory | opaque | ~5 MiB+ RSS | ~0.5 MiB Pss |
| Distribution | SaaS only | VMM + jailer + your code | one binary |
| License | proprietary | Apache-2.0 | Apache-2.0 / MIT |
| Control plane | included (proprietary) | bring your own | included (axum) |
mmap away. Fork doesn't re-boot a
kernel — it maps the snapshot's RAM file MAP_PRIVATE and lets
the kernel serve the read-only golden pages to every child.
Read the write-up →kvm-bindings's serde feature.
Read the write-up →/proc/self/smaps_rollup), not RSS.
RSS double-counts shared pages and overstates fork cost by 5–10×./fork route,
per-caller usage metering, Prometheus /metrics endpoint.
~330 lines of axum, no magic.git clone https://github.com/ip888/Rust-nano-vm.git
cd Rust-nano-vm
cargo build --release -p control-plane
NANOVM_API_TOKENS=dev-token \
./target/release/nanovm-control-plane &
until curl -sf localhost:8080/healthz >/dev/null; do sleep 0.1; done
TOKEN="Authorization: Bearer dev-token"
VM=$(curl -s -X POST localhost:8080/v1/vms -H "$TOKEN" -H 'content-type: application/json' -d '{}' | jq -r .id)
curl -s -X POST localhost:8080/v1/vms/$VM/start -H "$TOKEN" >/dev/null
SNAP=$(curl -s -X POST localhost:8080/v1/vms/$VM/snapshot -H "$TOKEN" | jq -r .id)
# Fork 5 children, ~milliseconds each:
for i in 1 2 3 4 5; do
curl -s -X POST localhost:8080/v1/snapshots/$SNAP/fork -H "$TOKEN" \
| jq -c '{vm: .vm.id, fork_ms, fork_count}'
done
curl -s localhost:8080/v1/usage -H "$TOKEN" | jq
curl -s localhost:8080/metrics | head -20