omarchy-microsandbox

August 22, 2026 · View on GitHub

An Omarchy shell plugin for managing microsandbox microVMs from the bar.

The bar shows a cube with the number of running sandboxes. Click it for a keyboard-friendly panel that lists every sandbox msb knows about, with the image, CPU and memory allocation, published ports, and age of each one. From there you can start, stop, and remove sandboxes, open a shell into a running one, or follow its logs — all without leaving the desktop.

Features

  • Running sandbox count in the bar; greyed out when nothing is running or msb is missing
  • Panel listing all sandboxes, running ones first, each with image · ports · resources · age (a forward reads as 8080→80; loopback and tcp are the defaults and stay implicit)
  • Start / stop a sandbox inline, with a pending state while msb works
  • Open a shell (msb ssh) or follow logs (msb logs -f) in a terminal window
  • Remove a sandbox with a confirmation step; a running sandbox is stopped first (msb rm --force)
  • Detects msb in ~/.local/bin and ~/.microsandbox/bin as well as on PATH
  • Points at the official install guide when msb is not found (the plugin never downloads or runs remote code)
  • Everything is keyboard-driven; r refreshes, Esc closes

Requirements

  • Omarchy with the Quickshell desktop (omarchy-shell)

  • microsandbox msb CLI — follow the official install guide. The plugin does not install it; it looks for msb on PATH, in ~/.local/bin, and in ~/.microsandbox/bin. microsandbox needs KVM on Linux — run msb doctor once to check the host.

  • jq (ships with Omarchy) — used to merge the two msb listings into one status read

Install

omarchy plugin add https://github.com/ya-luotao/omarchy-microsandbox.git --enable

The plugin lands in the right section of the bar. Move it with omarchy bar move luotao.microsandbox, or drag it around in Setup > Bar.

To install by hand instead, clone or copy this directory to ~/.config/omarchy/plugins/luotao.microsandbox/, then:

omarchy-shell shell rescanPlugins
omarchy plugin enable luotao.microsandbox

Remove

omarchy plugin remove luotao.microsandbox

That disables the widget and deletes the checkout under ~/.config/omarchy/plugins/. The plugin keeps no state of its own: its only setting lives on the widget's entry in ~/.config/omarchy/shell.json, which omarchy plugin remove drops with the entry. It never touches your msb installation or sandboxes.

Keyboard

Inside the panel:

KeyAction
j / k, arrowsMove the cursor
Enter / SpaceStart or stop the selected sandbox
sOpen a shell in the selected sandbox (running only)
gFollow the selected sandbox's logs
xRemove the selected sandbox (asks first)
rRefresh
iOpen the install guide (when msb is missing)
EscClose

In the bar: left click opens the panel, right click refreshes.

Settings

Set in ~/.config/omarchy/shell.json on the widget's entry, or through Setup > Bar:

KeyDefaultMeaning
refreshIntervalSec15How often to re-read the sandbox list (5–3600)
showCounttrueShow the running count next to the bar icon

IPC

The panel registers the luotao.microsandbox IPC target:

omarchy-shell luotao.microsandbox toggle
omarchy-shell luotao.microsandbox refresh
omarchy-shell luotao.microsandbox start devbox
omarchy-shell luotao.microsandbox stop devbox
omarchy-shell luotao.microsandbox status     # prints the summary line

Bind a key in ~/.config/hypr/bindings.lua to summon it, for example bind("SUPER", "M", "omarchy-shell luotao.microsandbox toggle").

Optional: a menu entry

Menu rows cannot ship inside a plugin, but one line in ~/.config/omarchy/extensions/omarchy-menu.jsonc adds a row that opens the panel from the Omarchy menu:

"microsandbox": {"icon":"󰆦","label":"Microsandbox","when":"command -v msb >/dev/null || [[ -x $HOME/.local/bin/msb ]]","action":"omarchy-shell luotao.microsandbox toggle"}

How it works

microsandbox has no daemon, so the plugin polls the CLI. Each refresh runs one bash -c that calls msb ls --format json and msb ps -a --format json and merges them with jq into a single {ls, ps} document — ls carries created_at, ps -a carries the CPU, memory, and port allocation. Model.js turns that into rows; Service.qml owns the processes, timers, and a watchdog that reaps a hung msb; Panel.qml is the bar button and the panel.

msb is treated as untrusted input, and nothing it prints ever reaches the filesystem. Each listing streams through head -c into a shell variable, so a run that overruns 4 MiB is cut off at the cap and rejected before jq sees it; stderr streams through tail -c so only its last 4 KiB is ever held; msb's exit status rides along as a trailing marker line. The parser then accepts at most 500 rows per listing and bounds every string it keeps, and lifecycle actions return only the tail of their output. No temp files means no predictable paths to pre-create, nothing to chmod, and nothing a killed poll can leave behind. Every panel text that shows msb-derived data is Text.PlainText, and strings that reach shared components (hero, confirm dialog) are stripped of control characters and markup first.

Sandbox statuses are the Rust Debug form msb prints: Running and Draining count as running, Crashed is flagged, and Created / Starting / Paused render as in transition.

Development

./test/model-test.sh        # Node tests for Model.js against fixtures in test/fixtures/
./test/script-test.sh       # runs the generated bash against a hostile fake msb
omarchy plugin validate .   # manifest and entry-point checks (needs jq)

Saving any file under ~/.config/omarchy/plugins/ hot-reloads the plugin, so symlinking a checkout there is the quickest way to iterate:

ln -s "$PWD" ~/.config/omarchy/plugins/luotao.microsandbox
omarchy-shell shell rescanPlugins

Note that omarchy plugin add refuses symlinks inside a plugin folder, but a symlinked plugin directory is fine for local development.

License

MIT