zion

One microVM per branch. Its own database, its own services, its own browser, its own Claude.

neo · smith · oracle — Firecracker on a box under my desk

follow the white rabbit ↓

Why

I stopped switching branches. I start machines.

A real feature touches the backend, the frontend, the database and a migration or two. On a laptop, that's one checkout, one Postgres and one branch at a time — and the moment an agent works on something, my machine isn't mine anymore. zion gives every piece of work a whole computer: a Firecracker microVM that boots with the code checked out, the database restored, the services running and Claude waiting in a tmux pane. When the work is merged, the VM is deleted and nothing is left behind.

Parallel, for real

Five branches, five VMs, five databases. Nothing shared, nothing to stash, no port clash.

A sandbox for agents

Claude runs without permission prompts, because the VM is the sandbox. Worst case, I delete it.

Fast to throw away

A shared build cache means a new env only rebuilds what its branch changed.

A URL per branch

Every env gets its own HTTPS address. I open the feature on my phone, or send it to someone.

The cast

Four names, one movie.

Yes, they're named after The Matrix. It turned out to be a surprisingly accurate map of who talks to whom.

on my laptop

neo

The command line I live in.

  • neo new creates an env from a branch
  • neo send queues a task for Claude
  • neo connect drops me into the VM's tmux
  • stop, start, list, delete — with zsh completion

"I know kung fu." — it only talks to smith, over ssh.

on the host

smith

The daemon that makes machines.

  • Creates the disks, the network tap and the Firecracker process
  • Gives each env an HTTPS route through Caddy
  • Keeps the build cache warm for the next env
  • Holds only the one capability it needs

"Never send a human to do a machine's job."

inside each VM

oracle

The one who knows what Claude is doing.

  • Talks to smith over vsock — no network needed
  • Reports boot progress and Claude's status: idle, busy, waiting
  • Pastes queued messages when Claude is ready
  • Restarts Claude where it left off if it exits

"You didn't come here to make the choice. You've already made it."

the whole thing

zion

The host, the image, the city.

  • A single Linux box, reached over WireGuard
  • One VM image with the whole stack baked in
  • Dumps, caches and bare git repos on the host
  • One ./update deploys all of it

"This is Zion. And we are not afraid."

How it works

Laptop, host, microVM.

Three layers, each with one job. The laptop stays light, the host owns the lifecycle, and each VM is a complete, self-contained dev machine.

LAPTOP HOST MICROVM · ONE PER ENV neo CLI browser https://<env>… smith daemon · disks · taps · cache firecracker one process per VM caddy wildcard HTTPS, a route per env oracle status · messages · files claude tmux pane · chrome it can drive the app backend · frontend · workers its own services postgres · valkey · queue nginx ssh vsock boots routes

neo pushes the branch

The host has no access to GitHub: neo pushes the branches to bare repos on the host first.

smith builds the machine

A sparse copy of the root image, a data disk with the checkouts, a copy of the build cache, a tap device, an IP — then Firecracker.

The VM boots itself

Restores a database dump, builds what changed, runs the new migrations, starts every service and oracle.

smith opens the door

Health checks pass, the HTTPS route goes live, neo prints the URL. The new build refreshes the shared cache.

A day with neo

Hand it a task, come back to a branch.

Most of my work now is creating envs, writing precise tasks, and reviewing what comes back. neo send never waits: the message is queued and oracle delivers it as soon as Claude is free.

~ zsh
$ neo new feat-search
  app: feat-search (from next)   front: feat-search (from next)   dump: qa
✓ feat-search ready (2m41s)
  https://feat-search.<domain>

$ neo send feat-search "add fuzzy matching to the search endpoint, with tests" --attach mockup.png
  queued — Claude is idle, delivering now

$ neo list
ENV          STATE     CLAUDE     RAM       UP
feat-search  running   busy (1)   3.1/8G    4m
fix-icons    running   idle       2.4/8G    2h10m
perf-test    stopped   —          —         —

$ neo connect feat-search     # watch it work; Ctrl-b d to leave
$ neo stop perf-test          # disks and conversation kept
$ neo delete fix-icons -y      # merged: nothing left behind

Under the hood

The parts I'm a bit proud of.

A build cache that's a disk smith

The last good build lives on the host as a filesystem image. Each env gets a copy as an extra disk and bind-mounts it. Copying an image takes seconds; writing millions of small files into a fresh filesystem takes minutes. Files identical to the cached commit are backdated, so cargo only rebuilds the crates the branch touched.

Everything inside the VM zion

Postgres, Valkey, a queue and nginx run in each VM. I measured a shared database over the tunnel: a few milliseconds per query adds up fast, and restoring a dump takes seconds anyway. Self-contained wins.

Claude, interactive, always oracle

Claude Code runs in a real tmux pane, not through an SDK. Hooks tell oracle when it's busy, idle or waiting; oracle pastes the next message only when it's idle. If Claude exits, it comes back with --continue.

A browser it can drive zion

Each VM runs Chrome on a virtual screen, and Claude drives it. The screen is streamed over noVNC at its own HTTPS address: I can watch Claude click through the feature, or take the mouse myself.

Paste screenshots from my laptop neo

While neo connect is open, any image I copy on my laptop lands in the VM's clipboard. Ctrl-v in Claude pastes it, as if it were local.

Stop is cheap, start resumes smith

A stopped env costs only disk. Starting it again — bigger or smaller if I want — brings back the code, the database and the same Claude conversation.

RustFirecrackervsocktmuxCaddy WireGuardsystemdPostgres 17Valkeymold Xvfb + noVNCClaude Code

There is no spoon

There is no laptop either. Just a terminal and a lot of machines.

zion is a personal tool, built for the way I work. It isn't a product and there's nothing to sign up for — just a write-up of how I run my dev environments today.