sb run

The in-guest command that puts any app on a copy's screen, and the three caches on your Mac that make the second run instant.

sb is the small CLI inside every copy. Its one job is to run an app on the desktop.

sb run [--json|--quiet] <app> [args…]

What <app> can be #

  • A bare name resolves against nixpkgs: sb run htop runs nixpkgs#htop, sb run firefox runs Firefox, sb run xorg.xeyes runs an attribute path.
  • A flake reference (anything with #, : or /) is passed through unchanged: sb run github:owner/repo#pkg.
  • Anything already on PATH runs directly, without asking Nix at all.

Unfree packages are allowed by default. A copy is a sandbox meant to run anything, Chrome and Slack and Obsidian included.

What happens #

  1. sb realises the package first, and shows progress. A multi-minute download is visible rather than silent.
  2. It exports the desktop environment (Wayland display, XDG runtime, HiDPI settings, the toolkit backends), because it may be called from a non-login shell.
  3. It applies a small table of per-app quirks, flags some apps need to behave under this compositor.
  4. It runs the app. In an interactive terminal the app is in the foreground; when the host calls it, the app is detached and its output is kept in a log inside the copy.

GUI apps appear on the copy's screen. CLI apps run in the terminal.

Where packages come from #

Three layers, all on your Mac's disk, all shared by every copy:

LayerPath on the MacWhat it is
Pull-through cachenix-cache/A caching proxy in front of cache.nixos.org. It never signs anything; it only stores what upstream already signed.
Shared storeshared-store/The packages themselves, mounted read-only into every copy as the lower layer of its /nix/store. One Firefox on disk, however many copies run it.
Guest-built cacheguest-cache/Closures a copy had to build itself because nothing upstream had them. The next copy substitutes instead of rebuilding.

All three live under the app's state directory; see Paths, ports, logs.

The guest image itself stays thin. Baked in: the compositor, sb, a terminal, git, curl, Nix, the GPU tooling. Not baked in: applications. A copy never keeps its own copy of an external package.

Network #

A cold package needs the network: copy → the copy's own user-space NAT → the cache on your Mac → cache.nixos.org. A package that is already in the shared store runs without it.

From an agent #

The sb_run tool types the command into the copy's foreground terminal and presses Return. It launches and does not wait. When the agent needs output back, it uses exec instead.