# Show HN: Sandkiln – Fast Firecracker MicroVM sandboxes for AI-generated code

> Source: <https://sandkiln.vercel.app/>
> Published: 2026-10-20 09:09:46+00:00

# 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.

```
[    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 ttyS0ubuntu-fc-uvm login: root (automatic login)
```

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](#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.

| Property | A container | A sandkiln sandbox | 
|---|---|---|
| Kernel | Shared with the host | Dedicated per sandbox | 
| Isolation boundary | Namespaces and cgroups | Hardware virtualization (KVM) | 
| Cold start | ~100ms–1s+ | 10.5–10.9ms, measured | 
| Escape surface | Shared syscall table | The microVM boundary | 
| Filesystem | Overlay on the host filesystem | Dedicated virtio-blk device | 
| Suited to | Packaging code you wrote | Running code you didn't | 

[surface](#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.

- 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

- Pre-warmed pools
- JS/TS SDK
- CLI
- Remote storage mounts
- Time-travel restore
- Egress firewall
- Custom & managed images
- Jailer hardening

- 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](https://sandkiln.vercel.app/roadmap/).

[client](#sdk)

## 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.

``` js
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
python
from sandkiln import Sandbox

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

result = sandbox.run_command("python3", ["analyze.py"])
print(result.stdout, result.exit_code)

sandbox.stop()  # preserved as a resumable snapshot by default
npm install -g sandkiln-cli   # installs the `kiln` command

# Boots a real Firecracker microVM — own kernel, own filesystem, own network.
kiln sandbox create --tag env=ci --tag owner=pipeline

kiln sandbox exec <id> python3 analyze.py
kiln sandbox ls --tag env=ci

kiln sandbox rm <id>           # preserves state as a snapshot by default
```

Quickstarts for [JS/TS](https://sandkiln.mintlify.site/getting-started/js), [Python](https://sandkiln.mintlify.site/getting-started/python) and [the CLI](https://sandkiln.mintlify.site/getting-started/cli), or the [daemon HTTP API](https://sandkiln.mintlify.site/reference/http-api) that every one of them wraps.

[further](#more)
