Desktop

Components

#A desktop in a sandbox

A sandbox made from the desktop image has a screen: a window manager, a terminal and Chromium, which you see and use in Studio's Desktop tab. It is for what a terminal cannot show — a page an agent is building, a site to click through by hand, a program with a window — and for watching an agent that drives a browser.

#Making one

sandbox-cli run --keep --name desktop \
  --image ghcr.io/amitgb14/sandbox-desktop:edge --memory 2048 -- true

Then open it in Studio (sandbox-cli studio), choose the Desktop tab and Start desktop. The screen appears a second or two later. Closing the tab leaves the desktop running; opening it again joins it where it was, and two viewers may watch at once.

Give it 2 GiB or more: a browser in 1 GiB is slow, and runs out of memory on a heavy page. A browser that should reach the web needs a network that lets it (--network open, or an allowlist naming the sites).

The image is published with the base image, under the same tags: sandbox-desktop:edge from main, and :<version> and :latest from a release. It is the base image plus a screen, so everything in the base image — the agents, git, the toolchains — is there too.

#How it works

Studio tab (noVNC, Studio's own code)
   │  WebSocket /api/ws/desktop, binary frames
Studio's server (sandbox-cli studio)
   │  the API's tunnel, to a VNC display port only (5900–5999)
sandboxd ─── the guest's own loopback ─── x11vnc ─── Xvfb :1 ─── openbox, xterm, chromium

sandbox-desktop, in the image, starts a virtual display, the window manager, a terminal and the browser, and serves the display over VNC on the guest's loopback, port 5900, with no password. Started from Studio, it is an ordinary background process of the sandbox: it is in the process list, its output is in Logs, and stopping it (or the sandbox) stops the desktop.

Studio reaches that port the way sandbox-cli tunnel does, through the API, and draws the screen itself:

  • Only pixels and input cross. Studio's VNC client is part of Studio; the guest sends the screen and receives keys and pointer moves. Nothing the sandbox serves is shown as a web page on Studio's address, where it could run beside Studio's token — which is why this is not a general port forward in the browser.
  • VNC display ports, and VNC only. Studio's server bridges the VNC display ports, 5900 to 5999, and no other port, whatever a page asks for; and it bridges one only after the guest's first bytes are a VNC server's greeting (RFB 003.008). A port in the range that answers with anything else is refused before the browser is sent a byte of it. It takes Studio's token and refuses another origin, like every Studio call.
  • No new way in. The VNC server listens on the guest's loopback, which only the API's tunnel reaches — so only a caller allowed to use the sandbox. X11 forwarding stays refused: the guest never draws on your machine's display.

Chromium keeps its own sandbox where the guest kernel lets the sandbox user make a user namespace (the macOS backend's kernel does), as a second wall inside the VM. Where it does not, it runs without it rather than not at all; the VM is the boundary.

#Settings

sandbox-desktop reads two variables, set like any other for the process:

Variable Default
SANDBOX_DESKTOP_SIZE 1280x800x24 the screen: width x height x depth
SANDBOX_DESKTOP_PORT 5900 the VNC port; Studio's tab finds a desktop on 5900 to 5909

#More than one desktop

The Desktop tab shows every desktop the sandbox serves, not only the one it started: it looks for a VNC server on each of ports 5900 to 5909 (X displays :0 to :9 by convention) and offers each one that answers, by port, with Rescan to look again. So a desktop the image starts as it boots, or a display an agent starts to work in, can be watched beside it — an agent that runs Xvnc :2 -rfbport 5902 -localhost -SecurityTypes None shows up as port 5902. Keep such a server on the guest's loopback (-localhost): the tunnel reaches it there, and nothing else needs to.

#Recording

Record, beside the screen, records the desktop and saves the video to your computer when you press Stop (the button counts the time; the screen is outlined in red meanwhile). The file is <sandbox>-<port>-<time>.mp4, or .webm in a browser that does not make MP4 (Firefox), at the desktop's own resolution, 15 frames a second.

  • It records in your browser. Studio opens a second, view-only connection to the desktop and records the screen it draws there; nothing runs in the sandbox and the video is not stored anywhere but your download.
  • It goes on while you use the rest of Studio. Another tab of the panel, another sandbox or another page of the sidebar: a bar in the bottom right corner of every page shows what is being recorded and for how long, with its own Stop, and a red dot marks the sandbox's Desktop tab. It keeps its frame rate in a browser tab left in the background.
  • It ends at Stop, or when the desktop goes away, and saves what it has either way. Closing or reloading Studio's page loses it: the browser asks you to confirm that first.
  • The pointer is not in it. Studio draws the desktop's pointer over the screen, not on it, so the recording shows windows and what is typed, not the mouse moving.
  • A recording is held in the browser's memory until it is saved: an hour of a busy screen is a few hundred megabytes.

#Limits

  • It keeps the sandbox up. A running process counts as activity, so a sandbox with its desktop running never reaches its idle timeout, and is never suspended for it either. Stop the desktop, or terminate the sandbox, when you are done.
  • Fonts. The image carries Latin, emoji and the common DejaVu faces. Text in other scripts (CJK among them) shows as boxes until a font for it is installed in the sandbox.
  • No sound and no clipboard between the desktop and your machine.
  • Linux only, as every sandbox is.
Edit on GitHubdocs/desktop.md