Commands · reference

vmlab down

3 min read · 2026-09-02 · vmlab 0.9

vmlab down stops the machines of the lab in the current directory, gracefully by default, and keeps their clones so the next vmlab up boots the same disks.

sh
vmlab down [OPTIONS] [VMS]...
OptionMeaning
[VMS]...Machines to stop. With none given, every machine in the lab.
--forceHard kill instead of the graceful ladder.
-h, --helpPrint help.

What it does

The verb talks only to a lab daemon that is already running; it never starts one. With no daemon it releases the lab at the supervisor, which reaps any QEMU, swtpm, virtiofsd or smbd process an earlier daemon left behind, prints `lab "<name>" is not running (any orphaned processes were reaped)` and exits 0.

Stopping is the mirror of up. A subset pulls in its dependents, and the waves run leaves first, so a domain controller outlives the members that need it to shut down cleanly. vmlab down dc01 therefore also stops everything that depends on dc01. Before any machine goes, the workspace syncer for each dev machine in the plan is stopped, so it does not spend its retry window looking for a guest that has gone. See Dev machines and the workspace syncer.

Each VM stops through the graceful ladder described in the lifecycle guide:

  1. A shutdown request to the guest agent, waiting up to 30 seconds for QEMU to exit.
  2. An ACPI power-down through the QEMU control channel, waiting another 30 seconds.
  3. A hard kill.

A container asks its init to signal the entrypoint and power off after the image's stop grace, then falls through to the agent and to a kill. --force skips the ladder and kills immediately; the guest gets no chance to flush, so a qcow2 clone can lose unflushed writes.

A full down (no machine names) also stops the bundled SMB server, so it does not hold its port against the next up, and then has the supervisor reap the lab daemon. That releases the lab's name: vmlab lab list no longer shows the lab, vmlab status says not running, and another directory declaring the same lab name, such as a second git worktree, can bring it up (see The lab name is already registered). The clones, snapshots and .vmlab/ stay. The next vmlab up starts a fresh daemon, so it reads vmlab.wcl as it is then, edits included.

A partial down keeps the daemon and the shares served for the machines still running. A daemon that outlives a partial down still holds the lab file as it read it; the next up replaces it if the file has changed and nothing is running (see Editing the lab file between runs). Use vmlab lab stop to do a full down by name from another directory, or vmlab destroy to remove everything.

A directory whose lab name is registered from another directory is refused with the same conflict as up (exit 5), so it cannot stop the other directory's machines.

Examples

Stop the whole lab, keeping clones:

sh
vmlab down

Kill one hung machine without waiting for the ladder:

sh
vmlab down --force buildbox

Exit status

Exit status is 0 when every machine in the plan stopped, and 0 when no lab daemon was running. A machine that fails to stop, or a lab directory that cannot be found, exits 1 (failed). A lab name registered from another directory exits 5 (conflict). A usage error exits 2.