~/msb-manager$docs v0.2.0 github

Everyday use

The current folder names the sandbox#

Like docker compose, msbctl works out which sandbox you mean from where you are. Inside a registered project folder, or any folder below it:

terminal
$ msbctl shell                   # this folder's sandbox
$ msbctl exec -- make test       # run one command in it
$ msbctl exec . make test        # the same; "." means "this folder's sandbox"
$ msbctl stop                    # start, rebuild, update, reclaim and purge too
$ msbctl stop . other-sandbox    # "." mixes with names
$ msbctl allow . example.com     # "." where more arguments follow

It is designed never to guess:

  • The registry decides. The sandbox is the registered one whose project folder contains your current directory. If projects are nested, the deepest one wins, the way git finds a repo. A .msb/ folder on its own isn't enough: a fresh clone of a project that commits .msb/ isn't registered on this machine.
  • The name can be left out only when it's the only argument. Where another argument follows (exec, allow, observe, mount, …), the name is still required, and . is the shorthand for it. . can never be a sandbox name, so msbctl observe on can't silently mean a sandbox called "on".
  • It tells you what it picked. On a terminal, a dim name (~/path) line goes to stderr. Piped output stays clean.
  • It stops when it can't decide. Two sandboxes registered on the same folder, a .msb/ with no registered sandbox, or a folder outside every project: each is an error that says what to do.

shell and exec also start in the matching subfolder: from ~/proj/src you land in /work/src.

shell, exec, code#

terminal
$ msbctl shell myproject                  # bash -l, SSH agent wired up
$ msbctl exec myproject -- npm test       # one command
$ msbctl code myproject                   # your editor on the project, on the host

shell and exec start a stopped sandbox first, but they never create one: creating is the one step that runs the bootstrap and fixes the network policy, so it should never happen as a side effect. Use msbctl start (or msbctl rebuild) for that.

code opens $MSB_EDITOR (default codium) on the project folder on the host, detached from the terminal. The editor works on the same files the sandbox sees.

Looking around#

terminal
$ msbctl ls              # one line per sandbox: state, project, pending updates
$ msbctl status          # one block per sandbox, with RAM and CPU figures
$ msbctl show            # everything about one: resources, versions, every egress rule
$ msbctl config          # the merged configuration, and where each value came from

msbctl show is the first thing to read when a sandbox behaves strangely. It lists the resources, disks and extra folders, the installed versions, the environment, every egress rule in order, and the git identity, SSH keys and secrets that are bound.

The menu#

Bare msbctl opens a menu: register a project, manage sandboxes, machine setup, your CLAUDE.md additions, and refreshing version info. With fzf installed it's a full-screen list with a live status sidebar; without it, a numbered prompt offering the same actions.

The picker#

Manage sandboxes in the menu, msb-picker, and the Sandboxes desktop entry all open the picker. It lists every registered sandbox with its state and what's out of date inside it, and binds a key to each action:

KeyAction
enteropen the editor on the project (msbctl code)
tshell
s / xstart / stop
eedit, one wizard section at a time
uupdate claude, gh and apt packages
lreclaim memory
frefresh version info
nregister a new project
R / Drebuild / purge (capitals, so a slip of the finger can't destroy anything)
space, aselect one, select all; most actions apply to every selected row
j / k, qmove, quit

Sandboxes marked autostart are started when the picker opens, so their state and versions are current by the time the list appears. Set MSB_NO_AUTOSTART=1 to skip that.

Stop, start, rebuild#

CommandWhat survives
msbctl stop / starteverything: packages, state, files
msbctl rebuildyour files, the Claude state, package caches and container images. Packages installed by hand are lost; the bootstrap reinstalls its own
msbctl purgenothing but your project folder. It asks first and lists exactly what it will delete

Rebuild whenever something that is fixed at create time changes: egress rules, mounts, the image, environment variables. cpus, memory and the root disk don't need one (msbctl resize).

Keeping a sandbox current#

terminal
$ msbctl ls --refresh                 # check upstream versions
$ msbctl update -c claude gh apt      # update in place, no rebuild

What update installs is recorded in the sandbox's registry entry, so a later rebuild reproduces it instead of quietly reverting.

Memory#

The VM's memory setting is a ceiling, not a reservation, but the guest's page cache is never given back on its own, so a sandbox that builds a lot drifts up to its ceiling and stays there. That's harmless, and takes about a second to fix:

terminal
$ msbctl reclaim