Virtual machines
Text

Virtual machines

A virtual machine (VM) is a persistent Linux computer of your own that runs on this machine, for you and your agents to work in. It has its own disk, its own private address and a user who may do anything inside it. VMs are what exe exists for: the rest of the desktop is there to make them, work in them and show what runs in them.

What a VM is for

For you:

  • A machine to build in. Install packages, write code, start servers. The user inside (dev) has passwordless sudo, and the VM is the sandbox boundary: you may install and run anything in it.
  • It stays as you left it. Stopping a VM keeps its disk, and starting it boots the same machine again. Only deleting a VM destroys its disk.
  • You reach it from where you work. A terminal in the browser, or ssh, scp and port forwards from your own terminal; see SSH from your own terminal.
  • What runs in it can go public. A port a server listens on inside the VM can get an HTTPS address on your own domain; see Publishing to the web.
  • A new one is quick. It is cloned from a base image and is usually ready in about ten seconds.

For a coding agent, such as Claude Code or Codex:

  • A sandbox of its own. The agent makes a VM, or takes one you name, and builds, runs and tests there: an isolated machine where it may install anything.
  • Everything has a command. VMs are made, started, stopped and deleted over HTTP or from a shell, and commands run inside one over plain SSH. From a shell or over HTTP, further down, lists them.
  • Notes to start from. Every VM has notes you write, and agents are told to read them before working in a VM they do not know.
  • The built-in agent works here too. A VM's Agent tab gives it a shell in that VM; see The coding agent.

Make a VM

Choose File → New VM…, or press New VM… in the Virtual Machines window.

The New VM dialog: a name, CPUs, memory, disk and the System pop-up

  1. Type a Name: lowercase letters, digits and hyphens. Only the name is required.
  2. Fill in CPUs, Memory (MB) and Disk (GB) if you want other sizes. Left empty they are 2 CPUs, 2048 MB of memory and a 20 GB disk, or the defaults you set on the VMs tab of Windows → Configuration.
  3. Pick the System: Debian 13, the default, or Alpine 3.24.
  4. Press Create. The VM is made and booted, and the dialog closes when it is ready to use.

The very first VM downloads the Debian base image (about 3 GB) once. Later VMs are cloned from it and boot in seconds. A VM's disk takes only the room its contents need on the host: 20 GB is how far it may grow, not space set aside.

Debian or Alpine

The System pop-up picks the VM's Linux.

  • Debian 13 is the default: apt, sudo, bash and systemd.
  • Alpine 3.24 is a lean guest for disposable experiments, a download of about 93 MB the first time. It runs OpenRC and apk, not systemd and apt. Its user's shell is ash and it has doas in place of sudo. Prebuilt glibc binaries do not run on its musl libc.

An Alpine VM can be made on a Linux host only: on macOS and on Windows exe refuses that system.

exe records which system each VM was made with. Chat, a chat pinned to the VM and the Agent tab are told it, so on Alpine they reach for apk and doas. Publish to GitHub… installs git with apt and expects a Debian VM.

The Virtual Machines window

Windows → Virtual Machines lists every VM with its state, its specs and, while it runs, its IP address. Click a column's heading to sort by it, and again to turn the order round. Each VM also has an icon on the desktop.

The Virtual Machines window listing two running VMs with their specs and IP addresses

  • Open a VM. Double-click its row or its icon; on a phone, tap it.
  • Stop shuts the VM down and keeps its disk. On a stopped VM the button is Start, which boots it again.
  • Delete asks Sure?: press it again within three seconds. The VM, its disk and its notes are then gone for good.
  • Refresh reads the list again, and New VM… opens the dialog.

Right-click a VM for its menu:

Menu itemWhat it does
OpenOpens the VM's window.
Open TerminalOpens the VM's window on its Terminal tab.
btopOpens the VM's process monitor in an 80×24 terminal window. It runs the VM's installed btop over SSH; press q to quit and close the window. A failed launch leaves its error visible. Only for a running VM.
Chat with this VMOpens the Chat window on this VM, once a chat backend is set up.
Stop or StartThe same as the row's button.
RestartStops a running VM and starts it again.
Copy IPPuts the VM's IP address on the clipboard.
Expose Port…Opens the VM's window on its Expose tab.
Publish to GitHub…Sends a folder of a running VM to GitHub; see Publishing to GitHub.
DeleteThe same as the row's button.

