Skip to content

systemstart/claude-microvm

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

claude-vm

Run Claude Code in an isolated NixOS microVM via microvm.nix (QEMU+KVM). Your project directory is mounted read-write at /work inside the guest via virtiofs — no root required.

Claude Code starts automatically on boot. Exiting claude shuts down the VM.

Prerequisites

  • Nix with flakes enabled
  • KVM support (/dev/kvm)

Quick start

# Build and run with current directory mounted at /work
make vm.run

# Mount a specific project directory
WORK_DIR=/path/to/project make vm.run

Usage from anywhere

nix run (no install)

# From the repo directory
WORK_DIR=. nix run

# From a local checkout
WORK_DIR=/path/to/project nix run /path/to/this/repo

# Directly from git
WORK_DIR=. nix run github:systemstart/claude-microvm

Install to PATH

nix profile install github:systemstart/claude-microvm

# Now available everywhere
WORK_DIR=/path/to/project microvm-run

As a flake input

Add as a dependency in another project's flake.nix:

{
  inputs.claude-vm.url = "github:systemstart/claude-microvm";

  outputs = { nixpkgs, claude-vm, ... }:
    let system = "x86_64-linux"; in {
      devShells.${system}.default = nixpkgs.legacyPackages.${system}.mkShell {
        packages = [ claude-vm.packages.${system}.vm ];
      };
    };
}

Then nix develop gives you microvm-run in the shell.

How it works

virtiofs (host directory sharing)

The host WORK_DIR is shared into the VM at /work using virtiofs. A virtiofsd daemon is started automatically as a systemd user service (claude-vm-virtiofsd-<id>, where <id> is derived from the work directory path) — no root or sudo needed. It runs unprivileged in a user namespace with UID/GID translation so files created inside the VM are owned by your host user.

Each work directory gets its own virtiofsd instance, so multiple VMs can run in parallel on different projects. The daemon persists between VM restarts for fast re-launches. Manage it with:

systemctl --user list-units 'claude-vm-virtiofsd-*'
systemctl --user stop claude-vm-virtiofsd-<id>

Sandboxing

The VM provides strong isolation from the host:

  • Filesystem — only /work is shared; everything else is VM-local and ephemeral
  • Processes — completely isolated (separate kernel)
  • Network — QEMU user-mode NAT; the VM can reach the internet but can't bind host ports

To let Claude Code run fully autonomously inside the VM (no permission prompts), add --dangerously-skip-permissions to the claude invocation in flake.nix.

Shutting down

Exiting Claude Code automatically powers off the VM.

Customization

Exposing ports

No ports are forwarded by default. To expose ports, edit flake.nix:

microvm.qemu.extraArgs = [
  "-netdev" "user,id=usernet,hostfwd=tcp::8080-:8080"
  "-device" "virtio-net-device,netdev=usernet"
];
networking.firewall.allowedTCPPorts = [ 8080 ];

Rebuild with make vm.

VM specs

Resource Default
RAM 4096 MB
vCPUs 4
Network User-mode (SLiRP)
Work dir Host directory via virtiofs (read-write)

About

claude-code running in a microvm.nix

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors