2026-09-01 21:27:15 -07:00
2026-09-01 11:49:10 -07:00
2026-09-01 16:30:19 -07:00
2026-09-01 16:44:41 -07:00
2026-09-01 11:49:10 -07:00
2026-09-01 11:49:10 -07:00
2026-09-01 11:49:10 -07:00

Hanzo VM

Hanzo's microVM layer. hanzo-vm boots a small Linux guest on the host you are on, runs a command in it, and throws the disk away when the command exits. The guest gets a copy-on-write clone of the root image, so packages installed and files written inside a run never touch the host or the next run.

Vocabulary

  • vm — a microVM booted on a host we control. This repository.
  • sandbox — a hosted lease of a vm with policy (/v1/sandbox in Hanzo Cloud). Not a local noun; nothing here is called a sandbox.
  • machine — a host (Visor).

Backends

  • macOS — Apple Virtualization.framework. Apple Silicon only, arm64 guests only, no Rosetta. macOS 14 or later.
  • Linux arm64 — KVM backend (crates/vm-linux), hosts with /dev/kvm.
  • Linux x86_64 — cloud-hypervisor backend (crates/vm-ch), hosts with /dev/kvm plus the cloud-hypervisor and virtiofsd binaries (see Linux hosts).

Install

cargo install hanzo-vm

or the release binary:

curl -fsSL https://raw.githubusercontent.com/hanzoai/vm/main/install.sh | sh

Both put hanzo-vm in ~/.local/bin. The first hanzo-vm run downloads the guest image (kernel, initramfs, root filesystem) from the matching GitHub release into ~/.hanzo/vm; set HANZO_VM_HOME to put it elsewhere.

Linux hosts

Both Linux backends need read/write access to /dev/kvm (membership in the kvm group, or an ACL).

arm64 connects to the guest through the host's vhost-vsock device; grant access once with:

sudo setfacl -m u:$USER:rw /dev/vhost-vsock

x86_64 drives release binaries of cloud-hypervisor (verified with v53.0) and virtiofsd (verified with 1.10.0), looked up on PATH and in ~/.local/bin:

curl -fsSLo ~/.local/bin/cloud-hypervisor \
  https://github.com/cloud-hypervisor/cloud-hypervisor/releases/download/v53.0/cloud-hypervisor-static
chmod +x ~/.local/bin/cloud-hypervisor
sudo apt install virtiofsd   # Debian/Ubuntu; installs /usr/libexec/virtiofsd
install -m 755 /usr/libexec/virtiofsd ~/.local/bin/virtiofsd

Usage

# Interactive shell
hanzo-vm run

# Run a command
hanzo-vm run -- echo hello

# With network access
hanzo-vm run --allow-net

# Restrict to specific hosts
hanzo-vm run --allow-net --allow-host api.openai.com --allow-host registry.npmjs.org

# Use a specific DNS resolver
hanzo-vm run --allow-net --dns-resolver 1.1.1.1 -- curl https://example.com

# Custom resources
hanzo-vm run --cpus 4 --memory 4096 --disk-size 8192 -- make -j4

Directory mounts

Host directories are shared into the guest over VirtioFS. A mount is read-only by default; guest writes land in a tmpfs overlay that disappears with the vm. Append :rw to write through to the host, which also needs --allow-host-writes. Only paths under the current directory can be mounted.

# Read-only: the write stays in the overlay
hanzo-vm run --mount ./src:/workspace -- touch /workspace/test.txt
ls ./src/test.txt   # not found

# Read-write: the write reaches the host
hanzo-vm run --allow-host-writes --mount ./src:/workspace:rw -- touch /workspace/test.txt
ls ./src/test.txt   # found

# Several mounts
hanzo-vm run --mount ./src:/workspace --mount ./data:/data -- sh

Mounts can also be listed in vm.json (see Config file).

Port forwarding

Host ports are forwarded to guest ports over vsock, so this works without --allow-net and without a network device in the guest.

# Install python3 into a checkpoint, then serve from it
hanzo-vm checkpoint create py --allow-net -- apt-get install -y python3
hanzo-vm run --from py -p 8080:8000 -- python3 -m http.server 8000

# From the host, in another terminal
curl http://127.0.0.1:8080/

# Several ports
hanzo-vm run -p 8080:80 -p 8443:443 -- nginx

Port forwards can also be listed in vm.json.

Checkpoints

A checkpoint saves the disk after a command so later runs start from it.

# Build an environment and save it
hanzo-vm checkpoint create myenv --allow-net -- sh -c 'apt-get install -y python3 gcc'

# Run from it; changes made during the run are discarded
hanzo-vm run --from myenv -- python3 script.py

# Branch from an existing checkpoint
hanzo-vm checkpoint create myenv2 --from myenv --allow-net -- sh -c 'pip install numpy'

# List and delete
hanzo-vm checkpoint list
hanzo-vm checkpoint delete myenv

Secrets

A secret never enters the guest. The guest sees a random placeholder in the named environment variable; the host-side proxy substitutes the real value only on HTTPS requests to the listed hosts.

hanzo-vm run --allow-net --secret API_KEY=[email protected] -- curl https://api.openai.com/v1/models

hanzo-vm run --allow-net \
  --secret API_KEY=[email protected] \
  --secret GH_TOKEN=[email protected] \
  -- sh

Format: NAME=ENV_VAR@host1,host2. NAME is the variable the guest sees, ENV_VAR is the host variable holding the real value, and the hosts are where the proxy substitutes it. A secret in vm.json can instead name a command that mints the value and is re-run as it expires; see docs/rfcs/0002-refreshable-secrets.md.

Config file

hanzo-vm reads vm.json from the current directory, or the file given by --config. Every field is optional and flags take precedence.

{
  "cpus": 4,
  "memory": 4096,
  "disk_size": 8192,
  "allow_net": true,
  "ports": ["8080:80"],
  "mounts": ["./src:/workspace", "./data:/data"],
  "command": ["python", "script.py"],
  "secrets": {
    "API_KEY": {
      "from": "OPENAI_API_KEY",
      "hosts": ["api.openai.com"]
    }
  },
  "network": {
    "allow": ["api.openai.com", "registry.npmjs.org"]
  }
}

network.allow restricts which hosts the guest can reach; omit it to allow all.

SDK

crates/vm-sdk is the async Rust API over the same vm. packages/sdk is the TypeScript package @hanzo/vm, which drives the hanzo-vm binary in --stdio mode; see packages/sdk/README.md.

Building from source

just build       # guest (aarch64 musl) + CLI + ad-hoc codesign
just install     # release CLI to ~/.local/bin/hanzo-vm

The guest image is built by scripts/prepare-rootfs.sh (kernel via scripts/build-kernel.sh); it runs natively on arm64 and x86_64 Linux hosts (building the guest needs musl-tools for the musl target) and inside Docker on macOS. CI publishes the image with every release.

Changelog

See CHANGELOG.md.

License

Apache-2.0. See LICENSE and NOTICE.

S
Description
Hanzo VM — native microVMs for agents: Virtualization.framework on macOS, KVM on Linux. Mounts, checkpoints, port forwards, egress policy, secret injection.
Readme
9.9 MiB
Languages
Rust 91.7%
TypeScript 6.7%
Shell 1.4%
Just 0.2%