A native window and workspace switcher for Omarchy 4. It runs as an overlay
plugin inside the existing omarchy-shell Quickshell process, so there is no
separate daemon to start or supervise.
The switcher mirrors the behavior of the original GTK implementation:
- windows from the active workspace only;
- most-recently-used ordering;
- app icon, window title, and app name;
- Alt+Tab window switching and Super+Tab workspace switching;
- repeated Tab and º cycling, matching the original bindings;
- selection when Alt is released;
- cursor preservation when a tiled window is focused;
- a compact, centered top-bar-style overlay.
- Omarchy 4.0 or newer (the Quattro/Quickshell plugin system)
- Hyprland using Omarchy's Lua configuration
Install and enable the plugin with:
omarchy plugin add https://github.com/vegonza/omarchy-tab.git --enableFor local development, link the checkout into the user plugin directory:
mkdir -p ~/.config/omarchy/plugins
ln -s "$(pwd)" ~/.config/omarchy/plugins/vegonza.omarchy-tab
omarchy-shell shell rescanPlugins
omarchy plugin enable vegonza.omarchy-tabThen copy examples/bindings.lua into
~/.config/hypr/bindings.lua. Hyprland reloads Lua configuration on save;
validate it afterward:
hyprctl reload
hyprctl configerrorsThe bindings replace Omarchy's stock Alt+Tab and Super+Tab actions. Repeated presses advance the open overlay, and releasing the modifier confirms the selection. The transparent release bindings also handle very fast taps that finish before an overlay could acquire keyboard focus.
These commands are useful while developing:
omarchy-shell shell call vegonza.omarchy-tab open '{"mode":"windows","step":1}'
omarchy-shell shell call vegonza.omarchy-tab open '{"mode":"workspaces","step":1}'
omarchy-shell shell call vegonza.omarchy-tab advance '{"step":1}'
omarchy-shell shell call vegonza.omarchy-tab confirm ignored
omarchy-shell shell call vegonza.omarchy-tab cancel ignoredFiles physically stored under ~/.config/omarchy/plugins/ hot-reload
automatically. The development symlink above is discoverable, but its target is
outside the watched tree, so rescan after editing it:
omarchy-shell shell rescanPluginsIf an already-loaded overlay remains stale after a development rescan, use the
documented recovery command omarchy restart shell.
omarchy plugin validate .
qmllint -I /usr/share/omarchy/shell Switcher.qml
node tests/gesture-state-test.js
node tests/client-snapshot-test.js
node tests/bindings-test.jsmanifest.json keeps only the small controller and a one-pixel, input-transparent
native layer surface loaded. This avoids both plugin and compositor cold starts.
The card scene graph exists only while the overlay is visible, and icons are
decoded at their displayed size without being retained in Qt's image cache.
The bindings attach a generation and sequence number to each switching gesture. The plugin queues out-of-order IPC calls and does not confirm until every Tab event preceding the modifier release has arrived. This preserves the original single-daemon cycling behavior even when the short-lived IPC processes race.
Switcher.qml takes a fresh hyprctl clients -j snapshot when a gesture starts,
matching the authoritative source used by the original daemon. This matters for
clients opened after the shell started: Quickshell's cached toplevel objects can
temporarily lack the IPC fields the switcher needs and were therefore omitted.
The Omarchy shell's shared desktop-entry/icon library still resolves app names
and icons, and window activation goes through Hyprland's Lua dispatcher. A
second hyprctl query captures the cursor immediately before a tiled window is
focused so its position can be restored exactly as in the original switcher.