A macOS 26/27-style desktop for Hyprland, built on Quickshell: Liquid Glass menu bar, Dock, Control Center, Spotlight, desktop widgets, notifications and a full lock screen. This is a fork of 0-ss/Macshell with a lot added on top (see below). The original README follows.
| Music widget: cover "burns" over while the album colour spreads | App switcher (Alt + Tab): gliding highlight, morphing name |
|---|---|
![]() |
![]() |
| Lock screen | Clock app |
|---|---|
![]() |
![]() |
| Control Center: tiles stagger in, every module animated | A folder pinned to the Dock fans out |
|---|---|
![]() |
![]() |
| The Dock fan: leans out of the folder, names underneath, folds itself away | Brightness: the sun turns and its rays grow with the level |
|---|---|
![]() |
![]() |
| Light ⇄ dark moves the whole system at once, as a fade | AirDrop finds devices on Wi-Fi, Ethernet and your own hotspot |
|---|---|
![]() |
![]() |
| Reminders |
|---|
![]() |
| Internet Sharing remembers its name and password |
|---|
![]() |
Measured on an Intel laptop (Hyprland 0.56, Quickshell 0.3, two monitors, 60 Hz + 164 Hz, Liquid Glass on):
| RAM (resident) | CPU at idle | |
|---|---|---|
| MacShell (menu bar, Dock, widgets, everything) | ~670 MB after start (was ~1.1 GB) | ~3 % of one core (was ~7.6 %) |
| …with real-time Liquid Glass on (the default) | ~7 % while the Dock or a panel is on screen | |
| …with Photos open on a 300-picture library | ~800 MB, and back to ~670 MB when the window closes | |
| Lock screen while locked | ~360 MB | ~0 % |
What made the difference: one variable Inter font file instead of a 13 MB collection mapped once per weight, MALLOC_ARENA_MAX=2,
Settings and Clock content only built while open, blurred backdrops at half resolution, desktop widgets culled while windows
cover the desktop, the Dock's glass refreshing nearby windows at 15 fps instead of every frame, window-title changes and the
shell's own captures no longer waking the 60 Hz geometry poll, and animations at each monitor's real refresh rate
(QSG_USE_SIMPLE_ANIMATION_DRIVER=1, otherwise Qt paced everything to the 60 Hz panel).
git clone -b tahoe https://github.com/vsoultann/MacShell.git
cd MacShell
./install.sh # interactive
./install.sh --all -y # everything, no questionsRun it with no options for the interactive menu: it notices an existing install (the original MacShell or this edition) and offers to update it or install everything, or lets you tick exactly the features you want.
| Command | What it does |
|---|---|
./install.sh |
Interactive: Install / Update / Check / Uninstall, then a checklist of features |
./install.sh --all |
Everything |
./install.sh --only shell,lock |
Just the features you name |
./install.sh --update [features] |
Pull the latest version, then update (default: shell, lock, config) |
./install.sh --uninstall [features] |
Remove everything, or just some features (settings are kept) |
./install.sh --check |
What's installed and what's missing |
Features: shell (menu bar, Dock, Spotlight, Control Center, notifications, widgets, Clock, Settings), lock (lock screen),
config (session config + scripts), session (separate "Hyprland (MacShell)" login), existing (start from your own Hyprland
config instead), deps, icons, fonts, apply, wallpapers, sounds.
Settings live in the shell itself: Apple menu → System Settings… (Install dependencies and Reset MacShell are in About / General).
The original MacShell is the menu bar, the Dock and the Liquid Glass shader. Everything below is new in this fork:
Internet Sharing that doesn't cost you Wi-Fi — most Wi-Fi chips can run a client and an access point at the
same time, as long as both sit on one channel. ./install.sh hotspot installs the one privileged piece that needs
(a script that can only add or remove a virtual AP interface, plus an optional sudoers line for that one file), and
then sharing runs the hotspot on its own interface and takes the channel you are already on — your connection stays
up, the network list stays real. Adapters that can't do both still work the old way, and Settings says which you get.
Its own session, laptop-ready — the "Hyprland (MacShell)" login runs a standalone Hyprland config
(~/.config/hypr-macshell/hyprland.lua + macshell/*.lua), not another shell's dotfiles. The volume, mute, mic-mute,
brightness and media keys work out of the box (also on the lock screen) and show the Liquid Glass HUD. Folders open
in Finder everywhere — the Dock, the desktop, Spotlight, the Control Center, and xdg-open from other apps.
Your custom/*.lua overrides carry over when you update.
Liquid Glass controls — every switch and slider is one shared component: holding the knob turns it into a glass lens (the Control Center and Sound sliders use the original MacShell CCSlider with its real Liquid Glass), and App Store, Finder and Photos have an overlay scroller that widens into glass. They follow Settings → Appearance (Liquid Glass, Frosted, Blur, Opaque).
Try it without disturbing the one you run — ./install.sh sandbox installs a second, complete copy under its
own name: its own shell folder, session config, settings and login entry. Nothing is shared with the MacShell you
already have, so you can test a version and then just delete it. Name it with
MACSHELL_SANDBOX_NAME=tahoe ./install.sh sandbox.
Quiet under load — while the machine is busy (a build, a system update, a big install) the Liquid Glass stops refracting live and the window captures pause, so the desktop stays responsive; everything comes back when the load drops. No setting to remember: it watches the load average and uses hysteresis so it never flaps.
New apps & screens
- Finder — Dolphin, dressed and named as Finder in the MacShell session only: MacTahoe (Kvantum) following
light / dark and the shell's accent (selections, focus, controls), translucent with live compositor blur in the
glass materials and solid in Opaque, Inter. Finder's toolbar (Back | Forward grouped, the folder name in bold,
the view switcher, search, the … menu), Finder's sidebar (Favorites with your name for Home, Locations, Network;
rounded selection), 64 px icons, no menu bar, status bar or tab strip, double-click to open. It is done with
KDE's own locked defaults in
~/.config/hypr-macshell/qt(macshell-kde-theme.shwrites them,finder.qssand a smallen@macshelltranslation do the rest), so your other sessions keep Dolphin exactly as it was. - Photos — your library grouped by day, folders as albums, favourites, a zoom slider and a full-screen viewer.
- AirDrop — the radar, the devices around you, drag-to-send. Drag files onto someone to send straight away, or
drop them anywhere in the window and pick who gets them. It speaks
LocalSend's protocol, so phones, tablets and other desktops running LocalSend appear here, send here and receive
from here. Networks that drop multicast (phone hotspots, guest Wi-Fi) are swept directly, a device that changed
address is found again by its fingerprint, and a failed send says why; tap the device to try again. If a firewall
runs,
./install.sh airdropopens port 53317 in ufw or firewalld. Every attempt is logged in~/.cache/macshell/airdrop.log. - App Store — Flathub, laid out like the real App Store: Discover, categories, screenshots, search and updates.
- Reminders — the macOS window: smart lists in the sidebar, a big title, type to add, click a circle to tick it off,
click the text to rename, × to delete. It edits the same
reminders.mdthe desktop widget shows. - Desktop icons — everything in ~/Desktop, drag and snap to the grid, double-click to open, drop one onto another to make a folder, rename and trash from the menu.
- VLC — still VLC (its name, icon and layout), dressed like the rest of the session by
macshell-vlc.sh: the MacShell Kvantum theme through Kvantum's Qt 5 half (kvantum-qt5), light / dark, your accent for highlights and the volume wedge, solid menus, Inter. (Its seek bar stays VLC's blue: VLC 3 hard-codes that colour on Linux.) - Lock screen (MacLock) — its own process (a shell crash can't take the lock down), PAM unlock, glass clock that stretches
like iOS 26's, Caps Lock indicator, animated wallpapers, per-character password dots, and:
- Now Playing bubble tinted from the album art, shuffle / repeat, synced lyrics (in the bubble or side by side), enlarge-the-cover artwork mode with a blurred album background, drag the bubble between two spots.
- Notifications, hidden like macOS ("previews when unlocked"): app icon, app name, time. Clicking one makes the password field glow.
- Live activity: a running timer or stopwatch, or a ringing alarm with Stop / Snooze.
- Clock app — World Clock (day / night faces), Alarms (repeat days, snooze, on/off), Stopwatch with laps, Timers with a progress ring. Alarms ring even with the window closed, and everything survives restarts.
- System Settings rebuilt like macOS: Wi-Fi (with Ethernet), Bluetooth, Network, Battery & Energy Mode, Control Center, Desktop & Dock, Displays (main display, resolution, refresh rate, with the macOS "keep or revert" countdown) & Night Shift, Notifications, Sound, Focus, Lock Screen, Users & Groups, Keyboard, Mouse, Trackpad, Wallpaper, Reset, Install dependencies. macOS pop-up menus and controls throughout.
- Desktop widgets — Clock, World Clock, Clock (timer / stopwatch / alarms with switches), Calendar, Weather, Batteries, Music, Notes, Photos, Reminders, Stocks; Liquid Glass / Frosted / Tinted / Opaque, drag, resize with motion-morph, glass that follows a live wallpaper.
Dock
- Live window previews next to the Trash that keep running while other apps open and close.
- Items grow in when an app opens and shrink out when it closes.
- Pull a window preview out of the Dock: it grows into the window, then the real window follows your pointer until you let go.
- Pull an app icon onto the desktop to open it.
Everywhere
- One material for the whole system — Liquid Glass, Frosted, Blur or Opaque applies to the menu bar, Dock, Control Center, notifications, Spotlight, the paste menu and the widgets at once, and refraction is real-time: whatever moves under a panel is refracted as it moves.
- Notifications — Liquid Glass banners that morph into Notification Center and disintegrate on Clear All.
- Animated wallpapers that stay cheap: an optimized copy decoded on the iGPU, paused while windows cover the desktop or the screen is locked.
- Blur + morph text transitions, auto contrast (panels switch text color only when it would be unreadable), Spotlight glow, Game Mode, UI sounds, drag clipboard items onto the desktop.
- State that survives a crash (Do Not Disturb, Night Shift, alarms, timers, …), about 4 % CPU when idle.
- A CLI installer with an interactive menu, a separate login session option,
--update,--checkand--uninstall.
- @0-ss (Rickky) — original author of MacShell: the menu bar, the Dock, the Liquid Glass shader and the foundation everything here is built on, plus help along the way. Their commits are part of this repository's history.
- @vsoultann — this fork (Tahoe edition).
- 0-ss/Macshell — the original MacShell (menu bar, Dock, Liquid Glass shader). All credit for the base goes there.
- Early versions of the session config started from end-4/dots-hyprland (GPL-3.0); it is its own standalone config now.
- MacTahoe icon theme by vinceliuice (GPL-3.0).
- apple_cursor by ful1e5 (GPL-3.0) — the macOS pointers, downloaded by
./install.sh --icons. - MacOS-Like by Scrimas (GPL-3.0) — builds the dark app icons for Settings → Icons → Dark.
- 0-ss/macshell by Rickky (MIT) — GlassSlab, the live glass behind the Settings toolbar buttons.
- Roboto Flex (OFL) and Inter (OFL), downloaded by the installer.
- Lyrics: LRCLIB and NetEase Cloud Music. Weather: Open-Meteo.
- Apple's wallpapers belong to Apple and are not included —
--wallpapersdownloads them.
A macOS Tahoe–style menu bar + Dock for Hyprland, built on Quickshell, with a real-time "Liquid Glass" refraction shader, window previews, Spotlight, clipboard/emoji picker, notifications, Control Center, screenshots,record video, a wallpaper picker and an Alt+Tab switcher — all in one Quickshell process.
Heads up: this targets Hyprland 0.55+ with a Lua config (
hyprland.lua) and a recent Quickshell (0.3.x). See Requirements and Known issues.
| File | Purpose |
|---|---|
shell.qml |
Entry point. Shared hub: window geometry, wallpaper lookup, capture gating. |
MacBar.qml |
Menu bar, Control Center, Spotlight, notifications, switcher, screenshots, wallpaper picker. |
MacDock.qml |
Dock, window previews, and the Settings window. |
liquidglass.frag |
Liquid Glass fragment shader (compiled to .qsb on first run). |
EmojiData.js |
Emoji fallback data for Spotlight (from gemoji, MIT). |
Keep all five files in the same folder.
| What | Why |
|---|---|
Hyprland ≥ 0.55, running a Lua config (~/.config/hypr/hyprland.lua) |
Window actions, the Alt+Tab focus, "paste after picking" and Log Out use Lua dispatches (hyprctl dispatch 'hl.dsp…', hyprctl eval). On older versions or a .conf session these actions fail; the bar, Dock, glass and previews still work. Quick test: hyprctl dispatch 'hl.dsp.no_op()' must not error. |
| Quickshell ≥ 0.3.0 (0.3.2 recommended) | Needs the Hyprland module (HyprlandToplevel, lastIpcObject, Lua-config support), ScreencopyView, IpcHandler, and the UPower / Pipewire / Mpris / SystemTray / Notifications services. |
| Quickshell built with Wayland, Hyprland, Screencopy → Hyprland Toplevel Export, Pipewire, UPower, Mpris, System Tray | Distro packages normally enable all of these. Check the build info that qs prints in its logs. |
Qt 6.5+ with qt6-declarative, qt6-wayland, qt6-shadertools (provides qsb) |
QtQuick.Effects (MultiEffect) needs 6.5+. qsb compiles liquidglass.frag on first run. Without it (and without a prebuilt liquidglass.frag.qsb) the glass falls back to "Normal Blur". |
qt6-svg (recommended) |
SVG app icons. |
hyprctl, sh, xdg-open |
Core. |
| An icon theme (Papirus, Adwaita, …) set for Qt apps | App icons in the Dock and Spotlight come from the system theme. If icons are blank, set one with qt6ct or QS_ICON_THEME. |
| Font Inter (default) | Falls back to the system font; "Noto Sans" / "System" can be chosen in Settings. |
| Feature | Tool(s) |
|---|---|
| Screenshots (Print key) | flameshot (pick an area, draw, blur, pin, upload; Shift+Print = every display), else the built-in picker: grim, wl-clipboard (clipboard copy), libnotify (notify-send). Flameshot follows the accent colour and never shows in the Dock |
| Clipboard history + Emoji (Spotlight) | wl-clipboard, cliphist (the shell starts the wl-paste --watch cliphist store watchers itself) |
| Screen recording | wf-recorder |
| Color picker | hyprpicker |
| Night Shift | hyprsunset |
| Brightness | brightnessctl |
| Wi-Fi / VPN / Ethernet | NetworkManager (nmcli); fallback editor nm-connection-editor or nmtui |
| Bluetooth | bluez (bluetoothctl) |
| Audio device routing | wpctl (WirePlumber) or pactl |
| Privacy indicators | PipeWire (pw-dump) |
| Keep Awake | systemd-inhibit |
| Lock / Sleep / Restart / Shut Down | loginctl, systemctl (UWSM sessions are stopped via uwsm) |
| Finder | dolphin, kvantum, kio-extras, ffmpegthumbs (thumbnails); the MacTahoe KDE theme is downloaded by ./install.sh --config |
| Videos | vlc, kvantum-qt5 (its theme) |
| Trash watching / emptying | inotify-tools (inotifywait), ktrash6/ktrash5, or a file manager (dolphin, nautilus, thunar, nemo, pcmanfm-qt) |
| Folder pickers in Settings | zenity, kdialog or yad |
| "About This Linux" | fastfetch or neofetch |
| Do Not Disturb (Focus) | dunstctl, makoctl or swaync-client (only if you keep one of those) |
| Emoji search keywords | emoji-test.txt from the unicode-emoji package (otherwise EmojiData.js is used) |
| Wallpaper detection / applying | one of: Noctalia, awww/swww, hyprpaper, swaybg, wpaperd — or set a path yourself (see Wallpaper) |
| Default apps | terminal kitty, file opener xdg-open — change terminal, launcher, filesCmd, clipboardCmd in ~/.config/macbar/settings.json |
| The AppleCare+ easter egg | yt-dlp (without it the video opens in your browser instead) |
| PDF previews in Quick Look | poppler (pdftotext) |
| Picking files (AirDrop, Photos) | kdialog |
| AirDrop itself | python3 (standard library only) and a device running LocalSend on the same network |
| Apple Music | Cider (cider), by the Cider Collective — installed as macshell-applemusic.desktop |
| App Store | flatpak with Flathub added (flatpak remote-add --if-not-exists flathub …) |
This shell replaces your bar, dock and notification daemon. Stop anything that overlaps:
- Other bars/shells (waybar, hyprpanel, ags, Noctalia, Caelestia, …) and docks (nwg-dock, …).
- Notification daemons (
dunst,mako,swaync): the bar ownsorg.freedesktop.Notifications.systemctl --user disable --now dunst(ormako/swaync).
- Install the requirements above. On Arch, for example:
Other distros: install the equivalents. Fedora has a Quickshell COPR; Nix has
sudo pacman -S hyprland quickshell qt6-declarative qt6-wayland qt6-shadertools qt6-svg \ grim wl-clipboard wf-recorder cliphist libnotify brightnessctl networkmanager bluez-utils inotify-tools \ ttf-inter noto-fonts-emojipkgs.quickshell. - Put the project in a Quickshell config folder. The folder name is the config name:
Don't reach it through a symlink; Quickshell ≥ 0.3 derives its state folders from the link path.
git clone https://github.com/0-ss/MacShell ~/.config/quickshell/MacShell - Try it:
On first run with the Liquid Glass style,
qs -c MacShell (or use qs -c ~/.config/quickshell/MacShell)liquidglass.fragis compiled withqsband cached in~/.config/macdock/liquidglass.frag.qsb. Watch for[macbar-glass] state: readyin the log. - Add the Hyprland config below, then autostart it.
-- autostart (remove other bars / docks / notification daemons first)
hl.on("hyprland.start", function()
hl.exec_cmd("qs -c macshell")
end)
-- layer rules: blur for the glass surfaces
hl.layer_rule({ name = "macdock", match = { namespace = "macdock" }, blur = true, ignore_alpha = 0.2, no_anim = true })
hl.layer_rule({ name = "macspot", match = { namespace = "macspot" }, blur = true, ignore_alpha = 0.05, no_anim = true })
hl.layer_rule({ name = "macbarbg", match = { namespace = "macbarbg" }, blur = true, ignore_alpha = 0.05, no_anim = true })
hl.layer_rule({ name = "macshot", match = { namespace = "macshot" }, no_anim = true }) -- optional: no fade on the screenshot picker
-- Settings window (fixed size). Hyprland usually floats it on its own; if it tiles, add a float rule for the title
-- "macshell Settings" (see /usr/share/hypr/hyprland.lua for the window_rule syntax of your version).
-- keybinds (the name after -c must match your folder name)
hl.bind("SUPER + V", hl.dsp.exec_cmd(qs .. "spotlight clipboard"))
hl.bind("SUPER + period", hl.dsp.exec_cmd("qs -c ~/.config/quickshell/MacShell ipc call spotlight emoji"))
hl.bind("SUPER + Space", hl.dsp.exec_cmd("qs -c ~/.config/quickshell/MacShell ipc call spotlight toggle"))
hl.bind("ALT + TAB", hl.dsp.exec_cmd("qs -c ~/.config/quickshell/MacShell ipc call switcher next"))
hl.bind("CTRL + ALT + W", hl.dsp.exec_cmd("qs -c ~/.config/quickshell/MacShell ipc call wallpapers toggle"))
hl.bind("PRINT", hl.dsp.exec_cmd("qs -c ~/.config/quickshell/MacShell ipc call screenshot region"))Also make sure blur is enabled in your Hyprland decoration settings, or the "Normal Blur" style won't blur.
qs -c macshell ipc call <target> <function>
| Target | Functions |
|---|---|
spotlight |
toggle, clipboard, emoji, apps |
screenshot |
region (Flameshot when installed), screen, window |
wallpapers |
toggle, open, close |
switcher |
next, prev, commit, cancel |
settings |
open (works even if both the bar and the Dock are disabled) |
glass |
captures true|false (window previews on/off, same as Settings → Dock Behavior → Live window capture) |
finder |
open, folder <path> |
photos |
open, folder <path> |
airdrop |
open |
appstore |
open, search <query>, page <id> |
player |
play <path|url>, youtube <url> |
desktop |
toggle, refresh (icons on the desktop) |
dock |
pinfolder <path>, unpinfolder <path>, stack <path> |
controlcenter |
toggle, open, close |
notifications |
open, close, clear, dismiss <id>, dnd on|off|toggle |
The Liquid Glass refracts your wallpaper, so the shell needs its file path. It looks, in order, at: the wallpaperPath
override in settings.json, Noctalia's settings.toml, awww/swww query, hyprctl hyprpaper listactive, and
~/.config/hypr/hyprpaper.conf. If yours isn't detected (swaybg, wpaperd, a custom script), either pick a wallpaper in the
built-in picker (Ctrl+Alt+W; it remembers the path), or set "wallpaperPath": "/path/to/image.png" in
~/.config/macdock/settings.json. The picker reads ~/Pictures/Wallpapers by default (wallpaperDir).
| Path | Content |
|---|---|
~/.config/macbar/settings.json |
Menu bar settings |
~/.config/macdock/settings.json, pinned.json |
Dock settings and pinned apps |
~/.config/macdock/liquidglass.frag.qsb |
Compiled shader cache |
~/.cache/macbar/ |
Clipboard history helper files (images, timestamps) |
~/Pictures/Screenshots |
Default screenshot folder |
Clipboard history is kept on disk (cliphist's database plus ~/.cache/macbar/clip). Turn it off with clipHistory: false
in ~/.config/macbar/settings.json if you don't want that.
| Symptom | Check |
|---|---|
| Glass looks flat / "Normal Blur" | qsb missing (install qt6-shadertools) — the log shows [macbar-glass] state: failed. Or ship a prebuilt liquidglass.frag.qsb next to liquidglass.frag; it is used as a fallback. |
| Glass shows no wallpaper | Wallpaper not detected: see Wallpaper. |
| Blank app icons | No Qt icon theme: set one (qt6ct, or QS_ICON_THEME) and install it. |
| No notifications | Another daemon owns the D-Bus name. Disable it and restart the shell. |
| Window menu actions, Alt+Tab focus, paste-after-pick or Log Out do nothing | Not on a Lua-config Hyprland 0.55+: run hyprctl dispatch 'hl.dsp.no_op()'. |
| No window previews / glass behind windows | Quickshell built without Hyprland Toplevel Export, or Settings → Dock Behavior → Live window capture is off. |
| Log | qs log (see qs --help for selecting the config). |
Shell crash with wl_display#1: error 0: invalid object NNN when many windows open/close quickly (a game launching,
spamming terminals) while live window capture runs. A window closes while a capture frame for it is still pending; Hyprland
does not answer that frame, the shell then destroys it, and the compositor drops the Wayland connection. Mitigations:
- Settings → Menu Bar → turn Real-time glass off (far fewer captures; the biggest win).
- Settings → Dock Behavior → turn Live window capture off.
- The shell already pauses glass captures while windows open/close.
- Auto-restart it:
sh -c 'while :; do qs -c macshell; sleep 1; done'as the autostart command.
Glitchy window capture, Can be disabled in Settings:
- Settings → Dock Behavior → turn Live window capture off.
Reproduced on Hyprland 0.56.2 / Quickshell 0.3.2
Emoji data from GitHub gemoji (MIT).













