Quicksand

Quicksand is an async Python API to launch, control, and snapshot QEMU virtual machines with a particular focus on sandboxing AI agents. Quicksand provides pre-built Linux VMs for Ubuntu and Alpine distros. It works on x86_64 and ARM64 across macOS, Linux, and Windows with no root privileges, no Docker, and no system dependencies. Just pip install quick-sandbox.
Installation
pip install 'quick-sandbox[qemu,alpine]'
Or install the core package and add QEMU/images separately:
pip install quick-sandbox quicksand install qemu alpine
Usage
Hello, World!
import asyncio from quicksand import Sandbox async def main(): async with Sandbox(image="ubuntu") as sb: result = await sb.execute("echo 'Hello from the sandbox!'") print(result.stdout) asyncio.run(main())
Run commands
result = await sb.execute("apt update && apt install -y python3") print(result.stdout, result.exit_code)
Mount host directories
Share host directories into the VM at boot or on the fly.
# At boot async with Sandbox( image="ubuntu", mounts=[Mount("./workspace", "/mnt/workspace")], ) as sb: ... # Or dynamically on a running sandbox handle = await sb.mount("/tmp/data", "/mnt/data") await sb.execute("ls /mnt/data") await sb.unmount(handle)
Configure networking
Sandboxes are network-isolated by default. Opt in to internet access and port forwarding with NetworkMode.FULL.
async with Sandbox( image="ubuntu", network_mode=NetworkMode.FULL, port_forwards=[PortForward(host=8080, guest=80)], ) as sb: ...
Save and load
Save the VM's disk state to a directory. Load it later, even on a different machine.
await sb.execute("pip install numpy pandas") await sb.save("my-env") # VM keeps running # Load later async with Sandbox(image="my-env") as sb: await sb.execute("python3 -c 'import numpy; print(numpy.__version__)'")
Checkpoint and revert
Capture the full VM state and roll back if something goes wrong.
await sb.checkpoint("before-experiment") await sb.execute("apt install -y something-risky") await sb.revert("before-experiment") # the VM snaps back to the checkpoint
Control a desktop
Desktop images provide a full Xfce4 graphical environment with a browser. Install one with quicksand install ubuntu-desktop or quicksand install alpine-desktop.
async with Sandbox(image="ubuntu-desktop", enable_display=True) as sb: await sb.screenshot("screen.png") await sb.type_text("hello world") await sb.press_key(Key.RET) await sb.mouse_move(500, 300) await sb.mouse_click("left")
Configuration
Here are all of the Sandbox configuration options:
Sandbox( # Image or save name to boot image="ubuntu", # Guest RAM (default: "512M") memory="2G", # Virtual CPU cores (default: 1) cpus=4, # Host directories shared into the VM at boot mounts=[Mount("/host", "/guest")], # NONE, MOUNTS_ONLY (default), or FULL internet access network_mode=NetworkMode.FULL, # Forward host TCP ports into the guest port_forwards=[PortForward(host=8080, guest=80)], # Expand the guest filesystem on boot disk_size="10G", # Attach virtual GPU, keyboard, and mouse for screenshot/type_text/mouse control enable_display=True, # Auto-save VM state on stop save="my-save-name", )
Available images
| Image | Type | Wheel size | Install command | What is it |
|---|---|---|---|---|
ubuntu | Base | ~341 MB | quicksand install ubuntu | Ubuntu 24.04 headless |
alpine | Base | ~78 MB | quicksand install alpine | Alpine 3.23 headless (faster boot) |
ubuntu-desktop | Overlay (ubuntu) | ~263 MB | quicksand install ubuntu-desktop | Ubuntu 24.04 + Xfce4 + Firefox |
alpine-desktop | Overlay (alpine) | ~310 MB | quicksand install alpine-desktop | Alpine 3.23 + Xfce4 + Chromium |
quicksand-agent | Overlay (ubuntu) | ~304 MB | quicksand install quicksand-agent | Ubuntu + Python 3.12, uv, build-essential, requests, pyyaml, ddgs, markitdown |
quicksand-cua | Overlay (quicksand-agent) | ~445 MB | quicksand install quicksand-cua | Agent Sandbox + Xvfb, x11vnc, noVNC, Playwright, Chromium |
Building from source
git clone https://github.com/microsoft/quicksand.git cd quicksand uv sync uv run uvr build --all-packages
Documentation
| Topic | Guide | Under the Hood |
|---|---|---|
| Installation | Installing packages | QEMU binaries, kernels, qcow2 disks |
| Sandbox Lifecycle | Creating and configuring sandboxes | -m, -smp, -accel, machine types |
| Running Commands | execute(), streaming, exit codes | Kernel boot, agent tokens, hostfwd |
| File Exchange | Mounts, hot-mounts, getting data in/out | CIFS via guestfwd, 9p via -fsdev |
| Save and Rollback | Checkpoints, reverts, persistent saves | qcow2 overlays, savevm, blockdev-snapshot-sync |
| Desktop Control | Screenshots, keyboard, mouse | VNC, GPU, USB tablet, QMP input injection |
| Network and Isolation | Network modes, port forwarding | SLIRP NAT, restrict=on, guestfwd |
| Performance | What makes it fast | io_uring, IOThreads, TCG vs KVM |
Contributing
| Guide | When to use |
|---|---|
| Creating Images | Build a new base or overlay image package |
| Extending the Sandbox | Add a method, OS, architecture, or QEMU flag |
| Testing | Run or write tests |
| Releasing | Cut a release |
Full guides: User Guide | Under the Hood | Contributor Guide