The details
The rest of omabox help: names, networks, windows, waiting, idle boxes and more, as the CLI prints it.
NAME defaults to $OMABOX, else the current git repo's name, else "default". In an agent session
(Claude Code, Codex, `guard exec`) that name gets the session's id, myrepo-5cc72cdc: one box per
session, gone when its agent exits. OMABOX_SESSION= (empty) turns that off. A git worktree is named
by its own folder, so each worktree has its own box. -b NAME also goes before the command
(omabox -b NAME windows), for every command that takes it.
`omabox run` with no box up starts a throwaway box for the command, with the current repo
mounted as a discarded overlay (writes succeed, vanish at teardown), and tears it down after.
A box named with -b or $OMABOX must be up: `run` fails rather than start a throwaway. With a
box up, `run` uses it and the repo is read-only there (tests that write into the tree: down first).
--net isolated --allow PORTS on a throwaway `run` keeps tests off your real local services.
Every box has its own network (pasta): by default the internet, the LAN and your servers. Across
the box boundary use 127.0.0.1, not localhost; a box's servers appear on your 127.0.0.1 about a
second after they listen. --net isolated: a loopback and the --allow ports only.
`run` starts the command with the box's environment, not yours: --pass VAR hands it one of your
variables (a password too: never on a command line); --env-file FILE hands it a file's KEY=VAL lines
(a dev.env: read as data, nothing expanded; --pass wins); `keys --pass VAR` types one (never `-t`
for a secret: the process list shows it). --env KEY=VAL is the box session's, on `up`.
--no-shell: Hyprland only, no Omarchy shell (faster; no bar, tray or notifications).
--plugin PATH|ID: a shell plugin, read-only, enabled where its manifest says; `up` and
`restart-shell` warn when Omarchy's validator or the shell refuses it (`ls --json`: plugin_status).
--hyprland PATH: the box runs that binary (its folder mounted read-only at its own path) with the
box's aquamarine, so a build must link a libaquamarine soname the box has (checked before the box
starts); hyprctl and hyprpm stay the installed ones (a warning when the versions differ). `ls` and
`windows` name it. Compositor logic runs for real (layouts, focus, input routing, the Lua config,
IPC, protocols); DRM/KMS, real monitors, HDR/VRR, multi-GPU, libinput with real devices and the
session/suspend/lock paths never run in a box.
SEL picks one window: active, its address (0x...), pid:N, class:RE, title:RE, initialClass:RE,
initialTitle:RE (any case), or a word (its class or the class's last part, nautilus for
org.gnome.Nautilus, or part of its title); repeat to narrow. None or
several is exit 2, with the candidates (`wait window SEL` asks for a window like it: any of several
does, each named). `shot --window` (-w; --active is --window active) is the
window's own pixels, covered or on another workspace too; `click --window` takes the window's
coordinates and focuses it first when it is off screen or covered there (--no-raise refuses instead);
`keys --window` focuses it, then types. --fit N scales a shot's longest side down to N pixels.
-g "X,Y WxH" (or X,Y,W,H) crops: the screen's, or with --window the window's own coordinates.
A cropped or scaled shot says so on stderr: `click --in SHOT X Y` (and `drag`, `pointer --in`)
take that image's pixels (a window shot follows the window if it moved). Screen shots show the
pointer; window shots never do. -o makes the file's folder if it is missing.
The pointer starts at the screen's centre and stays where it was left; `click` and `pointer move`
jump there. --steps N travels in N steps from where it is, over what lies between: under Omarchy's
focus-follows-mouse the windows on the way take focus, as with a real mouse (`pointer --steps N --
move A move B` passes through A). --mod MODS (ctrl, shift, alt, super, altgr; ctrl+shift, or --mod
again) holds modifiers down across a click, drag or pointer run, released after it, whatever happens
to omabox. SUPER with the left or right button is Hyprland's move or resize window, not the app's.
`wait still`: nothing on screen changed for --quiet; a caret (4 px or thinner) and the cursor do not
count, and are said (--strict counts them). `keys`, `click` and `run -d` take --wait [--start 2s]
[--quiet 300ms] [--timeout 10s] [--json]: a change within --start (5s for run -d), then quiet.
Exit 0 satisfied, 124 not by --timeout (after --wait: the input WAS sent), 1 unknown (the box went
down, an interactive box's hidden window renders nothing): never 0 for what could not be seen.
Durations: 300ms, 2s, 1m; --timeout at most 10m. Waiting counts as using the box.
$OMABOX_READY_TIMEOUT: seconds `up` waits for Hyprland and the shell (default 30).
`lua` takes an expression or statements (`return` what to print); one line per value: strings and
numbers as they are, nil as nil, tables and Hyprland's objects (a window, a monitor) as JSON (--json:
strings quoted too). A Lua error is exit 1 with its message. An error inside a callback (hl.on,
hl.timer) that runs later is logged nowhere: catch it with pcall.
`log` prints the last -n lines (100) of each log named, of a box that died too; run is the latest
`run -d`'s, apps what Omarchy's launcher started, box bwrap's. -f follows them until the box goes
down (-n then counts lines before --grep). Hyprland writes its log in pieces: its newest lines can
come late.
`events`: what the box's Hyprland reported on its event socket (activewindow>>, urgent>>, ...) from
its start, never cleared. --mark MARK takes "from here" (a byte offset: safe while events come);
--since MARK (a mark, an offset, or 30s/2m/1h ago) reads from there. --grep and --until match the
EVENT>>DATA part (grep -E). --until: the first matching event from --since (or from now), printed:
exit 0, 124 none by --timeout, 1 the box went down; -f follows until the box goes down.
Interactive boxes and peek windows open on workspace 9, without focus: `omabox config workspace WS`
(1-99, special = Omarchy's scratchpad on SUPER+S, special:NAME) or --workspace. A peek window shows
click, pointer and keys for ~3 s (a ring, key captions, --pass values as *); never the box's own frames.
Closing an interactive box's window ends the box; `omabox config confirm-close on` asks first (a
second close is a yes).
aquamarine's fix for nested Wayland outputs (hyprwm/aquamarine#415, until a release has it): a
headless box on an NVIDIA render node and confirm-close need it, and `up` refuses them without it;
`omabox setup --aquamarine` builds it (a checkout's build/prefix, else ~/.local/share/omabox).
OMABOX_AQUAMARINE=system: the system's aquamarine all the same (testing).
SUPER + ALT + ESCAPE toggles sending SUPER keys to an interactive box, once:
until focus leaves it, or a key is pressed with the pointer off it. `keys-to-box on` makes them
follow focus and the pointer, for the box's lifetime: its window has focus and the pointer is over
it, SUPER is the box's; focus goes elsewhere or the pointer leaves it (your bar, another monitor),
it is yours, and the pointer back over it gives it to the box again. SUPER + ALT + ESCAPE over the box
gives the keys back until the box loses focus and gets it again. No argument prints on or off. While keys go to a box, its window's border takes the
theme's red and the bar widget's icon is lit.
`clip` hands your clipboard's item (text, else an image by its type) to an interactive box, once;
--from-box hands the box's back. With no -b: the interactive box whose window has focus, else the only
one. Never for agents (refused in their sessions, under the guard, in ai-jail). Nothing keeps
watching either clipboard. Bind it to a key in your Hyprland config to paste into the box you are in.
A headless box goes down after $OMABOX_IDLE (default 2h) with no omabox command against it, no
peek window and no `omabox run` still running; --idle 30m|2h|0 (never) per box. Interactive: never.
`run -d` says where the command's output goes (its log) on stderr: -q says nothing (errors still),
--print-log prints the log's path on stdout (first, before --wait's line). `run -d --replace`
first stops what `run -d` started in that box with the same command and arguments (SIGTERM to its
session, SIGKILL after 5 s) and waits for its windows to go: a rebuilt app in one step. Nothing
else in the box is touched: an app started some other way stays.
A `run -d` job is not activity: a server only polled over HTTP needs --idle 0 (or longer).
At --idle 0 a session's box still goes with its agent (`ls` says never); a box with another name
(-b NAME) stays.
Sizes: WxH is @60; `host` copies your focused monitor's size and refresh rate (scale stays 1).
Measure rendering cost with `omabox gpu` in a box whose mode matches your monitor.
The agent guard (opt-in) gives agents' shell commands (Claude Code, Codex) a display that does not
exist, so a window, hyprctl or grim outside a box fails instead of reaching your desktop; omabox
still works, and `omabox host` runs a command you asked for on the real desktop.
An agent inside ai-jail cannot enter a box: `omabox broker on` (a systemd user socket) lets its
omabox hand commands to omabox outside, which keeps the jail's boxes to what the jail has (its
project, its network or none) and to themselves. It prints the lines to add to ~/.ai-jail.
Crashes in a box skip the desktop's crash notifications (core limit 1 byte; raise it inside for a core).
A save keeps what a box's apps set up (signed in, a PIN, a library): the box HOME without .cache and
its logs, keyring included, paused for the copy. `up --from` starts with it, then seeds your Omarchy
look on top as for any box (theme, bar, terminals: today's, not the save's). Close an app first for a
clean save. Saves live in ~/.local/share/omabox/saves until `saves rm`.