For people changing Ruixen rather than using it: where things live, how it
plugs into Omarchy, the dev scripts, and how to test. The repo-wide rules for
humans and coding agents are in AGENTS.md at the repository
root: read that first, it's the actionable development contract. User-facing docs are in
docs/.
Ruixen is a set of plugins that load inside Omarchy's existing, long-lived
Quickshell process. Nothing here starts its own shell. Each plugin is a
directory with a manifest.json (an Omarchy plugin id such as ruixen.bar)
and a QML entry point that is an Item, not a standalone ShellRoot.
Overlay-kind plugins (launcher, shelf) expose the lifecycle the host expects:
open(payloadJson), close(), toggle(payloadJson).
Control goes over omarchy-shell <target> <method> (see
docs/CONTROL.md); shared state lives in small
versioned files under ~/.local/state/ruixen/. AGENTS.md §1-§4 holds the
actual rules, including which Omarchy internals not to depend on.
bars/v2/ruixen.bar/ the bar, the screen frame, docked chrome
bars/widgets/ruixen.*/ bar widgets and the notch (ruixen.notch)
ruixen.launcher/ launcher, Search Files, Settings, and extensions/ (Clipboard,
Theme browser, Cliamp Radio, Wallpaper Shuffle, ...)
ruixen.shelf/ the drop-pocket overlay
ruixen.wallpaper/ video/GIF playback and artwork rotation
ruixen.background/ optional native static wallpaper renderer
ruixen.cava/ audio visualizer overlay
hyprland/ window look'n'feel variants + ruixen-lookfeel.sh
theme-overlays/ per-theme tweaks applied on install
lib/ installer helpers (shell.json merge, restore, lock, journal)
install.sh update.sh lifecycle scripts (all have --dry-run)
uninstall.sh
ruixen-doctor.sh read-only diagnostic report
ruixen-repair.sh redeploys drifted plugins via install.sh
dev/ developer helper scripts (below)
tests/ contract, model and lifecycle tests; run-all.sh
docs/ user manual
preview/ README images
Where a given feature lives: the bar and frame in
bars/v2/ruixen.bar/ (Bar.qml, BarPanel.qml, FrameWindow.qml); the
notch and its Kanban/wallpapers/health tabs in
bars/widgets/ruixen.notch/Overlay.qml; the launcher in
ruixen.launcher/Launcher.qml with each extension under
ruixen.launcher/extensions/; the Settings app in
ruixen.launcher/extensions/settings/; the Shelf in ruixen.shelf/.
The bar, notch and Shelf are one visual surface by design: read AGENTS.md
§9 before touching any of them.
| Script | What it does |
|---|---|
dev/ruixen-bar-mode.sh docked|floating|status |
Switch the bar between merged (docked) and separate (floating) pills; live, no restart |
dev/ruixen-bar-style.sh notch|fullbar|status |
Switch between the notch skin and the full-width statusline skin |
hyprland/ruixen-lookfeel.sh on|half|square|off|status |
Window corner/blur variants |
./ruixen-doctor.sh |
Read-only report: git state, plugin drift by content hash, bar layout, runtime health, clipboard capture |
./ruixen-repair.sh [--dry-run] |
Redeploy plugins that drifted from this checkout |
The first two are described for users in
docs/CUSTOMIZATION.md.
- Edit in a checkout, run
./install.sh --dry-runto see what a deploy would change, then./install.shto deploy it. - For runtime, QML or IPC changes do a real
omarchy restart shellrather than trusting hot reload, and checkjournalctl --user -b 0foris not a type,Type ... unavailable,TypeErrorand binding loops.tests/qml-lint.sh(issue #107) catches real parse/syntax errors and a broken local relative import (import "File.js"), but it cannot resolve Quickshell/Omarchy's own modules without a real desktop, so a renamed/broken sibling component reference or anything about actual runtime/compositor behavior still only ever shows up via a real restart + journal check -- see that script's own header for exactly where the line is. omarchy plugin validate <plugin>after manifest or structure changes.- Run the tests (below) before pushing.
The full checklist, with the incidents behind each item, is AGENTS.md §8.
Wallpaper implementation lessons are documented in
WALLPAPER-LESSONS.md, with verification evidence in
WALLPAPER-AUDIT.md.
COMPATIBILITY.md is the ledger of which Omarchy and
Quickshell versions have actually been reviewed. Don't bump its reviewed
versions until that version has really been reviewed; a bump is a claim of
verification.
./tests/run-all.shRuns almost everything CI runs (.github/workflows/ci.yml) in one go:
shell script lint (bash -n + ShellCheck, when installed), QML lint
(qmllint, when a real Qt 6 one is found locally -- CI always has it),
plugin manifest validation, the JS model tests, and the installer
lifecycle/config/uninstall-restore tests. Each suite can also be run on
its own -- see tests/*.sh, every file has its own header comment
explaining what it covers.
CI runs one additional step this doesn't: tests/host-contract- regression.sh (issue #34), which fetches real source from
github.com/basecamp/omarchy at the exact commit COMPATIBILITY.md
records as reviewed and checks it still matches the host contracts this
repo depends on. Deliberately excluded from run-all.sh since it needs
network access and GitHub API auth that a local run shouldn't require --
run it directly (./tests/host-contract-regression.sh) if you want to
check it yourself.
The installer tests (tests/install-lifecycle.sh, tests/shell-json- merge.sh, tests/looknfeel-preserve.sh, tests/uninstall-bar- restore.sh) run against a throwaway fake $HOME/directory tree, never
your real config, so they're safe to run anywhere including this repo's
own checkout.
tests/live-shelf-ipc.sh drives the Shelf's real IPC boundary against a
running shell, so it is outside run-all.sh and CI (it skips itself when no
shell is running). Run it after a real omarchy restart shell when you
change the Shelf.
tests/cava-*.sh cover the visualizer's own state/lifecycle wiring
statically, but a few things only really show up live. A couple of
minutes, not a long soak:
1. Off -> Bars -> Segments -> Wave
2. switch 64 <-> 96 bands
3. pause/resume audio
4. enable/disable a few times
5. enter/exit fullscreen
6. kill cava once and confirm only one replacement process appears