Skip to main content
The boxd CLI lets you manage machines from your local terminal without SSH keys. Recommended for automation and coding agents. The surface is a nested tree. Top-level groups: machine (alias m), snapshots (alias snap), auth, manage, env, config, plus docs / completions / version. remove is the canonical delete verb everywhere (alias rm); common aliases are ls (list), info (get), ssh (connect). boxd new and boxd connect also exist at the top level as shortcuts for boxd machine new / boxd machine connect.
boxd <cmd> --help is the always-current reference for flags and subcommands, straight from your installed binary. Running bare boxd in a terminal drops into an interactive REPL (boxd (org)>) where you type the same commands without the boxd prefix, with tab-completion and arrow-key pickers for missing arguments.

Install

Installs the boxd binary to ~/.local/bin/boxd (macOS arm64, Linux x86_64/arm64). The client utilities — the bridge that brings your clipboard, local files, and browser into a machine (macOS Apple Silicon for now) — are built into the same binary; turn them on with boxd config set client-utils.enable true. It also drops a set of agent skills into ~/.claude/skills/boxd-cli for everyday CLI driving, plus setup skills that wire boxd into a GitHub repo end-to-end via webhooks. Re-run the installer any time to upgrade the binary and the skills together. (Claude Code only for now — see the Skills page if you want them on another platform.)

Authentication

Any command that needs auth auto-starts the login flow if no credentials are found. You can also authenticate via token:

API keys

For CI pipelines, scripts, or agent integrations where the browser login flow isn’t an option, mint long-lived API keys under boxd auth keys. The raw value is shown only once at creation time.
Every key is fenced to one org — it never grants account-wide access. Without --org, the key is fenced to your active org context. --kind member (default) acts as you within that org; --kind org is a userless service credential limited to the org’s shared machines (requires org admin). keys create writes the raw bxd_… value to stdout; the warning + id + expiry go to stderr. To put it straight into a GitHub secret without copy/paste:
The key never lands in shell history or scrollback. --json mode is also available for scripting:

Managing machines

boxd new myapp and boxd m ls are the top-level / short forms. machine new folds in fork (--fork) and snapshot restore (--from-snapshot):
See Suspend & resume for how the idle timers work. All commands accept --json.

State control

Three categories of state transition, all boxd machine <verb> <machine>:
  • pause / resume: warm. Freezes the VMM process, keeps memory, running processes, and open sockets intact. Resume is sub-millisecond. Same mechanism as auto-suspend, but user-triggered. Status becomes standby.
  • reboot / stop + start: cold. Kills the VMM process. Memory lost, takes ~2s.
Use pause for cost savings without losing state. Use reboot when you need a cold kernel/config restart.

Running commands

Exit codes are forwarded — if the remote command exits 42, boxd machine exec exits 42. The remote command’s stdout and stderr are surfaced separately on the local side, so shell redirects work as you’d expect:
PTY execs (--tty) are an exception — the kernel TTY layer merges stderr into stdout (that’s how terminals work), so everything arrives on local stdout and 2> filters won’t separate them.
The -- separator is required between the machine name and the command. Without it, tokens like sudo or apt get parsed as flags and the command errors out.

Interactive access

boxd connect drops you straight into an interactive shell on the machine over the boxd API — no SSH config, no host keys, no extra credentials. Auto-resumes paused or hibernated machines on demand. Exit codes forward; type exit or Ctrl-D to come back to your local shell.
Requires an interactive terminal — connect refuses to run in scripts, pipes, or other non-TTY contexts. For automation, use boxd machine exec instead:

Editor & SSH integration

The CLI keeps a managed block of Host entries in ~/.ssh/config automatically — every machine new, fork, list, remove, and rename refreshes it, so your SSH config stays in sync as machines come and go. There’s no separate command to run. After the first sync, <vmname>.boxd is reachable to plain ssh, scp, rsync, Cursor / VS Code Remote-SSH, JetBrains Gateway, Zed Remote, etc. — without per-machine hand-rolling:
Each machine is reachable on a dedicated SSH port (10000–30000 range) on the shared proxy IP, so each stanza carries a HostName, a Port, and a User line. The <vmname>.boxd alias bakes the port in for you — connecting to the bare <vmname>.boxd.sh hostname (port 22) instead reaches the proxy, not the machine (the old ssh boxd.sh management shell there is retired — use this CLI). The managed block is bracketed with # BEGIN boxd / # END boxd; nothing outside the markers is ever modified.

