smolvm: an OCI-native microVM CLI for running agents in isolated Linux machines
An embeddable, portable, branchable virtual machine to safely run Agents locally.
At a glance
- What is it?
- smolvm boots Linux microVMs locally, declares them in a TOML Smolfile, and can fork a running machine into copy-on-write children. It is a strong fit for agent sandboxing and a poor fit for anyone who needs a stable, documented API surface today.
- Who is it for?
- Adopt smolvm if you are running coding agents or batch workloads that need a real Linux kernel boundary, disposable machines, and the ability to fork a warmed-up environment into many children. Do not adopt it if you need a frozen CLI surface: the README documents compatibility aliases (fork, --golden, --forkable) that already carry legacy weight, and the branch semantics have grown flags for batch identity, worker readiness and release.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Rust, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem smolvm solves: Linux isolation without a container runtime dependency
Running untrusted or semi-trusted code on a developer machine usually means choosing between a container and a full VM. Containers share the host kernel, which is a thinner boundary than many agent workloads want. A full VM gives you the kernel boundary but historically costs you either a hypervisor setup step or a slow boot. smolvm is aimed at the second option with the first option's ergonomics: a CLI that manages Linux virtual machines locally, with the README claiming sub-second cold start and elastic memory usage.
The stated audience is broad, but the repository layout points somewhere more specific. There is a crates/smolvm-agent crate, a smolvm-sdk directory, an sdks/ directory, and a demo directory containing dpo_train.py and qlora_train.py alongside H100_SETUP.md. The README's own install instructions include a line labelled "for coding agents: install + discover all commands". That is not a generic developer-tools pitch. The project is being shaped around agents that need to execute code, and around GPU training runs that need a reproducible environment.
The portability claim is the other half. The README says smolvm runs on macOS, Linux and Windows, and the Windows instructions are unusually explicit: download the windows-x86_64 release, which bundles krun.dll and libkrunfw.dll, and enable the Windows Hypervisor Platform feature. That is a real prerequisite, not a footnote, and it means Windows users are not getting a pure userspace sandbox.
How smolvm runs a machine: libkrun, OCI images and a TOML Smolfile
The Cargo.toml describes the package as an "OCI-native microVM runtime", and the topic list names libkrun and crun. The workspace confirms the structure: libkrun and libkrunfw are checked out as submodules at the repository root, and the dependency comment notes cross-platform dynamic library loading for libkrun via dlopen on Unix and LoadLibraryW on Windows. So the VM monitor is libkrun, the firmware is libkrunfw, and smolvm is the layer that turns OCI images and a declarative file into a running machine.
That layering explains the quick start. The command `smolvm machine run --net --image alpine` pulls an OCI image and boots it as a microVM rather than as a container, which is why the README's example can run `uname -a` inside and get a kernel that is not the host's. The `--net` flag is what enables networking; the README does not say what happens without it, but the flag's presence in every networking example suggests the default is no network.
The Smolfile is the piece that distinguishes smolvm from a plain `docker run` wrapper. It is TOML, and the README calls it the equivalent of a Dockerfile or a cloud-init file but for a whole VM. It carries image, cpus, memory, net, ports, volumes, env, init, workdir, user, gpu, cuda, docker_socket, storage and overlay, plus tables named [network], [dev], [auth], [health], [restart] and [service]. Two design decisions stand out. First, `init` runs once as root, explicitly compared to a Dockerfile RUN, while `user` controls who the workload runs as. Second, unknown keys are rejected rather than ignored, so a typo fails at create time. That is the right default for a config file that provisions a VM, and it is a deliberate departure from tools that silently accept junk keys.
Installing smolvm and running a first machine
On macOS and Linux the README gives a single install line that pipes a script from the project's site into bash. The same line is repeated with `smolvm --help` appended for coding agents that need to discover the command surface. If you prefer not to pipe a remote script into a shell, the README also points at GitHub Releases and says to place the binary into `~/.local/share/`.
curl -sSL https://smolmachines.com/install.sh | bashAfter that, the README's first real command runs a command inside an ephemeral VM that is cleaned up on exit. The `--net` flag enables networking, `--image alpine` selects the OCI image, and everything after `--` is the command inside the guest.
smolvm machine run --net --image alpine -- sh -c "echo 'Hello world from a microVM' && uname -a"The expected output is the echoed string followed by the guest's `uname -a` line. If you see the host's kernel version there, the machine did not boot as a VM. For an interactive session, the README uses `-it` with `/bin/sh`:
smolvm machine run --net -it --image alpine -- /bin/shInside that shell the README suggests `apk add sl && sl && exit`, which is a smoke test that package installation and networking both work. To keep a machine rather than discard it, declare it in a Smolfile and create it by name. The README's example file sets an image, resources, port ranges, a volume mount, an init command, an allow-list of hosts, and SSH agent forwarding:
image = "python:3.12-alpine"
net = true
cpus = 4
memory = 4096
ports = ["8000:8000", "5173-5180:5173-5180"]
volumes = ["./src:/app"]
init = ["pip install -r /app/requirements.txt"]
[network]
allow_hosts = ["api.stripe.com", "pypi.org"]
[auth]
ssh_agent = trueCreate and start it with the two commands the README gives, then use `smolvm machine shell --name myvm` to configure it interactively.
smolvm machine create --name myvm -s Smolfile
smolvm machine start --name myvmOne constraint worth knowing before you write port ranges: the README states that a machine can publish at most 64 concrete mappings, and that ranges must be equal-length and one-to-one. A range like `5173-5180:5173-5180` expands to eight mappings, so the ceiling is reachable quickly if you fan out services.
Branching a running machine: the feature with the most caveats
The branch feature is where smolvm stops looking like a container wrapper and starts looking like a research artifact that shipped. The README describes a branch as a live fork: an independent copy-on-write child that resumes with the source's running processes, memory and disk. You start a source with `--branchable`, then branch it.
smolvm machine start --name source --branchable
smolvm machine branch --from source --name childFor fan-out, the workload itself has to mark the branchpoint. The guest runs `smolvm-branch-ready` once its setup is done, and that helper blocks in the source, which stays parked, while in each child it hands off to a named program with the child's identity in the environment. The README's example installs a package, starts a background server, then execs the helper with `python3 episode.py` as the program each child should run. Children see SMOLVM_BRANCH_NAME, SMOLVM_BRANCH_INDEX, SMOLVM_BRANCH_BATCH_ID and SMOLVM_BRANCH_BATCH_SIZE. A shell script that wants to continue inline instead can run `eval "$(smolvm-branch-ready)"`, which emits those variables as export lines.
The caveats are the interesting part. A batch branch waits for the source to reach its branchpoint, with a default `--ready-timeout` of 10 minutes, but a single `--name` branch never waits. That asymmetry is a real footgun: the same conceptual operation behaves differently depending on whether you passed a name or a prefix. There is a second readiness layer for children that need their own warm-up, `smolvm-worker-ready`, which the branch command can wait on via `--wait-worker-ready` with `--worker-ready-timeout` defaulting to 5 minutes. The README is explicit that a child which never reports is torn down with its batch rather than handed back looking alive, which is the correct failure mode but also means a slow child silently disappears from your batch.
The naming has accumulated compatibility weight. `fork`, `--golden` and `--forkable` remain aliases for the current terms. If you are writing tooling against this CLI, treat the aliases as a signal that the vocabulary is still moving. Separately, `smolvm machine checkpoint` saves the same state as a durable `.smolcheckpoint` artifact, and the README points Rust developers at the `smolvm-checkpoint` crate, which provides incremental storage and verified file restoration without depending on the VM runtime.
Packing a configured machine into a portable artifact
The pack workflow addresses a different problem from branching: reproducibility without a Dockerfile. The README's argument is that you do not need a declarative build file to keep an environment. You set a machine up by hand, stop it, pack it, and push it to any OCI registry.
smolvm machine shell --name myvm
smolvm machine stop --name myvm
smolvm pack create --from-vm myvm -o myvm
smolvm pack push --file myvm.smolmachine ghcr.io/you/myvm:v1Anyone who pulls `ghcr.io/you/myvm:v1` boots the exact same machine. The artifact is a single `.smolmachine` file, and the README frames the whole thing as packing a stateful VM into one file to rehydrate on any supported platform.
There is a genuine tension here that the README does not resolve. The same project that rejects unknown Smolfile keys at create time, on the grounds that a typo should fail loudly, also offers a workflow where the environment is defined by whatever you happened to type into an interactive shell. Packing captures the result, but it does not capture the intent. For a one-off artifact that is fine. For a team that needs to review what changed between two image versions, the Smolfile is the reviewable path and the pack path is not. The README presents both without ranking them, and the right choice depends on whether your environment is a build output or a pet.
The registry side is real OCI, so `smolvm pack push` targets a normal registry namespace. The README's example uses ghcr.io, but nothing in the quoted text restricts it to that host.
Where smolvm is the wrong tool
The clearest limitation is the platform prerequisite on Windows. The README requires the Windows Hypervisor Platform feature to be enabled before smolvm.exe will run. On a locked-down corporate Windows image where you cannot toggle that feature, smolvm is not a fallback option; it is unavailable. The bundled krun.dll and libkrunfw.dll confirm that the release is shipping its own hypervisor-facing libraries rather than relying on something already present.
The second limitation is documentation coverage rather than capability. The README documents branch readiness, worker readiness, timeouts and release semantics in detail, but it does not document rollback. There is no described way to undo a branch, no stated behaviour for what happens to a child when the source is later modified, and no description of what `machine checkpoint` restore looks like from the CLI. The `smolvm-checkpoint` crate is mentioned as available for Rust developers, which suggests restore tooling exists at the library level, but the CLI surface for it is not spelled out in the README.
The third is the one that matters most for adoption decisions. The README documents three compatibility aliases for the branching vocabulary and shows a flag set that has grown to cover batch identity, per-child readiness and pool release. That is the shape of a feature still being designed in public. If your integration depends on `smolvm machine branch` behaving identically across minor versions, the aliases are a warning rather than a convenience.
Finally, the repository root contains a demo directory with training scripts and benchmark documents. That is evidence the project is used for GPU workloads, but the README's Smolfile key list includes `gpu` and `cuda` without explaining what hardware or driver setup they require. If GPU passthrough is your reason for looking at smolvm, the README alone will not tell you whether your setup qualifies.
smolvm compared with E2B, Microsandbox and plain containers
The search terms that surround this project include E2B, Microsandbox, OpenSandbox and Celesto AI, which is a fair map of the neighbourhood. E2B is a hosted sandbox service: you call an API and the sandbox runs on someone else's infrastructure. smolvm is the opposite arrangement. It is a CLI you install locally, it boots machines on your own hardware, and the README's Windows instructions are about enabling a hypervisor feature on your machine rather than about an API key. If your reason for wanting a sandbox is that you do not want to run untrusted code on your own laptop, E2B solves a problem smolvm does not attempt.
Against Microsandbox and similar local sandbox projects, the difference visible in this repository is the OCI and libkrun combination. smolvm pulls standard OCI images and runs them under libkrun with libkrunfw as firmware, and the Smolfile is TOML with a fixed key set that rejects unknowns. A sandbox that defines its own image format asks you to rebuild environments; smolvm asks you to reuse images you already have.
Against plain Docker or Podman, the difference is the kernel boundary and the branch primitive. A container shares the host kernel, and there is no equivalent of forking a running container's memory into eight independent children. The README's branch example, where a warmed-up Python process with an installed dependency tree is copied into eight workers, is not something a container runtime offers. That is the specific capability that justifies the VM overhead, and it is the capability with the most caveats attached.
Editorial conclusion
Adopt smolvm if you are running coding agents or batch workloads that need a real Linux kernel boundary, disposable machines, and the ability to fork a warmed-up environment into many children. Do not adopt it if you need a frozen CLI surface: the README documents compatibility aliases (fork, --golden, --forkable) that already carry legacy weight, and the branch semantics have grown flags for batch identity, worker readiness and release. Before committing, verify two things yourself on your target platform: that the install script path works for your architecture, and that your branch use case behaves as the README describes when the source has not reached its branchpoint, since a single --name branch never waits while a batch branch does.
Frequently asked questions
How do I install smolvm on macOS or Linux?
The README gives a single install line that pipes https://smolmachines.com/install.sh into bash. It also says you can download from GitHub Releases and place the binary into ~/.local/share/.
Does smolvm run on Windows?
Yes, according to the README. Download the windows-x86_64 release, which bundles krun.dll and libkrunfw.dll, unzip it, and run smolvm.exe. The Windows Hypervisor Platform feature must be enabled first.
What is a Smolfile in smolvm?
A Smolfile is a TOML file that declares a machine: image, resources, network policy, mounts, ports and setup commands. The README describes it as the equivalent of a Dockerfile or cloud-init file, but for a whole VM.
How many port mappings can a smolvm machine publish?
At most 64 concrete mappings. Port entries accept a single port, an explicit mapping like "8080:80", or equal-length one-to-one ranges like "5173-5180:5173-5180".
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/smol-machines-smolvm)