sandkiln.

Run untrusted code onhardware you control.

Every execution gets its own Firecracker microVM. Its own kernel, its own filesystem, its own network. Not a container with extra steps.

A Rust VMM, a static guest agent on vsock, an HTTP daemon driving both. Self-hosted, MIT licensed, benchmarked in the open.

Self-hosting quickstart

guest console — ttyS010.5–10.9ms to InstanceStart
[ 0.000000] Linux version 5.10.223 (gcc 11.4.0) #1 SMP
[ 0.000000] Command line: console=ttyS0 reboot=k panic=1
[ 0.000000] Hypervisor detected: KVM
[ 0.005803] Booting paravirtualized kernel on KVM
[ 0.046087] smp: Brought up 1 node, 2 CPUs
[ 0.214030] virtio_blk virtio0: [vda] 300 MiB
[ 0.259624] VFS: Mounted root (ext4) on device 254:0
[ 0.279281] Run /sbin/init as init process
[ 0.302006] systemd[1]: systemd 249.11 running
Starting sandkiln-agent.service...
[ OK ] Started sandkiln-agent.service
Ubuntu 22.04.5 LTS ubuntu-fc-uvm ttyS0
ubuntu-fc-uvm login: root (automatic login)
cold boot
10.5–10.9ms
criterion, spawn to InstanceStart
exec round-trip
220–250µs
criterion, over an open vsock
resume from snapshot
6.5–7.7ms
criterion
full create
144ms
mean of 20 isolated cold creates

Every track is the same log axis, 100µs to 1s, one tick per decade — so the marks compare directly. One dev box, single node.

isolation

Containers share a kernel.Sandboxes can't afford to.

Agent output, user uploads, third-party scripts. Running code you didn't write beside your own systems is a bad bet when the boundary is a namespace. A compromised container can still be a compromised kernel.

PropertyA containerA sandkiln sandbox
KernelShared with the hostDedicated per sandbox
Isolation boundaryNamespaces and cgroupsHardware virtualization (KVM)
Cold start~100ms–1s+10.5–10.9ms, measured
Escape surfaceShared syscall tableThe microVM boundary
FilesystemOverlay on the host filesystemDedicated virtio-blk device
Suited toPackaging code you wroteRunning code you didn't
surface

Everything a sandbox needs,marked by what's actually true.

Three marks, because two would lie. A capability that runs but isn't reachable from every client says so here rather than hiding behind a filled square.

18shippedverified on real hardware
  • Isolation
  • Networking
  • Auth
  • Tags
  • File operations
  • Interactive terminal
  • Guest-accessible metadata
  • Per-sandbox I/O rate limiting
  • Durable sandbox history
  • Snapshot lineage
  • Observability
  • Snapshots & persistence
  • Drives
  • Auto-suspend on idle
  • Multi-agent isolation
  • Python SDK
  • Benchmarking
  • Local tunnel
8partialbuilt, with the gap stated
  • Pre-warmed pools
  • JS/TS SDK
  • CLI
  • Remote storage mounts
  • Time-travel restore
  • Egress firewall
  • Custom & managed images
  • Jailer hardening
3plannednot built yet
  • Streamed output
  • Seccomp filters & disk quotas
  • System-privileged workloads

Every item above, with what it does and exactly where it stops, is on the roadmap.

client

A thin, fully-typed client.Nothing more.

The daemon's HTTP API is the source of truth. Every SDK method is a thin wrapper over it, verified against a live daemon rather than designed in isolation — so the same four calls read the same way in all three.

import { Sandbox } from "sandkiln";

// Boots a real Firecracker microVM — own kernel, own filesystem, own network.
const sandbox = await Sandbox.create({
  tags: { env: "ci", owner: "pipeline" },
});

const result = await sandbox.runCommand("python3", ["analyze.py"]);
console.log(result.stdout, result.exitCode);

await sandbox.stop(); // preserved as a resumable snapshot by default

Quickstarts for JS/TS, Python and the CLI, or the daemon HTTP API that every one of them wraps.