A VM in its own window

Double-click a VM to open its window. The line at its top shows the VM's state, then its IP, how much disk the VM really holds on the host (allocated space, not the sparse file's nominal size) and the guest's system with its version, read from the guest itself. At the right edge is the load average over one, five and fifteen minutes, refreshed every five seconds while the window is open.

A VM's window on its Services tab: the state, IP, disk and system, then the ports listening inside it and the addresses they are published at

TabWhat it is for
ServicesThe TCP ports listening inside the VM, each with a link that opens it, and the routes already published to the web. A server must bind 0.0.0.0, not 127.0.0.1, to show up here or to be exposed.
TerminalA full SSH terminal in the browser.
AgentTell the built-in coding agent what to build. It gets a shell in this VM and streams its work live.
ExposePublishes a VM port at an HTTPS subdomain; see Publishing to the web.
SessionsEvery chat pinned to this VM, agent runs included, each with a one-line summary a model wrote of what it accomplished. Click one to reopen it in the Chat window.
NotesFree-form notes about the VM, saved automatically. Agents are told to read them before working in an unfamiliar VM, so write down what runs where. Under them the tab shows what the built-in agent has remembered about the VM, with Forget, pressed twice, to erase it.

From a shell or over HTTP

Everything the windows do has a command. exe is typed on the machine that runs the daemon. The HTTP calls go to the address the desktop is served at, and are what an agent uses.

ToCommandHTTP
List the VMsexe lsGET /v1/vms
Make a VM and boot itexe create demoPOST /v1/vms
Start a stopped VMexe start demoPOST /v1/vms/demo/start
Stop it, keeping its diskexe stop demoPOST /v1/vms/demo/stop
Delete it and its diskexe rm demoDELETE /v1/vms/demo
Read its state and IPexe ip demo prints the IPGET /v1/vms/demo
Read or replace its notesnoneGET or PUT /v1/vms/demo/notes
Open a shell or run one command in itexe ssh demo or exe ssh demo uname -anone: use SSH
  • Sizes and system. exe create takes -cpus, -mem (MB), -disk (GB) and -image alpine. Over HTTP the body is JSON, and only name is required: {"name":"demo","cpus":2,"memory_mb":2048,"disk_gb":20,"image":"alpine"}.
  • Create and start wait. Both answer only when the VM has booted, has an IP and answers SSH, so what they return is usable at once. Allow ten minutes or more when the first VM still has the base image to download.
  • The token. When api_token is set, every HTTP call carries Authorization: Bearer <token>; see Configuration.
  • Errors are JSON, {"error":"…"}: 404 for a VM that does not exist, 409 for one that is not running, 503 on a machine that cannot run VMs.
  • Commands inside a VM go over the daemon's SSH gate, which starts a stopped VM by itself: ssh -p 2222 demo@this-host 'uname -a'. See SSH from your own terminal.

Help → Agent Skill Guide… is all of this written for an agent, served at /skill.md. How VMs Work, on the website, says what a VM is made of on Linux, macOS and Windows.

When exe restarts

On Linux, where systemd runs exe, the VMs keep running when the daemon restarts: after an update, after Restart in the desktop and after systemctl --user restart exe. The next daemon takes each running VM over as it is. What runs inside does not notice, and a site published from a VM answers again as soon as the daemon is back.

  • To stop a VM, use exe stop demo or its window, as before.
  • A shutdown of the host stops the VMs first, and they start again when the daemon comes back.
  • systemctl --user stop exe leaves the VMs running as well. Stop them first with exe stop when they should not run on without the daemon.
  • The daemon stops the VMs with it, as it did before, in two cases: the exe on disk is an older one that could not take them over, or the unit has no KillMode=process. journalctl --user -u exe says which.

On macOS and on Windows, and when you start exe serve by hand, the VMs run inside the daemon. When it stops or restarts, they shut down with it, and the ones that were running start again when it comes back.

A machine that cannot run VMs

A node without a hypervisor (a NAS, a container without /dev/kvm) runs the desktop without VMs. The Virtual Machines window stays empty and says why: This node cannot run VMs, followed by the reason. Apple menu → About This Computer gives its VM memory as unavailable on this node. Everything else works as usual. Running without VMs, on the website, has more.

Contents