How the Omarchy Test Suite Works: CLI, Shell, and Acceptance Testing
Omarchy's automated testing infrastructure is divided into three independent layers—CLI validation, shell plugin verification, and graphical acceptance testing—that execute via ./test/cli, ./test/shell, and disposable VMs through the omarchy-iso repository.
The basecamp/omarchy repository maintains a robust, multi-layered Omarchy test suite designed to validate everything from command routing to full desktop interactions. This testing pyramid separates concerns into fast headless checks and comprehensive graphical validation, ensuring reliable deployments across both CI environments and local development machines.
CLI Test Suite
The CLI test suite validates the command router, metadata linting, and theme pipelines located under bin/omarchy-*. It ensures that every binary exposes proper metadata headers and that the routing logic correctly handles help output and required arguments.
How CLI Tests Validate the Router
According to the source code in docs/testing.md, the ./test/cli script executes against a fake $HOME and a stubbed $PATH to verify routing behavior. The runner confirms that the omarchy command correctly resolves routes, loads metadata, and enforces required arguments as implemented in docs/cli-router.md. Additionally, it validates that every binary includes a proper # omarchy:summary= header and that omarchy commands --check passes metadata linting.
Running the CLI Tests
Execute the CLI suite independently using:
./test/cli
Shell Test Suite
The shell test suite exercises individual plugins, binary helpers, configuration invariants, and migration scripts without requiring a graphical environment. Tests reside in test/shell.d/*-test.sh and are coordinated by the ./test/shell runner.
The base-test.sh Harness
Every shell test begins with the same boilerplate that sources test/shell.d/base-test.sh:
#!/usr/bin/env bash
set -euo pipefail
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/base-test.sh"
The harness performs several setup operations:
- Discovers the repository root and exports it as
ROOT(accessible as$OMARCHY_PATH) - Creates a temporary
$HOMEusingmktemp -dfor test isolation - Prepends a stub
bin/directory to$PATHthat logs calls instead of executing side effects likesudo,tmux, orgsettings
TAP-Style Assertions
The harness provides test helpers that output TAP (Test Anything Protocol) format:
pass "description"— printsok - descriptionfail "description" [detail]— printsnot ok - descriptionand aborts the current test filerequire_command <cmd>— fails the file if a required external tool is missing
Because fail exits only the current test file with set -e, the ./test/shell runner continues executing remaining files and aggregates failures at the end, providing per-file granularity.
Compositor Gating for Headless CI
Tests requiring a Wayland compositor call require_compositor "reason". When no compositor socket is available, the helper prints a skip message (ok - no Wayland compositor; skipping …) and exits 0, which TAP treats as a passing test. This design keeps the Omarchy test suite green on headless CI runners while enabling comprehensive tests locally.
Node.js Unit Testing from Bash
Pure JavaScript modules—such as shell/plugins/menu/MenuModel.js—are tested via the run_node_test helper. This function injects a small JS prelude that mirrors the Bash assertions, allowing the same pass/fail output for logic that would otherwise require a running compositor.
Graphical Acceptance Test Suite
The acceptance layer validates end-to-end behavior requiring a real compositor (Quickshell or Hyprland), including panels, keyboard shortcuts, real applications, and system setup flows.
VM-Based Testing with omarchy-iso
Acceptance tests run inside disposable VMs managed by the sibling omarchy-iso repository. The harness drives the compositor via QMP and uses wtype for typing simulation.
To test against an existing installation with your current checkout synced:
cd ../omarchy-iso
./bin/omarchy-iso-test release/<iso>.iso --reuse-base --sync-omarchy ../omarchy --no-preview
For testing changes that affect the installer or shipped defaults, build a fresh ISO without --reuse-base:
./bin/omarchy-iso-make --no-boot-offer --local-source ../omarchy ../omarchy-pkgs
./bin/omarchy-iso-test release/<generated-iso>.iso --no-preview
Test Structure and Screenshot Capture
Acceptance tests reside in test/acceptance.d/*-test.sh and follow the same base-test.sh contract as the shell suite. Each test records artifacts for CI analysis:
- Screenshots named
success-<step>.pngorfailure-<step>.pngfor each step - Comprehensive logs collected under
test-runs/
The VM harness follows the guidelines in agents/skills/acceptance-tests.md to orchestrate compositor-level shortcuts and application interactions.
Running the Full Test Pyramid
Execute all headless suites sequentially while continuing past individual failures:
./test/all
This runs ./test/cli first to validate routing and metadata, then ./test/shell to verify plugins and migrations, finally printing a summary of any failures. This aggregation ensures hidden problems are not masked by early aborts.
Summary
- The Omarchy test suite is organized into three layers: CLI validation, shell testing, and graphical acceptance.
- CLI tests in
./test/cliverify the router and metadata headers using stubbed$HOMEand$PATHenvironments. - Shell tests use
test/shell.d/base-test.shto provide TAP-compatible assertions, temporary$HOMEisolation, and stubbed binaries. - Compositor-dependent shell tests gracefully skip on headless systems via
require_compositor, maintaining CI compatibility. - Acceptance tests require the
omarchy-isorepository and run in disposable VMs with automated screenshot capture via QMP andwtype. - Execute the complete headless suite via
./test/allto validate routing, plugins, migrations, and configuration invariants.
Frequently Asked Questions
How do I run only the CLI tests in Omarchy?
Execute ./test/cli from the repository root. This script validates the command router against a fake $HOME, checks that every binary in bin/omarchy-* contains a proper # omarchy:summary= header, and verifies that omarchy commands --check passes metadata linting.
What is the purpose of base-test.sh in the shell test suite?
The test/shell.d/base-test.sh file provides the common harness that every shell test sources. It creates a temporary $HOME via mktemp -d, sets OMARCHY_PATH="$ROOT" to the checkout root, and builds a stub bin/ directory that logs calls to prevent side effects. It also exports pass, fail, and require_command functions that output TAP-compatible results.
Can the Omarchy test suite run without a graphical environment?
Yes. Both the CLI and shell suites run headless on standard CI runners. Shell tests that require a Wayland compositor call require_compositor, which skips the test gracefully when no socket is available, allowing the suite to pass on headless systems. Only the acceptance tests require a running compositor inside a VM.
How are JavaScript modules tested within the shell suite?
The run_node_test helper executes Node.js unit tests from Bash by injecting a prelude that mirrors the shell assertion protocol. This enables testing pure JavaScript logic—such as shell/plugins/menu/MenuModel.js—without spinning up a full graphical environment, outputting pass/fail results in TAP format that the shell runner can aggregate.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →