Skip to content

Releases

v0.10.1

Choose a tag to compare

@benvinegar benvinegar released this 04 Nov 03:31

Fixes for Lima hosts reached over ssh, and for running the test suite in a terminal. Also adds an experimental OpenShell backend. No upgrade steps beyond the usual boxery upgrade-host.

Fixes

  • Lima on a remote Mac with Node from fnm or nvm. boxery new failed with only limactl start … failed, because the Lima backend ran bare node, which isn't on PATH in the non-interactive ssh session the controller uses. Backend scripts now always use the host's own Node, the one init recorded (#146, #158, fixes #143).
  • Lima on a remote Mac with Homebrew. Over non-interactive ssh, limactl from /opt/homebrew/bin wasn't found, and boxery new wrongly reported no base image; run: boxery-host build-base. On macOS, backend calls (and the ssh ProxyCommand) now add /opt/homebrew/bin:/usr/local/bin to the end of PATH. If a backend can't tell whether the base exists, it now says why, instead of reporting that the base is missing (#157).
  • The Lima ssh port with FORCE_COLOR set. The free-port helper printed the port with console.log, which wraps it in colour codes when FORCE_COLOR is set. The port was then rejected, and a confined Lima start failed with no free port. This also made npm test (and so npm publish) fail when run in a terminal, since the test runner sets FORCE_COLOR there (#156).

New: OpenShell backend (experimental)

boxery can now drive headless sandboxes on an OpenShell gateway, where OpenShell's policy limits what each sandbox can read and reach on the network (#152, #153):

boxery setup local --backend openshell
boxery --host restricted new demo --headless

It supports the shell, file, copy and background-job tools. Desktops, snapshots, forks, resize, pools and boxery grants aren't supported and are refused with an error. OpenShell manages credentials and network access itself. It has been tested on Linux only. See docs/openshell.md.

Upgrading

  • boxery upgrade-host, then update the controllers. The image layers haven't changed since 0.10.0, so desktop bases and existing VMs don't need a rebuild or a patch.

v0.10.0

Choose a tag to compare

@benvinegar benvinegar released this 04 Nov 02:14

This release requires a person to approve new VM access, adds GitHub Actions runners on pool VMs, and lets you see and patch VMs whose software is out of date. It also fixes ssh to VMs on remote hosts, which was broken in 0.9.0. Read "Upgrading" first.

Highlights

  • New access needs a person. boxery grant, agent-forward on, new --grant, fork --grants, pi's /vm grant and vm_grant all show what would be granted and ask for approval. The CLI reads the answer only from /dev/tty, defaults to No, and refuses to run without a terminal, so piping yes doesn't approve anything. Listing, revoking and re-applying existing grants don't ask. For cron, CI or pool setup, add GRANT_CONFIRM=off to a profile's config (#138, details).
  • GitHub Actions runners on your own host. Each job runs in a fresh pool VM, which is reset to its clean image afterwards. The GitHub token stays on the host, and the VM only gets a single-use JIT config (#141, docs):
    boxery new r1 --headless --layers github-runner && boxery pool add r1
    boxery runners token < token.txt
  • boxery runners once registers one runner with your own gh login, from wherever you run it. The host never holds a GitHub credential (#145).
  • See which VMs are out of date, and patch them in place. boxery ls has a GUEST column: current, outdated (older layers, built more than 30 days ago, or waiting for a reboot) or unknown. boxery patch NAME (or --all) runs the layers again inside a running VM: apt-get full-upgrade, the kernel, playwright-core, the pi and opencode CLIs, and node. It restarts the VM if needed. For pool VMs, it captures NAME@boxery-clean again, so later leases start patched (#137).

Security

  • Security updates in every VM, and MPTCP turned off. Every VM, desktop or headless, now runs apt-get full-upgrade (kernel included) when it's built. Before, VMs kept whatever the cached Ubuntu image had. MPTCP is turned off (net.mptcp.enabled=0) because of CVE-2026-98432, which has no fixed Ubuntu 24.04 kernel yet (#136).
  • The LLM proxy drops guest OpenAI billing headers. A VM can no longer pick another org or project with openai-organization / openai-project. Set them on the host with OPENAI_ORG_ID / OPENAI_PROJECT_ID in proxy.env (#147).

Fixes

  • ssh to VMs on remote hosts. In 0.9.0, a controller set up with boxery setup user@host wrote a KnownHostsCommand that ssh couldn't run, so every VM failed host key verification. Local hosts were fine. Existing profiles are rewritten the next time you run a command (#149).
  • Locks that hold on uutils coreutils. Ubuntu 26.04's default mkdir isn't atomic under a race. As a result, concurrent grants or revokes could lose an entry, and concurrent news could get the same network slot or port. Both now use an O_EXCL lock (#129, #134).
  • macOS: init no longer fails intermittently with Bootstrap failed: 5: Input/output error while launchd is still removing the old job (#132).
  • init refuses a HOME that isn't the account's, so it can't install services launchd or systemd would never load. Shell tests can no longer replace the real proxy on macOS (#140).
  • tokens.json is parsed again only when it changes, not on every proxied request (#147).

Other changes

  • e2e.sh checks first that grants can be approved. Without a terminal, it needs GRANT_CONFIRM=off in the profile and otherwise exits before creating a VM (#151).
  • Agent behaviour evals for the MCP server, under evals/: which vm_* tools an agent uses, and whether it follows instructions (#148).
  • Docs: a new README, tagline, hero diagram and promo video, and a research section that starts with hunk's test suite on macOS vs boxery VMs vs Docker (#128, #130, #131, #133, #135, #139, #142).

Upgrading

  • Upgrade the host before the controllers (boxery upgrade-host).
  • Scripts that run boxery grant without a terminal now fail. Either have a person run them, or add GRANT_CONFIRM=off to that profile's config. That setting turns off CLI confirmation for the profile, so use it only where an agent adding grants unprompted is acceptable. MCP and pi clients need a confirm dialog or elicitation to grant anything; pi's print mode can't approve.
  • Rebuild the desktop base, and patch or recreate existing VMs, to get the security updates and MPTCP turned off. Upgrading the host doesn't change the software inside existing VMs. boxery ls --refresh shows which ones are outdated, and boxery patch --all patches those that are running. Patching doesn't change the base itself: boxery build-base does that, and it refuses while desktop VMs or snapshots still depend on the old base. Desktops built before 0.9.0 also have no VNC password until they're recreated from a new base.
  • Controllers on 0.9.0 with a remote host get working ssh once they're updated. Nothing else needs to be done.

v0.9.0

Choose a tag to compare

@benvinegar benvinegar released this 02 Nov 18:18

A security-focused release. VMs get no access by default and are isolated from each other. It also adds a new backend, boxery cp, and lets agents ask you for grants. There are breaking changes, so read "Upgrading" first.

Highlights

  • LLM access is now a grant. VMs no longer get every LLM provider the host has set up. You give access per provider with boxery grant VM llm:chatgpt (or llm:openai, llm:anthropic, llm:ollama), and revoking takes effect on the next request (#111).
  • Agents can ask for grants. With the new vm_grant tool, an agent requests github, ssh-agent, env:VAR or file: access. You approve or decline in a prompt the agent can't answer. Boxery's own secrets, ~/.ssh and ~/.gnupg are always refused (#91, #109).
  • boxery cp copies files to, from and between VMs, including across hosts. It uses the same code as vm_copy (#87).
  • Multi-host in pi. pi now has --vm-host, /vm host, and a host parameter on every tool, matching MCP (#121).
  • Several backends on one machine. boxery host add exe local --backend exe adds one, with its own proxy port and services (#88).
  • Experimental boat.dev backend. boxery-host init --backend boat runs VMs as boat.dev sandboxes. It needs a paid boat plan (#80).
  • Newer toolchain in VMs. VMs get Node 24, and git 2.56 from the git-core PPA instead of Ubuntu's 2.43 (#89).
  • Smaller images on libvirt. Space freed in the guest is returned to the host, so snapshots, forks and pool resets stop copying deleted data (#100).

Security

  • SSH host keys are pinned for every VM and checked strictly, on every backend (#114).
  • Guests are isolated from each other.
    • libvirt: guests can no longer reach each other, the host, the LAN, the tailnet or cloud metadata (#113).
    • Lima on macOS: guests can reach only the proxy port on the Mac's loopback (#103).
  • Pool VMs get a new proxy token on each lease, and their grants are tied to that lease. A previous holder can't keep using them after the lease ends (#98).
  • The VM desktop requires a VNC password. boxery desktop sets a fresh one for each session (#110).
  • MCP over HTTP is locked down.
    • --no-auth only works on loopback addresses.
    • Tokens are compared in constant time.
    • vm_copy won't touch local: paths unless you pass --copy-root (#101, #108).
  • The Node download in the image build is checked against its checksum before it's unpacked (#107).

Other changes

  • Tool and listing cleanup, based on feedback from agents (#92):
    • lookups (list, shapes, grants, snaps, images, hosts) are only on vm_info;
    • the VM parameter is called vm on every tool;
    • listings use disk_size/disk_used and ssh_addr.
  • Upgrade rollback restores state too. A failed boxery-host upgrade now restores each profile's lease store and state files along with the code (#102).
  • Fixed: with several host profiles, each profile's init or upgrade rewrote the shared guest-to-proxy bridge, so the other profiles' VMs lost the proxy. Each profile now gets its own bridge (#119).

Upgrading

  • Upgrade the host before the controllers (boxery upgrade-host).
  • Existing VMs lose LLM access until you grant it: boxery grant VM llm:PROVIDER.
  • The legacy host is gone. Every host needs a registered name. If you still use the old root ~/.boxery profile, register it with boxery host add NAME --config-dir ~/.boxery. BOXERY_HOST and BOXERY_HOST_BIN are no longer read (#90).
  • The agentvm migration shims are removed (#83).
  • Node >= 22.13 is now required, on both the laptop and the host (#104).
  • Prompts or scripts that use the vm_* tools may need updating for #92 (lookups moved to vm_info, name → vm, renamed listing fields).
  • libvirt: VMs that were already running stay on the open network until you restart them with boxery stop NAME && boxery start NAME.
  • Cloud Hypervisor: run boxery pin NAME --from-guest once for each existing VM.
  • exe.dev: detach the account's default llm integration before you create or start VMs.

v0.8.0

Choose a tag to compare

@benvinegar benvinegar released this 02 Nov 17:29

A big release: headless VMs, two new experimental backends, background jobs, and much better MCP support.

Highlights

  • Headless VMs. boxery new NAME --headless (or vm_manage new {headless: true}) builds from the stock Ubuntu image without a desktop, and needs no build-base. Desktop VMs are still the default (#55).
  • Background jobs. Use boxery run --bg, jobs, logs, wait, kill and jobs --prune, or the vm_jobs tool in MCP and pi. Jobs survive disconnects and report real exit codes (#28, #36).
  • VM shapes. Pick a named size with --shape small|standard|large. You can define your own in ~/.config/boxery/shapes.json on the host (#29).
  • boxery resize changes a VM's CPUs, memory or disk after it's created (#26).
  • Host upgrades. boxery upgrade-host updates a host in place. It checks the result and rolls back if the checks fail. boxery version warns when the host is behind the controller (#66).
  • Live desktop in chat. In MCP Apps clients, the vm_view tool shows a VM's desktop inline, and you can take control of it (#56).

New backends (experimental)

  • exe.dev: run VMs on exe.dev from any machine with ssh, a Mac included (#30). ls now reports tunnel state, and the docs explain how to set up an always-on host (#45, #65).
  • cloud-hypervisor: Linux + KVM without libvirt. Each VM gets its own network isolation (#25).

Agent tools

  • vm_manage adds start, stop, resize, snap-rm, images, new --from, and size parameters (#33).
  • vm_lease lets MCP and pi agents lease VMs from the shared pool. Leases renew while the session is active and are released when it ends (#34).
  • vm_info is a new read-only tool, so clients that support annotations don't ask for approval on lookups (#35).
  • MCP progress notifications and structured output, sent only to clients that support them (#35).
  • vm_edit is atomic and checks for conflicts. It no longer needs Python in the guest (#44).
  • vm_copy streams transfers with bounded memory and cleans up properly when cancelled (#32).

Reliability

  • Host lifecycle operations are serialized, and work left behind by a crash is recovered. New: boxery-host reconcile (#24).
  • boxery-host has been rewritten from bash to Node (#48–#52).
  • Fixed a hang on Lima hosts when an operation started a VM (#26).
  • Screenshots fail with a clear error, instead of returning NaN sizes, when the desktop isn't ready yet (#63).

Upgrading

Stop running boxery-host processes before you upgrade from 0.7.0. The old locks don't coordinate with the new SQLite-based ones (#24).

v0.7.0

Choose a tag to compare

@benvinegar benvinegar released this 02 Nov 17:29

The first tagged release of boxery: self-hosted Linux desktop VMs for coding agents. Your agent stays on your laptop and gets vm_* tools that act on VMs on a machine you own.

Highlights

  • One-line MCP install. npx add-mcp boxery-vm adds the boxery MCP server to Claude Code, Codex, Cursor, VS Code and other MCP clients. It works over stdio, or Streamable HTTP for remote use (e.g. tailscale serve).
  • pi extension. pi install npm:boxery-vm gives pi explicit vm_bash, vm_read, vm_write, vm_edit and vm_copy tools, plus computer use and Chrome over CDP. pi's built-in tools still run locally.
  • Backends. libvirt/KVM on Linux, or Lima on a Mac (boxery-host init --backend lima + boxery setup local).
  • Multiple hosts. A single controller and MCP server can manage VMs on several hosts.
  • Images, snapshots and forks. All three are built on one image primitive (VM@LABEL), and it also handles pool resets.
  • Shared VM pool. Exclusive leases that expire on their own.
  • Grants. Give a VM ssh-agent, env or file access per VM, from the controller. http: grants inject credentials at the edge, so secrets never enter the VM.
  • --json output for the listing commands.
  • zip is now in the base image.

Breaking changes

  • The project was renamed from agentvm to boxery, and the npm package is boxery-vm. See Migrating from agentvm.
  • boxery run passes its arguments to the VM exactly as given, like docker exec. To run a shell line, use boxery run demo bash -c 'make test'. run also starts in ~/project now (#16).

Security

  • A security review led to fixes for a host command-injection bug in the controller transport. The LLM proxy also gets an allowlist and limits.
  • Grant revocation now tears down ssh-agent sessions.
  • Sandboxed ARM64 Chromium now works under Ubuntu's AppArmor.