Copying files

Paths after : are relative to /home/boxd unless starting with /. Uploads stream automatically — no inherent file-size cap.

Proxy management

Every machine gets https://name.boxd.sh forwarding to its default port. Publish more ports — HTTPS subdomains or raw TCP/UDP forwards — all under boxd machine proxy.
Subdomain proxies are HTTPS-only. To expose a database, an SSH daemon, or any non-HTTP service, use a raw port forward (below).

Exposing raw TCP/UDP ports

Raw forwards live under the same machine proxy group — pass --raw. boxd opens a raw TCP or UDP port on the machine’s public proxy and forwards it straight to a port inside the machine, for anything that isn’t HTTP (databases, game servers, custom protocols). The public port is allocated for you; connect on the machine’s existing name.boxd.sh endpoint at that port. See Port forwarding for the concept.
Up to 3 raw forwards per machine. Re-adding a port you already forwarded keeps the same public port and just updates the protocol set. Forwards are owner-only and removed automatically when the machine is destroyed.

Snapshots

A snapshot captures a running machine’s memory + disk at a moment in time, replicated across a few workers. Create a machine from it near-instantly with machine new --from-snapshot.
Re-saving an existing name captures a new version (latest wins). Snapshots are fenced to the org context that created them and never cross an org boundary.

Checkpoints

A checkpoint captures a running machine’s memory + disk held on the machine’s own worker, restorable in place (the machine reboots into that exact state — same name, URL, and ports). Unlike snapshots they’re per-machine, not replicated, and never become a reusable image — they live and die with the machine. Use them as quick “save points” before a risky change.
Up to 10 checkpoints per machine. available: no means the checkpoint’s worker is no longer the machine’s worker (e.g. after a migration) — it can’t be restored until they line up again.

Integrations

Connect third-party accounts — GitHub, Linear, and Slack — under boxd manage integrations, and every personal machine in that org can use them. See Integrations for the full model.
connect prints an authorize URL for you to open in a browser — a human has to approve it. Integrations are fenced to one org: your own connection serves your private machines in the active org; --shared addresses the org’s connection for its shared machines (admin only).

Env vars & secrets

Set environment variables and secrets once; boxd injects them into every machine you own in that org. Plain vars are cleartext and readable back; --secret seals a value at rest (write-only). See Env vars & secrets for the full model (scopes, naming, injection).
To put a literal .env file on one machine (rather than an account-wide var), use boxd env push:

Billing

Every machine is 2 vCPU / 8 GB RAM / 100 GB disk, billed by usage — there are no fixed plans or shapes to pick. Your balance, usage, and payment live under boxd manage billing.
See Pricing for the rate card.

Organizations

If you belong to an organization, your active context decides which org a new machine is billed to and which machines list and connect see. Sharing a machine opens it to every member of the org.
  • The active org context is a per-device selection. boxd auth switch writes it locally; it is not synced to the web console or your other devices — each surface keeps its own. personal = your default org.
  • In an org context, boxd machine new creates a machine billed to the org but private to you; add --shared to make it visible to the whole org from birth.
  • boxd manage billing follows the active context — in an org it shows the org’s balance and usage.
  • Share / unshare is owner-only. Any member can connect to a shared machine; a private machine (personal or org-billed) is reachable only by its owner.
  • An org has three roles: owner, admin, and member. Owners and admins invite and remove members at /app/organizations — see Organizations.
Sharing a machine wipes its in-VM agent logins (Claude Code, Codex, OpenCode) the instant it goes shared, so a teammate with a shell can never read your personal tokens. Unsharing restores Claude automatically; Codex/OpenCode need a one-time re-login. Forking a shared machine gives you a private fork with your logins intact. See Share a VM for the full handoff.

Per-machine settings

Auto-suspend and auto-hibernate timeouts live under boxd machine config (you can also set them at creation with --auto-suspend-timeout / --auto-hibernate-timeout).

CLI settings

boxd config persists laptop-side CLI settings (kept in config.toml).

Shell completions

Tab-completes commands, flags, and your machine/snapshot/org/proxy/key names (fetched live). Set up automatically by the installer and on boxd auth login; to (re)install manually:

Open the docs

Global flags