Give coding agents a disposable Omarchy desktop—without giving up your own.
Omarchy Plugin Lab gives coding agents a separate desktop for developing and testing Omarchy plugins, Hyprland integrations, Quickshell components, and native desktop behavior. The agent gets a real graphical session it can safely exercise; the user keeps control of the daily desktop.
It is built for the boundaries unit tests cannot settle: a fresh graphical login, a real compositor, global shortcuts, pointer input, shell lifecycle, hot reloads, and the artifacts needed to explain a result later.
The agent edits source and controls the harness from the host, but plugin code, desktop restarts, and user interaction run inside the disposable guest. Keyboard and pointer events go to the VM's virtual hardware—not to the user's active windows—and the result comes back as assertions, logs, and screenshots.
That separation lets an agent test disruptive flows without stealing focus, typing into the wrong application, or reconfiguring the user's live shell. The guest can be discarded after every run while the evidence remains available.
| Build | Prove in the lab |
|---|---|
| A Quickshell plugin | Install, enable, disable, re-enable, remove, and clean up in a real shell session |
| A Hyprland shortcut or UI control | The actual QMP key or pointer event reaches the visible control and has the expected effect |
| A hot-reloadable widget or service | The loaded runtime—not just the files on disk—matches the version and behavior you shipped |
An installer, package, systemd, or /etc change |
A local ISO installs and passes desktop acceptance from a fresh base |
The installed base remains clean. Every run uses a fresh copy-on-write overlay, while timestamped logs, state dumps, screenshots, and test artifacts stay available as evidence.
Initialize the default sibling checkouts and download the current published ISO with its checksum:
./bin/lab setupSetup clones the public Omarchy, ISO, and package repositories, applies the
versioned lab integration to the ISO test harness, and downloads roughly 6 GiB
for the ISO. Existing checkouts and ISOs are preserved. Use --no-iso to skip
the large download. Setup does not install host packages, build an ISO, create a
VM, or change the running desktop.
By default, these repositories are siblings named omarchy, omarchy-iso, and
omarchy-pkgs. If your layout differs, copy
lab.env.example to .lab.env and set absolute paths before
running setup.
Check that the selected source checkout, ISO harness, KVM, and dependencies are ready:
./bin/lab doctorExample output:
Omarchy Plugin Lab
Source: /path/to/omarchy
ISO: /path/to/omarchy.iso
Memory: 5120 MiB
SSH port: 127.0.0.1:2222
ok - official ISO checksum matches
ok - KVM acceleration is available
ok - source, harness, packages, and host tools are ready
Create the reusable installed base once:
./bin/lab prepareThen choose the smallest proof that answers your question:
| Goal | Command | Coverage |
|---|---|---|
| Source contracts and regressions | ./bin/lab fast |
Complete source suite in a disposable guest |
| Plugin lifecycle | ./bin/lab plugin |
Add, enable, disable, re-enable, remove, and configuration cleanup |
| A specific plugin behavior | ./bin/lab plugin /path/to/plugin/tests/lab/acceptance.sh |
A product-owned scenario in the real graphical session |
| Broad desktop regression | ./bin/lab accept |
Omarchy’s in-guest suite and shortcut smoke tests |
| Custom broad acceptance | ./bin/lab accept-host /path/to/plugin/tests/lab/acceptance.sh |
Your product-owned scenario alongside the broad regression suite |
| Manual inspection | ./bin/lab accept-keep then ./bin/lab shell |
A retained guest accessible over SSH |
Show the artifacts from the latest run:
./bin/lab latestNormal fast, plugin, and accept runs discard their copy-on-write VM disk
after the guest has stopped. The timestamped run directory stays in place with
its logs, screenshots, state dumps, and test reports, so the evidence remains
useful without retaining a roughly 0.5–1.3 GiB disk after every run.
Use accept-keep when you need a running guest for manual inspection. To keep a
stopped overlay for later forensic work, pass the explicit override:
./bin/lab accept --keep-overlayPreview how much space old throwaway overlays consume, then reclaim them:
./bin/lab clean --dry-run
./bin/lab cleanCleanup skips disks that belong to a running VM. It removes only per-run
run.qcow2 overlays; reusable base disks, ISO files, logs, screenshots, and
other evidence are preserved.
Copy host-tests/example.sh into the plugin repository,
then define omarchy_host_test() there. Product-specific scenarios and fixtures
belong with the product, not in this lab repository. The official ISO harness
sources the supplied scenario after the disposable guest boots from the
synchronized checkout.
press meta_l-spc
wait_for_guest_state "Omarchy menu opens" 10 ssh_session \
"hyprctl -j layers | jq -e '[.. | objects | select(.namespace? == \"omarchy-menu\")] | length >= 1'"
capture_console "success-menu-shortcut"The harness provides:
pressfor real virtual keys and chords through QMP.ssh_guestfor ordinary guest state andssh_sessionfor the active Wayland/Hyprland environment.wait_for_guest_statefor bounded machine assertions.capture_consolefor visual checkpoints saved beside the logs.host-tests/helpers/pointer.shandqmp_pointer_tapfor visible pointer or touch controls.
Before a supplied host test begins, the harness waits for the notification service, dismisses startup popups inherited from the reusable base, and verifies that the notification layer has closed. Notifications created by the test itself remain unaffected.
Drive the same route a user will take. An IPC call proves a backend path, not hit testing. A successful rescan proves file state, not a hot-loaded runtime. Pair every meaningful action with an observable assertion.
| Level | Command | Establishes | Does not establish |
|---|---|---|---|
| Source suite | ./bin/lab fast |
Parsers, scripts, QML, JavaScript, and regressions | Global shortcuts or a complete installation |
| Plugin | ./bin/lab plugin |
Current lifecycle behavior in Hyprland + Quickshell | Every Omarchy application or installation path |
| Scenario | ./bin/lab plugin /path/to/plugin/tests/lab/<test>.sh |
The concrete behavior the product-owned scenario asserts | Behavior it does not assert |
| Broad | ./bin/lab accept |
Core shortcuts and the complete Omarchy suite | Compatibility across mismatched ISO and source revisions |
| Installation | Local ISO → fresh base → accept |
Packaging, installation, fixed system files, and desktop behavior | Hardware not passed through to the VM |
See TESTING.md for the full release gate, runtime identity rules, and scenario recipes.
Use an ISO and source checkout from compatible revisions for broad acceptance. Use a focused plugin proof when installation-level coverage is unnecessary.
Ordinary plugin work does not need an ISO build. Build one when changing
packages, the installer, systemd, /etc, or other fixed system files:
./bin/lab buildSet the printed ISO path in .lab.env, then prepare a matching base and run
acceptance:
./bin/lab prepare --fresh
./bin/lab acceptStart local configuration from lab.env.example. The real
.lab.env remains untracked.
The default guest receives 5 GiB of memory and KVM acceleration, with SSH
forwarded only to 127.0.0.1:2222. A complete desktop acceptance run is
noticeable on a 16 GiB machine, but the host remains outside the guest’s
mounts, sockets, agents, secrets, and device list.
- Never run Omarchy repository test entrypoints in the logged-in host session.
- Never point
OMARCHY_LAB_SOURCEat/usr/share/omarchyor host~/.config. - Never pass host secrets, agents, sockets, home directories, or physical devices into the guest for ordinary plugin work.
- Preserve the reusable base and prior evidence; replace a base only with
./bin/lab prepare --fresh. - Run the clean, committed candidate you intend to share, and keep the README, manifest, CLI, and status output aligned with what that run proved.
