macOS ⌘-Tab for Omarchy / Hyprland — hold, tab, release.
Stock Omarchy binds SUPER+Tab to
D398
next workspace, so it walks you 1 → 2 → 3 → 4 like a slideshow. Swish turns SUPER+Tab into the thing your Mac muscle memory expects: a glass bar of cards pops up, you tap Tab to move, the desktop behind it switches live so you can see where you're about to land, and letting go of SUPER commits. Esc bails and puts you back exactly where you were.
Cards are grouped by workspace, in numeric order, always. They never shuffle by recency — a card is where you left it, so your hands learn it.
flowchart LR
H[Hold SUPER] --> O[Open glass<br/>workspace bar]
O --> T[Tap Tab<br/>or backtick]
T --> P[Preview highlighted<br/>workspace live]
P --> M{Keep moving?}
M -->|yes| T
M -->|release SUPER| C[Commit highlighted<br/>workspace]
M -->|Esc| R[Restore exact<br/>origin]
classDef input fill:#101921,stroke:#7aa8ab,color:#eef8fa
classDef preview fill:#17202a,stroke:#a48ec9,color:#f8f2ff
classDef outcome fill:#14231c,stroke:#75c88a,color:#effff3
class H,O,T input
class P,M preview
class C,R outcome
A quick SUPER+Tab tap now toggles between your last two workspaces, exactly like Cmd+Tab: on open, the switcher pre-selects the most recently used other workspace (by Hyprland focus history) while the cards stay in numeric order. Keep tapping to walk right; SUPER+Shift+Tab still walks left from the numeric previous.
| Hold / tap / release | Hold SUPER, tap Tab (or `) to move right, SUPER+Shift+Tab to move left. Release SUPER to switch. Esc cancels and restores your original window. |
| Live preview | Every tap actually focuses the highlighted window / workspace underneath the overlay. No guessing — you watch the desktop change with the dimmed cards still on top. |
| Stable workspace groups | One glass panel per workspace, 1 2 3 4 …, each holding its app cards. Same order every time. Add or close an app and only that card changes. |
| Liquid glass | Frosted dark bar, blurred, with a cyan glow on the selected card — tuned to Omarchy's Japan Night palette, easy to retune to yours (it's CSS). |
| Fast | ~110 ms pop-in, 140–160 ms selection transitions. No waiting on it, ever. |
SUPER+q while open |
Kills the highlighted window without leaving the switcher. |
Swish is hyprshell (the excellent GTK4 switcher/launcher for Hyprland by @h3rmt, MIT) plus a ~100-line patch and an opinionated config:
swish-workspace-preview.patch ← the behaviour
config/config.ron ← switch-only, workspace groups, global (no monitor/workspace filter)
config/styles.css ← the glass
hypr/swish.lua ← frees SUPER+Tab, enables blur for the overlay layer
PKGBUILD ← builds `hyprshell-swish` (replaces hyprshell / hyprshell-bin)
install.sh ← does all of the above
The patch changes three things in hyprshell's switch mode:
- Numeric order. Upstream sorts workspace groups by most-recently-used. Swish sorts them by position/ID when
switch_workspaces = true(plain client mode keeps upstream MRU). - Live preview.
navigate()now focuses the highlighted client/workspace immediately (preview_active()), instead of only on close. The overlay is a layer-shell surface, so it stays on top while the desktop changes behind it. - Esc restores origin. The switcher remembers where you were when it opened and
CloseSwitch(false)jumps back there.
Everything else — hold/release detection, the socket protocol, icons, theming — is upstream hyprshell, unchanged. Upstream's own config editor (hyprshell config edit) still works.
flowchart TB
U[Upstream hyprshell<br/>4.10.8] --> P[Swish patch<br/>root.rs]
P --> N[Numeric workspace<br/>group order]
P --> M[MRU other workspace<br/>on forward open]
P --> L[Live focus<br/>preview]
P --> E[Esc origin<br/>restore]
N --> S[hyprshell-swish]
M --> S
L --> S
E --> S
classDef upstream fill:#17202a,stroke:#8a929f,color:#f1f3f5
classDef patch fill:#101921,stroke:#7aa8ab,color:#eef8fa
classDef behavior fill:#211b29,stroke:#a48ec9,color:#f8f2ff
class U upstream
class P,S patch
class N,M,L,E behavior
Requirements: Hyprland ≥ 0.55 with the Lua config (Omarchy 4.x has this), cargo, makepkg.
git clone https://github.com/nixfred/swish ~/Projects/swish
cd ~/Projects/swish
./install.shThat will:
- build and install the
hyprshell-swishpackage (first build ≈ 3–4 min; it conflicts withhyprshell/hyprshell-binand replaces them cleanly), - drop
config.ron+styles.cssinto~/.config/hyprshell/(backing up anything already there), - copy
hypr/swish.luainto~/.config/hypr/and addrequire("hypr.swish")to yourhyprland.lua(afterrequire("hypr.bindings"), so it wins), - enable + start the
hyprshelluser service and verifySUPER+Tabis registered.
Then: hold SUPER, tap Tab. That's it.
flowchart LR
I[install.sh] --> B[makepkg builds<br/>patched package]
B --> C[Back up and install<br/>hyprshell config]
C --> L[Copy swish.lua<br/>and wire require]
L --> H[Reload<br/>Hyprland]
H --> D[Enable and start<br/>user service]
D --> V[Verify SUPER+Tab<br/>binding]
classDef install fill:#101921,stroke:#7aa8ab,color:#eef8fa
classDef system fill:#17202a,stroke:#a48ec9,color:#f8f2ff
classDef verify fill:#14231c,stroke:#75c88a,color:#effff3
class I,B,C install
class L,H,D system
class V verify
./install.sh --uninstall # removes package, hypr/swish.lua, the require line; leaves ~/.config/hyprshell/| Keys | Does |
|---|---|
SUPER + Tab |
open / move right |
SUPER + Shift + Tab, SUPER + ` |
move left |
← → ↑ ↓ / h j k l |
move (while open) |
release SUPER |
switch to highlighted |
Esc |
cancel — back to where you were |
SUPER + q / Delete |
close the highlighted window, stay in the switcher |
Stock SUPER+Ctrl+Tab (former workspace), SUPER+1..9, and Omarchy's swipe gestures are untouched. Only SUPER+Tab / SUPER+Shift+Tab are re-bound.
stateDiagram-v2
[*] --> Closed
Closed --> Open: SUPER + Tab
Open --> Previewing: preselect MRU other
Previewing --> Previewing: Tab / arrows / hjkl
Previewing --> Previewing: SUPER + q closes client
Previewing --> Committed: release SUPER
Previewing --> Cancelled: Esc
Committed --> Closed
Cancelled --> OriginRestored
OriginRestored --> Closed
All live-reload (hyprshell watches both files):
- Size of the cards —
config/config.ron→scale(smaller number = bigger cards),items_per_row. - Colours / glow / radius —
config/styles.css→ the:rootblock. The glass is plain GTK4 CSS; the cyan is Japan Night'sbright_cyan #7aa8ab, swap it for your theme's accent. - Want MRU order back? Set
switch_workspaces: false— you'll get one flat row of cards in most-recently-used order (upstream's default feel), still with live preview. - Don't want blur? Comment the
hl.config({ decoration = { blur … } })line inhypr/swish.lua. The bar goes flat-dark instead of frosted. - Only current monitor / workspace?
filter_by: [current_monitor]etc. inconfig.ron(upstream options).
Test it without touching the keyboard (handy when scripting / screenshotting):
hyprshell socat '{"OpenSwitch":{"reverse":false}}' # open / tab
hyprshell socat '{"CloseSwitch":{"switch":false}}' # esc
grim shot.pngcyclenext/focuscurrentorlast? Native, instant, no UI — but no visual andcyclenext histbounces between two windows because focus history updates on every hop. Fine for a quick flip, not a switcher.- Upstream hyprshell as-is? Close! But the groups reorder by recency every time you open it ("when you move them I can't find them"), and it doesn't move until you let go. Swish fixes exactly those two.
- hyprexpo? Great for an overview (Omarchy maps it to
F3), not for⌘-Tabflow.
PKGBUILD pins an upstream tag (_upstream=4.10.8). To bump: change it, run makepkg -sif, and if the patch stops applying, the touch points are all in crates/windows-lib/src/switch/root.rs (open_switch, navigate, close_switch, SwitchData). The patch is small on purpose.
- hyprshell by h3rmt — the whole switcher. Swish is a thin layer on top. MIT.
- Omarchy by DHH & contributors — the desktop this is made for.
- Built on vic by Fred Nix with Larry, 2026-08-21. Part of the "make Omarchy feel like my Mac" series alongside rift and plonk.
MIT — see LICENSE.