A Material 3 Expressive desktop shell for Hyprland, built on Quickshell.
A bar, a dock that morphs into a launcher, desktop widgets, a lock screen, an emoji picker, a screenshot tool and a settings app — themed together from your wallpaper.
v1.20.1. Lucid 2 with icons on the desktop, bar modules that join into one island, live wallpapers and four ways to pick one, five new widgets, files over Bluetooth, and the fix for Steam opening and closing in a loop. Lucid 2 itself redrew every surface in Material You Expressive, made the clock an app and gave the launcher, the bar and the settings room to be shaped, much of it from contributors. It's what I use daily. The shell shows the highlights once after you update; everything that landed in it, and in every version before it, is in the changelog. Rough edges are still possible and bug reports are welcome.
To hear about new versions, press Watch → Custom → Releases at the top of this page. Lucid also checks for itself: once a day it asks GitHub for the newest release and says so once, in a notification. See Updating.
Lucid installs to ~/.config/quickshell and needs Arch Linux and
Hyprland. Three commands:
git clone https://github.com/Sn3akyy1/lucid.git
cd lucid
./install.shThat's it — the installer does the rest:
- Checks your system — refuses to run anywhere it can't finish the job, rather than leaving you half-installed.
- Installs dependencies — finds
paruoryayand uses it, falling back topacmanfor repo packages. It lists everything and asks before touching your system. Say no and it carries on, telling you which features won't work. This includes the apps Lucid ships pinned to the dock — several GB, mostly from the AUR.--no-appsskips them. - Copies the shell to
~/.config/quickshell, moving any existing config to~/.config/quickshell.backup-<timestamp>first. - Sets up Hyprland —
hyprland.luaand its modules: the keybinds, the window and layer rules, blur, animations, and an autostart that launches the shell on login. If you already have a config it is backed up and you are asked first;--no-hyprkeeps yours untouched. - Sets up theming — the palettes, the wallpaper hook, and the matugen
template. An existing
matugen/config.tomlis appended to, never replaced. - Applies the look — kitty's colours, its opacity and its fish shell, the
starship prompt (wired into
.bashrc,.zshrcandconfig.fish), a fastfetch config that wears the theme (only where you have none), the VSCode/VSCodium Matugen theme, and the GTK theme:adw-gtk3-darkwith the FairyWren icons, written togsettingsand to bothgtk-3.0andgtk-4.0settings.ini. Akitty.confor prompt an earlier release installed, and nobody has changed since, is swapped for the current one, with a backup.--no-lookskips this. - Pins the dock — reads your installed
.desktopfiles and pins the real apps, so the dock is never a row of blank letter tiles. - Offers to restart a running instance onto the new files.
Then reload Hyprland so the new binds and rules take effect:
hyprctl reloadOr log out and back in, which picks up the autostart too. To start the shell by
hand in the meantime, run qs.
Set a wallpaper from Settings → General on first run — that's what generates your colour palette.
Pull and re-run. Your settings, pinned apps, reminders, Shazam history and API keys are carried forward into the new install:
git pull
./install.shLucid tells you when there is something to pull. Once a day it asks GitHub's
public API for the newest release, and when that is newer than the version you
installed it posts one notification — once per version, never again for the same
one. The request is a plain curl for
api.github.com/repos/Sn3akyy1/lucid/releases/latest and carries nothing about
you or your machine; Settings → About shows what it found and turns it off.
Update (on the About page, or on the notification) installs the release
for you: a warning, your password, then a pop-up with a progress bar that also
asks anything the installer would ask in a terminal. It downloads the release's
source from GitHub and runs that release's own install.sh, the same as doing
it by hand below, and offers to restart Lucid at the end. The password goes to
sudo once and is not kept. Only a published release counts, never a push to
main, unless you turn on Beta updates, which offers the newest commit on
main instead and comes with a warning: beta builds are untested.
qs ipc call updates status # what it knows
qs ipc call updates check # ask now
qs ipc call updates update # install the new release (warning first)v0.57 beta is a tag, so it stays exactly where it is:
git clone --branch v0.57 https://github.com/Sn3akyy1/lucid.gitIt is on the releases page too, as a source archive. Nothing carries over between the two — v1.0.0 moved enough that it is worth installing fresh.
| Flag | What it does |
|---|---|
--no-theming |
Skips the palette layer. Leaves ~/.config/lucid and ~/.config/matugen alone — use this if you already have a matugen setup you don't want touched. |
--no-hypr |
Keeps your Hyprland config. Lucid's binds, window rules, blur and autostart are not installed. |
--no-apps |
Doesn't install the apps the dock ships pinned (Zen, VSCodium, Spotify, Vesktop, Files, Steam, Proton VPN). The dock then pins whatever equivalents you already have. |
--no-look |
Doesn't touch kitty.conf, starship.toml, the fastfetch config, your shell rc files, VSCode settings, or the GTK theme and icons. |
--no-wallpapers |
Doesn't copy the bundled wallpapers into ~/Pictures/wallpapers. They are ~180 MB, so this is worth passing on a small disk or a slow link. |
--with-hypr |
Reinstalls Lucid's Hyprland config even when one is already in place. |
--skip-deps |
Never installs packages, just reports what's missing. |
-y, --yes |
Accept every prompt. |
Re-running the installer is how you update. It moves your existing
~/.config/quickshell to ~/.config/quickshell.backup-<timestamp>, installs
the new shell files, then carries your settings, pinned apps, reminders,
Shazam history and API keys forward into it. Nothing is deleted, and the
backup stays where it is until you remove it.
The installer ships these in ~/.config/hypr/modules/binds.lua, along with the
window rules, blur, animations and the autostart. Run hyprctl reload after
installing to pick them up.
| Key | Does |
|---|---|
SUPER (tap) |
Launcher |
SUPER + P |
Command palette |
SUPER + T |
Theme picker |
SUPER + B |
Wallpaper picker |
SUPER + SHIFT + V |
Clipboard history |
SUPER + S |
Settings |
SUPER + . |
Emoji picker |
SUPER + K |
On-screen keyboard |
SUPER + W |
Workspace overview (also: three-finger swipe) |
CTRL + ALT + TAB |
Window switcher — every window on every workspace, newest first (+SHIFT steps back) |
SUPER + Esc |
Session screen — lock, sleep, log out, restart, shut down |
SUPER + D / Print |
Region screenshot |
SUPER + Print |
Full screenshot |
SUPER + SHIFT + T |
Copy text from a region (OCR) |
SUPER + SHIFT + C |
Pick a colour off the screen |
SUPER + E |
Files |
SUPER + C |
Close window |
SUPER + V |
Toggle float |
SUPER + 1–0 |
Switch workspace (+SHIFT moves the window) |
SUPER + SHIFT + S |
Scratchpad, or put away whichever special workspace is up |
SUPER + ALT + S |
Stash the focused window in the scratchpad, or send it back |
SUPER + SHIFT + M |
Music workspace |
SUPER + SHIFT + D |
Comms workspace |
SUPER + SHIFT + R |
To-do workspace |
CTRL + SHIFT + Esc |
System monitor workspace |
SUPER + arrows |
Move focus |
SUPER + R |
Reload Hyprland |
F1–F6 |
Volume, mic, brightness |
F9 |
Terminal |
F10 |
Lock |
F12 |
Calculator |
Ran with --no-hypr, or want to bind things yourself? Everything is exposed
over IPC:
hl.bind("SUPER + SPACE", hl.dsp.exec_cmd("qs ipc call -- launcher toggle"))
hl.bind("SUPER + E", hl.dsp.exec_cmd("qs ipc call -- moji toggle"))
hl.bind("SUPER + L", hl.dsp.exec_cmd("qs ipc call -- lock lock"))
hl.bind("SUPER + Escape", hl.dsp.exec_cmd("qs ipc call -- session toggle"))
hl.bind("SUPER + S", hl.dsp.exec_cmd("qs ipc call -- snap toggle"))
hl.bind("SUPER + SHIFT + T", hl.dsp.exec_cmd("qs ipc call -- snap text"))
hl.bind("SUPER + SHIFT + C", hl.dsp.exec_cmd("qs ipc call -- snap color"))
hl.bind("SUPER + comma", hl.dsp.exec_cmd("qs ipc call -- settings open"))Special workspaces are Hyprland Lua rather than IPC. On a Lua config of your
own, copy support/hypr/modules/specials.lua into ~/.config/hypr/modules/
and bind its functions the way Lucid's modules/binds.lua does:
local specials = require("modules.specials")
hl.bind("SUPER + SHIFT + M", specials.toggle("music"))Keep the --. It is only strictly required when the call takes an argument —
qs ipc call settings show bar fails with "The following argument was not
expected: bar", while qs ipc call -- settings show bar works. It is harmless
on argument-free calls, so using it everywhere saves you the surprise.
Six modules, each a pill that expands into a panel. Settings lays them out: the bar has a left, a middle and a right zone, and every module can be moved between them and reordered inside them, or taken out of the bar entirely.
- Workspaces — live window previews per workspace, click to switch. With more than one display the dots gather into a run per display, marked on hover with its number from Settings → Displays, and the overview lays out a block per display, left to right as they stand on the desk. A scratchpad (special workspace) shows beside the dots only while it is open: the dots sink, and a chip comes up with its name and a glyph for each app stashed in it — a terminal for a terminal, a note for an editor, read off each app's own categories. Click a glyph to jump to that window, or drag windows in and out from the overview's scratchpad row
- Media — MPRIS controls, seek bar, art, and Shazam-style song ID (
songrec) - Tray — SNI system tray with working context menus
- Clock — the date beside the time, the time itself in a filled chip, and a five-page clock app behind them: the day with the weather and what is next, a month calendar with reminders that toast when they are due, countdown timers and a pomodoro, a stopwatch with laps, and world clocks. Whatever is counting shows in the pill as a chip with a ring. The pomodoro card opens onto its own options: presets, every length, a daily goal, whether breaks and focus sessions start by themselves, and do-not-disturb for as long as you are focusing
- Notifications — grouped by application, with inline reply for chat apps and progress bars for transfers. New ones stack under the bar, the newest growing out of the pill itself; do-not-disturb holds them back
- System — volume, brightness, battery, disk stats, plus full Wi-Fi and Bluetooth panels and a switcher for the audio output and input. Two rows of tiles underneath: the toggles (silence, awake, dark, airplane, location, mic) and the tools (capture, record, colour picker, keyboard, timer, session); Edit tiles adds more, such as the power profile, game mode and night light, which warms the screen through hyprsunset, fading in and out, by hand or from sunset to sunrise where you are (worked out locally, no network) or between set hours. Right-click its tile to pick how warm and when; Settings → Displays has the same. Turning it on or off while a schedule runs holds until the schedule next changes. The compact strip shows the keyboard layout (click it to switch). Hover any icon there and it names itself; click it and the panel opens on the page that icon belongs to
Three shapes, set in Settings: island (floating rounded pills), notch (flush to the screen edge, with flares that blend into it) or the full bar (one strip across the whole top edge, hanging into the screen's corners). Two more switches on the Bar page, both off by default: Open on hover unfolds a module under the pointer without taking the keyboard from your window, and Auto-hide slides the bar out of sight until the pointer touches the top edge or a panel is open, giving its space to the windows meanwhile.
Each module's card under Settings → Bar also picks its look, starting from the one above: the clock in one line or two, or with the time on its accent chip, and how the date reads; media as the turning disc, a still cover or just its bars, with a large-cover panel; workspaces as dots or numbers, how many always show and whether the wheel switches them; notifications as a count, a dot or an accent chip; and the tray collapsed or as every app's icon, in the app's own colours or the palette's, with a switch per app to keep it out.
With more than one display, Settings → Displays → The bar on its own → Every
display puts a bar on each screen, showing that screen's workspaces. One of
them, on the shell's display or the one in use, still turns into notification
popups and answers the bar's qs ipc targets.
Drag a module by its handle to move it within a zone or into another one, or down into Not in the bar to take it out; the arrows and buttons beside it do the same thing. The link between two neighbours joins them: they sit flush and share one island (or one notch, its fillets only at the ends), with a faint line where they meet if you want one, and a module opened in place hangs its panel from its own stretch of the group, its corners curving into the neighbours. In pop-up mode the pop-up floats below as it always has, or, with Notched pop-ups, grows straight down out of its module or group, the corners curving into each other as a notch meets the top of the screen. Also in Settings: how close the middle may come to either side before it gives way, and a button that puts every module back where Lucid ships it.
The System pill opens into a control centre — Wi-Fi and Bluetooth with full panels behind them, brightness and volume with the audio devices behind those, two rows of tiles you arrange yourself, what is playing, and CPU, memory, disk and battery.
The small tiles are yours to arrange, the way a phone's quick settings are. The pencil in the panel's header opens Edit tiles: drag a tile to move it, tap its − or drag it below the line to take it out, and tap anything under Tap to add to put it in. Clipboard, Emoji, Wallpaper, Theme, Widgets and Clear wait there to begin with, and Reset brings back the set Lucid ships.
The clock pill opens into the clock app, here on its Today page: the time, the weather through the day and the week ahead, and the next reminder. Around it, a stacked clock, what is playing, the month, the weather, the battery, the system and a to-do list.
A floating M3 toolbar that grows into the launcher rather than opening a second window over it. Pinned apps, running-window indicators, drag to reorder, optional magnification and auto-hide - always, or Dynamic, which only tucks the dock away while a tiled window is open on the workspace or a floating one overlaps it, so it is there whenever the desktop is clear. With the dock hidden or turned off, the launcher opens as a notch from the bottom edge. Pull a pinned app up off the dock and drop it on the desktop for a launcher there, the way Windows makes a shortcut; the pin stays put (unpin from its right-click menu). A pinned folder or file lands as a link. With desktop icons off, pulling a pin off unpins it as before.
The launcher opens with a head that carries the Lucida mark, the modes as one
row of pills, and what the results add up to. It is one search field over eight
modes, each reachable by a pill, by Ctrl and its number, by Tab, or by a
prefix you can type:
| Mode | Prefix | What it does |
|---|---|---|
| Apps | — | Fuzzy search over .desktop entries — word boundaries and initials both hit, so vsc finds Visual Studio Code |
| Commands | > |
Shell commands and shell actions |
| Emoji | : |
The emoji picker's own list, searched by name and keyword; Return copies one |
| Web | ? |
Searches your engine of choice, or opens the address if what you typed is one |
| Run | $ |
Runs a command line, in the background or in a terminal that stays open |
| Theme | >theme |
Switch between the seven bundled palettes, and any you have imported |
| Wallpaper | >wallpaper |
Your wallpaper folder, as a carousel, pills, tiles or a bento grid |
| Clipboard | >clip |
What you copied earlier, images included — pick one to put it back on the clipboard |
The wallpaper picker comes in four styles, picked in Settings → Theme →
Wallpaper picker with a live thumbnail of each: Strip (the carousel, with
how fast the neighbours shrink and two or three of them on each side),
Pills (slim pills that open into the picture: even, full height, or a
wave), Tiles (a grid of two to five rows, square or wide, the panel cut to
fit it) and Bento (a large picture beside smaller ones, with or without the
previous one). ← and → change the wallpaper, or ↑ and ↓ (Arrow
keys, same page) so ← and → stay with the search field; Tiles, a grid, takes
all four. The same page picks the transition the wallpaper changes
with — fade, wipe, wave, grow, outer and the rest of what awww can do, its
length, angle and easing — from presets or your own, saved and named, and can
grow it from the card you picked or from the cursor. Try transition runs it
on the wallpaper you have, without changing anything. The choice is written to
~/.config/lucid/wallpaper-transition.conf, which set-wallpaper.sh reads
line by line (never sourced); anything it does not recognise falls back to the
plain fade.
Live wallpapers (Settings → Theme → Live wallpapers, on by default):
videos in the wallpaper folder (mp4, webm, mkv, mov) get a side of the picker of
their own, in the same four styles: a tall Pictures / Live switch sits beside
the picker, which opens on whichever kind is on the desktop (>live goes
straight to the videos). A video plays
behind the desktop's icons and widgets; its first frame is what awww holds
under it and what the colours come from, so the palette matches the picture the
video starts on. The player is a quickshell of its own (lucidlive/), started
by LiveWall.qml with the decoder you pick: Automatic tries VA-API (the
integrated GPU) before NVIDIA, so a hybrid laptop keeps its graphics card asleep;
Intel needs intel-media-driver for that. It holds still on a screen with a
fullscreen window (or under any window, or never), behind the lock screen, and
in game mode it keeps playing, pauses, or stops and leaves the first frame.
It sits between awww and the desktop through layer-rule order, which
LiveWall.qml sets with hyprctl eval before the player starts.
Type a sum in the search field for a calculator (2^3^2, right-associative).
The answer takes a card above the results, set in display type; Return copies it.
Applications with a window already open carry the dock's own running mark beside their name, and the selected row says what Return will do with it. A search that finds nothing offers the four prefixes as chips you can click.
A typed search ranks more than apps: open windows, by their app or their title (Return switches to the window); apps' own actions such as New Private Window, listed under the app when you type its name; and lock, suspend, log out, restart and shut down from three letters, the last three asking for a second Return. Something that reads as an address gets a row of its own at the top when nothing matches it better. Each of these is a switch on the Launcher settings page, which can also put power buttons at the end of the empty search field.
The application list follows the desktop-entry spec properly: ~/.local/share/ applications overrides /usr/share/applications entry for entry, so an
override marked NoDisplay really does hide the system copy, and OnlyShowIn /
NotShowIn are honoured against XDG_CURRENT_DESKTOP. Whatever is left that
you still do not want, hover it and press the eye on the right of the row — the
Launcher settings page lists everything you hid and brings any of it back.
Hidden applications still launch from the dock and still name their windows.
The Power pill, and the Power row in the command palette, hand over to the
full-screen session screen — the same one SUPER + Esc raises.
Searching apps ends with a web search row, so one field covers "open it" and "look it up". It is a switch on the Launcher settings page, along with the search engine — DuckDuckGo, Google, Brave, Startpage or Kagi.
Clipboard mode keeps what you copy and hands it back: pick an entry to put it
back on the clipboard, Delete (or the button on the row) to drop one, and
Clear history on the Launcher settings page to drop the lot. Images are kept
too and preview in the row. cliphist is the store; the shell owns the
wl-paste watchers that feed it, so history records for as long as the shell
is running. Turn the whole thing off with the switch on the Launcher page.
Wallpaper mode: a carousel that previews as you move through it, and applies on the second press.
Cards you place on the wallpaper yourself. Right-click the desktop and pick Widget Panel, or pick Widgets in the launcher's mode bar, and a sheet slides in with every widget drawn live: drag one straight out to where it should sit, or click it to drop it in the first free spot. Drag it anywhere afterwards, pin it so it stops moving, and it comes back where you left it after a reboot.
The panel searches by name or by what a widget does, filters by kind, lists what is already out on On desktop — hover a row to find its card, click it for the card's sheet, lock or remove it there — and switches layouts on Layouts. While it is open your widgets come up over the windows with a − on each, and a card dragged back onto the sheet is taken off the desktop. Settings → Widgets holds the same gallery and every preset.
The widget panel on its Clock gallery: drag a card onto the desktop, or click it to add it. Out on the desktop, a Coming up card and lucidfetch, each with its − while the panel is open.
Twenty-four kinds, eighty-four looks between them — every category ships several variants of the same data:
| Widget | Looks |
|---|---|
| Clock | Digital, stacked, analog with a date window, the time inside an expressive shape, minimal (no card at all), world clocks, the time on a band across a round face, or bold hands on a scalloped dial with the seconds as a dot |
| Calendar | Full month, this week, today, or your next reminders |
| Progress | How much of the day, the week, the month and the year has gone: one wavy ring for the stretch you pick, a bar each, or every day of the year as a dot |
| System | Rings, meters, a two-minute graph, quick-settings tiles, or network throughput — CPU, memory, disk, temperature |
| Quick toggles | Wi-Fi, Bluetooth, Do not disturb and more, a tap away: round switches that turn into shapes as they come on, a pill of buttons that square up, or Quick Settings tiles that spell out each one's state |
| Battery | Ring, cell, full detail, or every wireless device that reports a charge |
| Media | Artwork card, compact row, cover art with the controls over it, a record that turns while it plays, a capsule with the progress circling the cover, a round face with a wavy ring of progress, a tall pill with the track on its side, or the cover cut to a shape of its own that morphs with every track — and it takes its colours from the artwork |
| Visualiser | Bars, mirrored bands, or one filled wave — live off whatever is playing. Drag any edge to size it, right across the screen if you want |
| Weather | Now, a forecast, an icon and a number, the next twelve hours as a curve, or the reading with feels like, high and low, rain, humidity and wind beside it |
| Sun | Sunrise, sunset and the daylight left, worked out where you are: the sun on its road across the sky, sunrise over sunset with a wave between, or whichever comes next |
| Notes | A sticky square, a ruled sheet that counts your words, or one line in display type |
| To-do | A checklist with real checkboxes, or just the next thing with Done and Later |
| Timer | A countdown with one-tap lengths, a pomodoro with a dot per round, or a stopwatch — the same timers the bar's clock keeps |
| At a Glance | The date and weather, and under them the one thing worth knowing now: a running timer, your next reminder, what is playing, a low battery, sunset, or rain |
| Photo | A frame that turns over your pictures on its own — filling the card, cut to a shape, or as a print with the date under it |
| Fetch | Your machine the way a fetch script prints it, as a card or as terminal output |
| Thermals | The graphics card in full with each fan and the power profile, arc gauges for GPU and CPU heat and the fans, or two temperatures and a fan speed in a row |
| Network | A minute of download and upload drawn as a graph, the connection in detail (address, signal, VPN and whether the internet answers), or down and up as two numbers |
| Games | Your installed Steam games, one click from playing: covers on a shelf, the last one you played over its artwork, or a list |
| Shortcuts | Your dock's apps on shapes of their own, one tap from open: four on four shapes straight on the wallpaper, a pill that blooms under the pointer, or a folder like a phone's |
| Search | The launcher's search, kept on the desktop: a search bar like a phone's with emoji and the clipboard at its end, or the bar over the launcher's modes |
| GitHub | Your contributions as your profile draws them, with as many weeks as you drag it wide, or your streak with today and the year. It reads the public profile page, so it only needs your username, no token |
| Palette | The Material roles the shell is currently built from, click one to copy the hex |
| Phone | Card, compact row, or a remote — the paired phone's battery and signal, with ring, ping, send a file and send the clipboard a click away; the remote drives whatever the phone is playing |
Every widget has its own sheet — right-click it, or use the gear that appears on hover. It draws every style of that widget as a live thumbnail, so you pick the look by seeing it, and holds the card's colour (auto, or any Material container), its size, and its own options: 12- or 24-hour, which metrics to show, a note's tint, and so on. Most take one of four sizes; the visualiser instead grows an outline with handles when you hover it, and you drag any edge or corner to whatever shape you want.
Dragging snaps to the screen edges and centre lines and lines up with the other widgets, with guides while you drag. They can go anywhere on the screen, including the strips the bar and the dock reserve — a full-width visualiser tucked under the dock is the point. Widgets sit below your windows by default so they behave like a desktop, and step aside for fullscreen windows; both are switches on the Widgets page if you would rather they float on top.
Your ~/Desktop folder on the wallpaper of the main display, the way it is on
Windows, macOS or GNOME. Turn it on in Settings → General → Desktop icons.
Folders, files and apps are drawn by your icon theme, the one picked on the
Environment page, at the exact size they are shown. Pictures, videos, music
with cover art and office documents show thumbnails, made with the system's
thumbnailers and shared with your file manager. The Trash fills up, USB sticks
and phones appear while they are mounted, and names turn dark over a light
patch of wallpaper. Widgets always keep their space: an icon under one steps to
the nearest free cell, live while the widget is dragged, and goes back after.
It follows Material You. Each icon sits in a tonal well that lights under the pointer; selected, the well takes the primary container and the name becomes a pill (grey once a window has the keyboard). Arrow keys draw a focus ring. Cut files fade, tagged ones wear coloured dots, new ones pop in, and whatever goes to the Trash or into a folder flies there.
Selecting and dragging. Click, Ctrl- or Shift-click, or draw a box, which counts what it holds. Drag into a folder, onto the Trash or a drive, out to a file manager or a browser, or anywhere on the grid; a chip beside the pointer says what letting go will do (Move to Projects, Copy to Projects with Ctrl, Link with Ctrl+Shift). Several icons drag as a stack with a count. Hold a drag on a folder and it springs open in the file manager, as on a Mac.
Right-click an icon for Cut, Copy, Rename and Delete as buttons along the top
(Windows 11 style), then Open, Open With › (the apps for that type, the
default marked), Quick Look, Get Info, Open in Terminal, Paste Into Folder,
Compress or Extract Here, Duplicate, Make Link, Send To › (Documents,
Downloads, Pictures… and phones over KDE Connect), Tags › and Copy Path.
Right-click the desktop for New Item › (folder, text or Markdown document,
empty file, anything in ~/Templates, an app shortcut), Paste (a copied picture
pastes as a PNG), Undo, View › (icon size, auto arrange, hidden files,
extensions, previews), Arrange By › (name, type, size, modified, ascending
or descending), Select All, Open in Terminal and Open Desktop in Files. Hide
Icons sits beside Hide Widgets and puts every icon away until Show Icons. Submenus open beside their row on hover or click, and the arrow keys,
Enter and Escape walk them.
Get Info shows a file's size (a folder's is counted), location, the app it opens with, its dates, owner and permissions, its tags, a drive's free space, and a switch to let a file run as a program. Quick Look (Space) shows pictures, text, a folder's contents, and plays video and music.
Moving to the Trash, moving, copying, renaming, tagging, compressing and new items can all be undone, from the snackbar that follows or with Ctrl+Z. Emptying the Trash and Shift+Delete ask first. Folders always open in a real file manager, even when an editor has claimed folders on the system.
After a click the desktop has the keyboard: Enter, Space, F2, Delete, Shift+Delete, Alt+Enter, Ctrl+A/I/C/X/V/Z/D, Ctrl+Shift+C (copy path), Ctrl+Shift+N (new folder), Ctrl+Alt+N (new text document), Ctrl+Alt+T (terminal), Ctrl+H (hidden files) and F5. Every one of them, plus Compress, Arrange Icons and Hide Icons, can be changed under Settings → Keybinds → Desktop icons; the menus show whatever keys are set. Arrows and Shift+arrows, Home/End, typing a name to jump to it, Escape and the Menu key stay as they are. These keys only ever reach the desktop: it gives the keyboard back as soon as a window is focused, and never takes it when the pointer just passes over.
Scratchpads that slide over whatever workspace you are on, and hide again with the same keys.
| Keys | Workspace | Opens |
|---|---|---|
SUPER + SHIFT + S |
Scratchpad | Nothing of its own — somewhere to park windows |
SUPER + SHIFT + M |
Music | Spotify, Feishin, Supersonic, Cider, YouTube Music, TIDAL… |
SUPER + SHIFT + D |
Comms | Discord, Vesktop, Telegram, Signal, Element, Slack… |
SUPER + SHIFT + R |
To-do | Todoist, Planify, Errands, Endeavour, Obsidian… |
CTRL + SHIFT + Esc |
System | btop in a terminal, Mission Center, Resources… |
A key starts its workspace's app if it is not running, and pulls it back in if
you moved it somewhere else; opened from the launcher or the dock, the app lands
in its workspace too. SUPER + ALT + S stashes the focused window in the
scratchpad and, pressed inside a special workspace, sends it back. The
scratchpad key also puts away whichever workspace is up, so one key always
returns you to what you were doing.
Settings → Workspaces picks each one's apps, turns any of them off, and sets
how far the screen behind dims, whether it blurs too, how much margin the windows
keep from the screen's edges, and whether switching workspace puts them away.
New workspace makes one of your own, with a name, a mark for the bar and any
apps; its key goes into keybinds.json like any other, so it shows on the
cheatsheet and is changed on the Keybinds page. Deleting it brings its windows
back to the workspace you are on.
Add an app offers everything installed, not only the catalogue above, and
works out what to match its window by. It writes ~/.config/hypr/lucid-specials.lua, which
modules/specials.lua reads on every key press, so a change applies without a
Hyprland reload.
Settings → Windows changes how Hyprland draws your windows, live, with a preview drawn from the values in force: the gaps between windows and around the screen, border width and colour (none, your palette's accent, or a gradient through three of its colours, which follows the theme as it changes), a faint border on the other windows, how round the corners are and their shape, a shadow, and dimming the windows you are not in. Under Tiling: the layout (dwindle, master or scrolling) and each one's own options — which way dwindle splits and where a new window goes, the master's side and size, the width of a scrolling column — with a preview of the whole screen for one to five windows, and a switch that takes a lone window edge to edge, without gaps, border or rounded corners. Under Behaviour: whether focus follows the cursor or waits for a click, whether an app may take the focus when it asks, the cursor jumping with the focus, resizing a window by its edges, floating windows snapping to each other and to the screen, hiding the cursor while typing or after a while, and window animations.
Two cards mark windows that need telling apart. A pinned window (it floats over the rest and follows you to every workspace) wears a border of its own — accent, tertiary or a gradient — a tab with a pin tucked into the corner you pick, which unpins it on a click and steps away while the window moves, and a ripple the moment it is pinned. A window asking for attention (a message in, a download done, a terminal's bell) gets a tab with a ringing bell in its corner, in the colour the bar gives its workspace, and rings the first time you see it; a click takes you to it and the tab goes once you are there.
Only what you change there is Lucid's. It goes to
~/.config/hypr/lucid-settings.lua, which modules/settings.lua applies without
a reload; everything else stays as your Hyprland config has it, and each row's
reset hands its option back to your config. hyprland.lua requires the module
before anything of your own, so a file you add after it — hypr-user.lua,
HyprMod's hyprland-gui — still wins: the row says which file sets the option
and stays shut until it is taken out there.
Settings → Input holds the keyboard side of Hyprland, through the same
lucid-settings.lua as the Windows page and with the same rule that your own
config wins: your layouts in order (the first is the one every keyboard starts
with), each picked by name from the system's list of layouts and variants, the
key that switches between them, what Caps Lock does — the other keyboard options
your config sets are kept — key repeat delay and speed, and Num Lock at sign-in,
with a field to try it all out. Then the mouse — pointer speed, acceleration,
natural scrolling, scroll speed, left-handed buttons — and, when there is one,
the touchpad: tap to click, natural scrolling, scroll speed, off while typing,
two-finger right click, tap and drag, and a middle click from both buttons —
and the swipe between workspaces: how far the fingers travel, which way, how
fast a flick switches anyway, how far along letting go still switches, going
past the neighbour and making a new workspace at the end.
Settings → Startup holds what would otherwise mean editing
modules/autostart.lua and modules/env.lua. Apps are opened each time you
log in: pick an installed app or type a command, switch one off without losing
it, or open it now. System autostart lists the entries apps and packages put
in ~/.config/autostart and /etc/xdg/autostart. Hyprland alone does not read
them; a session manager such as uwsm does, and the page says which you have.
Without one, a switch has Lucid start them the way a desktop session would,
through systemd's own xdg-desktop-autostart.target. Each entry can be switched
off for you alone with the spec's Hidden=true, and the page flags an app that
two of these would start twice. Environment variables are set for every app:
those opened from keybinds see a change at once, the dock and the launcher at
the next login, and the page shows which is which. The session's own variables
(WAYLAND_DISPLAY, HOME and the like) cannot be set there.
Under the variables, a few suggestions show up when Lucid finds what they fix
on the machine: Java apps (_JAVA_AWT_WM_NONREPARENTING), an NVIDIA card alone
with its VA-API driver (LIBVA_DRIVER_NAME), a screen scaled 2× or more with
XWayland left unscaled (GDK_SCALE). The ones Hyprland's wiki lists for every
machine are left out on purpose: the toolkits pick Wayland on their own now,
and SDL_VIDEODRIVER=wayland breaks games. Those, and others that guides still copy around,
get a word of warning when you type them or keep them in env.lua — what each
does now and why it is not a good idea — without being refused:
ELECTRON_OZONE_PLATFORM_HINT (gone since Electron 38), MOZ_ENABLE_WAYLAND
(Firefox is on Wayland since 121), GDK_BACKEND and QT_QPA_PLATFORM (and
worse with no fallback), SDL_VIDEODRIVER=wayland, NVD_BACKEND=egl,
STEAM_FORCE_DESKTOPUI_SCALING, LIBVA_DRIVER_NAME=nvidia on a machine with a
second graphics card, GDK_SCALE without force_zero_scaling, AQ_NO_ATOMIC.
All of it goes to ~/.config/hypr/lucid-startup.lua, which modules/startup.lua
reads, so a reinstall, which rewrites autostart.lua and env.lua, keeps it.
What you added to those two files by hand shows in the same lists, with a
button that moves a line here and leaves it in the file commented out; a line
that is more than one plain call stays there, with a button to open the file.
Lucid's own lines in them (the shell, the wallpaper daemon, the variables
Environment sets) are left out.
- Users and accounts — the card at the top of the Settings rail opens a Users and Accounts page for every account on the machine: full name, username, account type, login shell, email and location, with the guards that matter — the last administrator cannot demote themselves and a signed-in account cannot be renamed. Set a password or have the account choose its own at the next sign-in, add and remove accounts, toggle supplementary groups, and pick a picture from the stock faces or any image. It all goes through AccountsService, so the shell's own polkit dialog does the asking and nothing runs as root
- Account picture history — changing your account picture keeps the old one on a shelf in the picker, newest first, so any picture you have worn is a click away. It holds twelve or 8 MB, drops the oldest as new ones arrive, files nothing twice, and can be emptied outright
- Authentication prompts — Lucid is the session's polkit agent, so every request for an administrator on the machine comes up in the shell's own dialog rather than KDE's. polkitd and PAM are still the backend; the dialog names the action, shows which account's password it wants (with the picture from the Users page) and lets you pick a different administrator when polkit will accept more than one
- Lock screen — a real
WlSessionLockthat checks the password through PAM, laid out the way Material You lays out a lock screen: an oversized two-line clock in the wallpaper's own colour, the weather, battery, network and Bluetooth at a glance, what is playing, the notifications and a power bar that asks before it logs you out. Start typing and it focuses — the wallpaper blurs further and everything but the sign-in card steps back. It counts your remaining tries against faillock, warns about Caps Lock, shows the keyboard layout, and will not let a notification launch anything while it is up. Withfprintdinstalled and a finger enrolled (fprintd-enroll), it takes a fingerprint at the same time as the password: touch the sensor or type, whichever comes first - Login screen — the lock screen ported to SDDM, so the machine looks like
itself before you have signed in: the same clock, the same palette and the
same wallpaper, blurred once in advance rather than on a cold GPU, with the
user and session pickers where the glance chips sit. It is painted from the
running shell's own colours, so it follows a theme change. Every account
keeps its own wallpaper and palette there, and picking another account
crossfades the screen to theirs. The installer
copies it in when SDDM is present but never switches to it — which theme
greets you stays your call. With
fprintdinstalled it also offers to let the login screen take a fingerprint: press Enter on an empty field, then touch the sensor. That adds two marked lines to/etc/pam.d/sddm(a typed password is still checked first), whichsudo support/sddm/install-theme.sh --no-fingerprinttakes out again. A fingerprint login leaves GNOME Keyring locked until you next type the password, since the keyring opens with it - Session screen —
SUPER+Esc, the control centre's Session tile or the launcher's command list. Lock, sleep, log out, restart and shut down, each on its own expressive shape that morphs as you move along the row with the arrow keys. The three that cost you work ask twice: the first press arms the shape in red with a ring that runs out after four seconds, and only the second goes through - On-screen keyboard —
SUPER+K, the desktop's right-click menu or the launcher's command list. It never takes the focus off what you are typing into, and clicks outside it reach the application underneath, so the caret stays where you put it. A letters layer and a function layer, modifiers that latch on one press and lock on two, and chords sent as chords. Drag it anywhere by the strip along its top and it stays there - Emoji picker — emoji, kaomoji and GIFs (Giphy or Tenor), with recents, favourites and skin-tone variants; pastes into the focused window
- Screenshots — region select, full screen, and screen recording with optional mic and system audio. What you took then floats in the corner as a card: click it to open, drag it straight into a chat or a file manager, or copy, mark it up, show it in its folder or send it to the trash. It slides away after a few seconds, or stays while the pointer rests on it; a recording gets the same card with a frame from the video. General → Screenshots swaps the card for the old notification, or for nothing
- Text copier — the Text mode in the screenshot toolbar. Drag a box over anything on screen — an image, a video still, a PDF, an error dialog, a window that will not let you select its text — and the words inside it land on your clipboard. Runs the crop through tesseract twice, once inverted, and keeps the better read, so light-on-dark UI text works as well as a scan. Emoji come across too: tesseract has none in its character set and either drops them or reads them as junk letters, so anything colourful and square is matched against the glyphs of your installed emoji fonts instead. One flat colour means text, many means emoji. A shape it cannot name is left out rather than guessed at. Reading takes a moment, so the overlay does not vanish on release: the toolbar, the shade and the box you drew all stay, and a beam sweeps the selection until the text is on the clipboard, at which point it closes itself. The result lands as a toast under the bar rather than a desktop notification
- Colour picker -- the Colour mode hands off to
hyprpicker. Choosing it drops the freeze, the shade and the crosshair and lets clicks through, so the toolbar is left floating over a live, usable desktop. Pick HEX, RGB or HSL, then hit the eyedropper: the toolbar stays up over hyprpicker, you click a pixel, and the value is copied and shown in a toast with the colour beside it. The output template is set per format, so the zoom lens, the clipboard and the toast all read the same and all three are valid CSS (#RRGGBB,rgb(r, g, b),hsl(h, s%, l%)). Cancelling the pick leaves you on the toolbar; picking a colour ends the session. The toast shows the colour as itself rather than as an icon. hyprpicker is asked for raw components and the string is built here, so the swatch, the clipboard and the format all agree - Toasts -- a compact pill under the bar for things that just need saying.
Any script can raise one:
qs ipc call -- toast show game "Game Mode On", ortoast warn alert "..."for the red variant. Named icons arecopy,check,alert,info,text,gameandcamera; anything else is taken as a raw SVG path - Notifications — a Notifications page for how they behave: whether popups appear at all, how long one stays and whether an application may set its own timeout, how much of the message and how many action buttons show, do-not-disturb with quiet hours between two times and a rule for fullscreen windows, a notification sound picked from Lucid's own eight with its own volume, how many the list keeps, per-application muting, and switches for grouping by application, showing how long ago each arrived, progress bars, inline reply, and how many popups stack at once. Its System events card picks what the machine itself gets a toast for: the keyboard layout, game mode, the charger and battery, Bluetooth and USB devices (the laptop's built-in parts stay quiet), the camera turning on and off with the app using it, Wi-Fi, the sound output, displays and the power profile
- OSD — volume, brightness and microphone, each a badge and a level; Caps
Lock and Num Lock get one too, showing the letters the next keystroke will
make —
ABCagainstabc— rather than the words on and off. Either can be switched off in Settings → General → On-screen display - Desktop — drag across empty desktop and a translucent accent box follows the cursor, the way it does on Windows and macOS; it is cosmetic and selects nothing. Right-click the desktop for wallpaper, theme, the widget panel, a screenshot and settings. Both are switches on the General page
- Date and time — a Date & Time page in Settings holds where the shell
thinks it is. Turn on Auto-detect location — the same switch as the GPS
tile in the bar's system panel — and your position is read from your network
connection every few hours; leave it off and name a town yourself. One
forecast is fetched for that position from
Open-Meteo and shared by the bar clock, the lock
screen and the weather widget, so the three can never disagree. Units on
the same page shows it, and every other temperature in the shell, in °C and
km/h or °F and mph. The time zone
on that page is the machine's, not a private one: picking a zone runs
timedatectl set-timezonebehind a polkit prompt, so every application on the box moves together and Lucid can never drift from the rest of your desktop. Switch on Set it from my location and a new position brings the zone with it. A program reads the zone once when it starts, so anything already open stays on the old one until you restart it — Lucid corrects for that itself and is right either way - Network — a Network page covering what NetworkManager can do. Wi-Fi
radio, a live network list grouped into connected, saved and nearby, with a
filter, a scan you can stop, per-network join with password, forget and
join-automatically, and a form for hidden networks. Share on a saved
network shows it as a QR code a phone camera joins from, with the password
beside it, dotted until you ask and copied without landing in clipboard
history; the Wi-Fi panel in the bar has the same code behind a button. Below that: wired devices
with link speed, VPN and WireGuard profiles to connect and disconnect, a
Wi-Fi hotspot to share the connection, and every saved profile with its
autoconnect switch. Each device also gets its addressing — IPv4, IPv6,
gateway, DNS, MAC, MTU, link rate — and an IP configuration editor that
switches between DHCP and a hand-set address, gateway and DNS, or just
overrides DNS while leaving the rest automatic. Scriptable with
qs ipc call network status | list | rescan - Sound — a Sound page for what plays and what listens. Every output and
every input the machine has, each one named, with what it is doing right now
— its mode and the socket the sound comes out of — and a tick on the one in
use. Click another and it takes over; anything already playing moves across
with it, which is the part that is usually missing. Open a device for its own
volume, its socket — speakers, the headphone jack, the digital output,
with the unplugged ones said to be unplugged — and its mode, the card
profile that decides what devices it offers at all. Below that, everything
making or taking sound right now: a volume and a mute of its own per program,
and a device of its own, so one application can play somewhere else while the
rest stay put. A visualiser or a screen recorder sitting on a monitor is left
where it is rather than dragged onto a microphone. It reads PipeWire directly
and hears about changes as they happen, so it agrees with
pavucontroland with whatever else you use. System sounds mark a USB or Bluetooth device coming and going, the charger, low battery, the camera turning on and off and a screenshot, each with its own switch and a button to hear it, under one volume; they keep quiet while you are silenced, apart from the battery warnings. Tiny ticks answer the volume, brightness, Caps Lock and microphone keys — once where a drag or a held key starts and once where it stops. The page also shows what a device is doing: a live meter under the output and the microphone volume, balance and a Left/Right test for a stereo output, a way to put an app back on the default device, and a Behaviour card for WirePlumber's own settings (remembering each app's volume and device, following the default, pausing when headphones go, headset call mode, mono). The sounds are synthesised bysupport/sounds/build-sounds.pyintoassets/sounds; the ticks start from Kenney's Interface Sounds, which are CC0. Scriptable withqs ipc call settings sound, andqs ipc call sounds play <name>plays any of them - Bluetooth — a Bluetooth page in Settings is a full manager: the radio,
discoverability, whether the machine accepts pairing requests, and the name
other devices see. Below it every device the adapter knows, grouped into
connected, paired and available, with a filter, a scan that stops itself
after a minute, and per device: connect, pair, forget, rename, auto-reconnect,
allow-wake, block, and battery where the device reports it. A connected pair
of headphones also gets its audio mode — high quality versus headset,
whichever profiles PipeWire offers for it — so switching to the microphone
no longer means a trip to
pavucontrol. Receiving files: a phone or laptop sending something over Bluetooth gets a notification with Accept and Decline; accepted, the same notification follows the transfer and the last one opens the file or shows it in its folder. Pick the folder (Downloads by default) and whether paired devices skip the question. Sending files: a paired phone or computer gets Send files in its row, here and in the control centre; pick the files and one notification follows it all — waiting for the other side to accept, progress, Cancel, and how it ended - Phone — a Phone page that is a real KDE Connect client, not a launcher
for someone else's. It drives the KDE Connect daemon over D-Bus, so it pairs,
unpairs and answers pairing requests with the verification key shown on both
sides. Open a connected device and you get: send files through the
desktop's own file chooser, send text or a link, ring it, lock it, mount and
browse its storage, send your clipboard, run the commands you set up on it,
its notifications with dismiss and inline reply, a media remote with
seek and volume for whichever player it is running, its system volume,
and a touchpad and keyboard that drive the phone from this machine. Every
per-device feature can be switched off individually. The phone widget on the
desktop browses the phone's files too, greys out whatever the phone has
switched off, and steps between phones when more than one is paired.
Scriptable too —
qs ipc call kdeconnect status,list,rescan, andqs ipc call -- kdeconnect ring <id> - Storage — a Storage page for what fills your drives: how much each
kind of file takes, a map you can zoom through from your home folder or the
whole disk, what could go (package caches, old trash, duplicates and large
files in your own folders, each with a confirm), and the drives themselves,
with their health from
smartctland mounting throughudisksctl. It warns when space runs low and can empty trash after a number of days - Idle and sleep — an Idle page that owns hypridle for you. It writes
~/.config/hypr/hypridle.confand restarts the daemon whenever something on the page changes, so the ladder — dim, lock, screen off, suspend — is set with sliders rather than by hand. A rail at the top of the page shows the sequence in the order it actually fires and warns when two steps are out of turn. Extras worth knowing: keep awake, a caffeine toggle that holds every step until you turn it off; never interrupt something playing, which asks playerctl before each step; a suspend that can be limited to battery only; and lock-before-sleep plus wake-the-screen-on-resume. Whatever was in your hypridle.conf first is read into the page once and copied tohypridle.conf.pre-lucid, so nothing is lost. Scriptable withqs ipc call idle status | keepawake | on | off | restart - Environment — an Environment page that owns the desktop's appearance
outside the shell. Cursor theme, size and shadow, icon theme, GTK theme,
light or dark, the Qt style, and the interface, application, document and
monospace fonts. Pointer shadow has no compositor switch behind it — the
shade is painted into the cursor theme's own images — so turning it off
renders the theme again from its vector sources into
~/.local/share/icons/<theme>-noshadow, copying the original's sizes, hotspots and frame delays exactly, and points everything at that copy. The point is that one choice reaches everywhere: each change is written to GTK 2, 3 and 4, togsettings, to the XCursor fallback theme, to qt5ct and qt6ct, and to Hyprland's env module, andhyprctl setcursorruns so the pointer changes under your hand rather than at the next login. The dock picks a new icon theme up the moment you choose it — Qt only reads the icon theme when a process starts, so Lucid walks the theme directories itself. Only the keys Lucid owns are touched — every comment and every other setting in those files stays where it was, and a toolkit this machine does not use is skipped rather than conjured. It starts by reading what the machine already says, so opening the page changes nothing; Re-read from the system picks those values up again after you have changed appearance with another tool. Turn GTK, Qt or Hyprland off individually if you would rather keep one of them by hand. Scriptable withqs ipc call settings environment - Displays — a Displays page for the screens themselves: resolution,
refresh rate, scale, orientation and adaptive sync, one card per output, which
names the panel and its size and says what it is doing right now. Only modes
the display actually reports are offered, so there is no picking one it cannot
show, and each scale is labelled with the room it leaves for windows — with a
word of warning on the ones that do not divide the panel evenly. More than one
screen adds an arrangement you drag: displays snap to their neighbours' edges
so the pointer has no gaps to fall into, and moving one pins them all where
they already are rather than letting Hyprland shuffle the rest. A display can
mirror another or be switched off, except the last one left on, which neither
the page nor the Hyprland module will let go. The shell itself — the bar, the
dock, the volume popup and the toasts — sits on whichever display you pick,
and widgets with no display of their own follow it; the bar and the dock can
each be sent to a display of their own if you would rather have them apart.
The wallpaper and the desktop menu are drawn on all of them either way, and
so is the lock screen — though only the display the shell is on carries the
password field; the rest show the clock. Unplug the
display it was pinned to and it moves to one that is left, without losing the
pick, so plugging back in puts it back. It all becomes monitor rules in
~/.config/hypr/lucid-monitors.lua, applied without a reload, and a display is keyed by its description rather than its port, so moving the cable keeps what you set. Scriptable withqs ipc call settings displays, and the display the shell sits on withqs ipc call -- displays shell <name|here|next|auto>— worth a keybind if you move between screens - Glass — a Glass page holding one slider for how far the desktop shows
through what is in front of it, and a readout of where that lands. Three
surfaces follow it, each as far as it can take: the shell's own panels, kitty
— whose
background_opacityleaves the text alone, so it can go all the way — and app windows, a quarter as far, because Hyprland fades a window's text along with its background. Any installed app can be frosted on its own, and anything else you have open can be added by its window class. Per-app values become Hyprland window rules in~/.config/hypr/lucid-glass.lua, applied without a reload and pushed onto windows that are already open. Scriptable withqs ipc call settings glass - Settings — a GUI for all of the above, no config file editing.
Twenty-five pages behind a collapsible rail, grouped-list cards, an app bar that collapses
as you scroll, and a reset arrow on anything you have moved off its default.
The search field at the head of the rail finds any option by its name or its
description and opens its page scrolled to it;
Ctrl+F, or just start typing. Scriptable withqs ipc call -- settings search <words>. The General page sets how big the whole shell is (Interface size, 75 to 125 %, without touching the monitor's scale) and how round (Corner rounding, square to half as round again). The first start after an update opens a What's new sheet once; About → What's new brings it back
The lock screen — the clock in the wallpaper's own colour, the weather, battery, network and Bluetooth at a glance, what is playing, the notifications, and the power bar in the corner.
The screenshot toolbar — Photo, Video, Text and Colour, then a region or the whole display — over the desktop it is about to take.
Settings on the Sound page: Lucid's own system sounds, each with a switch and a play button, under one volume for all of them.
Settings on the Storage page — what fills the drive, by kind and as a map you can zoom through — with the control centre and the on-screen keyboard open beside it.
Colours come from one of eight palettes, picked in Settings or via the launcher's Theme mode:
Matugen and Pywal generate a palette from your current wallpaper. Your colour builds one from a single colour you pick, and leaves the wallpaper alone. Catppuccin Mocha, Gruvbox, Nightfox, Nord and Tokyo Night are fixed palettes that don't change with the wallpaper. Anything you import sits alongside them, and the whole list can be dragged into the order you want.
Every palette has a light mode too — Light or dark on the Theme page. Matugen and Pywal re-extract the wallpaper in the mode you pick, Your colour is built again from its colour; the fixed palettes get a light version built from their own colours, so Nord lands on its own Snow Storm and Gruvbox on its own cream. An imported light scheme goes the other way: light mode keeps it exactly as its author made it, and its dark mode is built from its own colours. Light surfaces carry a trace of the accent, and Accent tint on the General page sets how much. The mode is remembered beside the theme, and GTK and Qt applications follow it, switching to the light or dark counterpart of their theme where one is installed.
Generated palettes, at the top of Settings → Colours, shapes what Matugen and Your colour build:
- Your colour — the colour itself: typed as hex, picked from anywhere on
screen (with
hyprpicker), or one of a handful to start from. - Style — matugen's nine scheme types, from the calm Tonal it uses by default through Vibrant, Expressive and Fidelity to Neutral and Monochrome.
- Contrast — from −100 % to +100 %; 0 is the design as specified.
- Colour from the wallpaper — Matugen starts from the wallpaper's most dominant colour. This shows the others it finds (up to four), each as the accent it would give, to start from instead. The pick belongs to that wallpaper: change the picture and it starts from its most dominant again.
Changes apply as you make them, to the shell and every app template.
Light mode, with the palette taken from the wallpaper. The bar, the dock and every widget follow it.
Whichever is active, the shell reads ~/.cache/quickshell/matugen.json — a
flat map of Material 3 colour roles. Changing your wallpaper through Lucid
runs ~/.config/hypr/scripts/wallpaper/set-wallpaper.sh, which sets the
wallpaper and then regenerates that file if the active theme is wallpaper-derived.
Hyprland's window borders follow it as well. modules/decorations.lua reads the
same file, primary for the focused window and surface container for the rest,
and the shell re-applies it every time the palette changes, light mode included.
So does the starship prompt, without Lucid owning it: only the [palettes.colors]
table in ~/.config/starship.toml is repainted, so a prompt you have designed
yourself keeps its shape. Point its styles at color1 to color9 (the comment
above that table says which colour each one carries) and they follow every theme.
Every display gets the same picture, cropped to fill. To treat one differently —
a portrait screen that should letterbox rather than crop, or a second screen
with a picture of its own — put a rule in ~/.config/lucid/wallpaper-outputs.conf,
one output a line:
DP-3 --resize fit --fill-color 000000
HDMI-A-1 ~/Pictures/wallpapers/second.jpg
Any argument that is a file becomes that output's picture; the rest is passed to
awww/swww. Outputs with no rule keep the wallpaper you picked, and colours
are still generated from that one. qs ipc call displays list prints your
outputs, left to right.
If you already use matugen, the installer appends its Quickshell template
to your config.toml and backs up the original — your existing templates are
left alone.
Qt and KDE apps follow the theme too when qt6ct is installed. Qt widget apps
read their palette from qt6ct, so the installer points qt6ct.conf at the one
a template writes, ~/.config/qt6ct/colors/lucid.conf. KDE apps (Dolphin,
Kate, Okular…) need one more step: outside Plasma, they swap that palette for
Breeze as they start unless kdeglobals names a colour scheme. So a second
template writes ~/.local/share/color-schemes/Lucid.colors, and kdeglobals
gets [UiSettings] ColorScheme=Lucid. A palette you already picked in qt6ct,
or a scheme already named in kdeglobals, stays as it is. An open Qt app
repaints a few seconds after the theme changes: qt6ct rereads its palette when
something in ~/.config/qt6ct changes, and the template's hook touches
qt6ct.conf. KDE apps only read their colour scheme as they start, so one that
is already open changes the next time you open it.
Every template in ~/.config/matugen/config.toml follows whichever palette is
active, not only the wallpaper ones: picking Nord or Catppuccin renders them
with that theme's colours. That makes the config the place to theme any other
application — put a template in ~/.config/matugen/templates/ and add a block
for it:
[templates.myapp]
input_path = '~/.config/matugen/templates/myapp.css'
output_path = '~/.config/myapp/colors.css'
post_hook = 'pkill -USR1 myapp' # optional: tell the app to reloadTemplates use matugen's syntax —
{{colors.primary.default.hex}} and so on. A fixed palette fills every role it
defines with its own colour; the few it doesn't (the *_fixed family, the
tonal palettes, base16) come from a scheme matugen derives from its primary.
Each template renders on its own, so one that fails doesn't hold the rest back:
a toast names it, and ~/.cache/lucid/templates.json keeps what happened to
every template on the last change, with matugen's error for the ones that
failed. ~/.config/lucid/render-templates.sh is what renders them, for the
wallpaper and the fixed palettes alike.
Settings → Colours (qs ipc call settings colours) shows the same thing
without opening the file:
- App templates lists every template with the file it writes and how the last change went, matugen's reason included when one failed. A switch turns a template off (its block stays in the config, commented out) or back on, in which case it renders at once with the current colours. Render again redoes all of them without touching the wallpaper.
- Add an app offers the templates Lucid ships for applications you have installed but that aren't wired up yet — installed after Lucid, say.
- Your own template adds one from a file or an
https://link. Try it shows what it writes with your colours, or why it can't, before it's added. Below it, every colour role of the current palette: click one to copy the variable that writes it, as#rrggbb,rrggbb,rgb(),rgba()orhsl().
~/.config/lucid/templates.py does the editing, and runs from a terminal too
(templates.py list, set <name> on|off, add, remove, try). The config
is copied to config.toml.lucid-backup before each change.
Settings → Palettes (qs ipc call settings palettes) has a gallery of
the few hundred base16 and base24 schemes that
tinted-theming collects, each drawn
in its own colours, searchable, and split into dark and light. Download fetches
the whole collection once (about half a megabyte, kept in
~/.cache/lucid/schemes); after that, hovering a scheme offers Add, which
makes it one of your themes, and Use, which also switches to it.
The same page takes the URL of any colour-scheme repo, or a scheme file you already have, clones or reads it, and builds a full Material 3 palette out of what it finds. Scheme repos agree on no common format, so detection is tiered: base16 and base24 YAML, name-keyed JSON (Catppuccin and friends) and palettes Lucid exported are read exactly, and anything else falls back to harvesting hex codes and sorting them by tone and chroma. A repo carrying several variants lists them so you can pick one, and wallpapers in the repo come along with it.
Nothing from the repo is ever executed — only text is parsed and only images are copied.
It writes ~/.config/lucid/themes/<id>/{quickshell.json,meta.json} and
~/Pictures/wallpapers/<id>/, which you can also do by hand: a
quickshell.json with the same keys as the bundled palettes is all a theme is.
The importer runs from a terminal too, on a repo URL or a local file or folder:
python3 ~/.config/lucid/add-theme.py <repo-url|file|folder> [--list] [--variant <name>] [--name <label>]
python3 ~/.config/lucid/scheme-gallery.py update # the gallery, downloaded and indexedFurther down the page, the editor works on the palette on screen. Six key colours (background, text, primary, secondary, tertiary, error) each rebuild the whole palette the way an imported scheme is built, and every other role can be set by itself; the shell wears the draft while you work, and Save as theme keeps it (Discard, or closing Settings, puts the palette back). Export writes the palette on screen to a file: a Lucid palette, which keeps every role and imports back exactly, or base16 YAML for tinted-theming's tools and anything else that reads base16.
The exporter runs from a terminal too:
python3 ~/.config/lucid/palette-edit.py export ~/.cache/quickshell/matugen.json <lucid|base16> <file> [<name>]Arch Linux and Hyprland. The installer handles all of this, listed here so you know what's being pulled in.
Required — the shell won't start without these:
quickshell · qt6-5compat · qt6-declarative · qt6-multimedia
Per feature — a missing one breaks only its own feature:
| Package | Backs |
|---|---|
matugen, jq |
Wallpaper-derived colours, theme switching |
git |
Importing a theme from a scheme repo on Settings → Theme |
awww |
Setting the wallpaper |
python-pywal |
The Pywal theme |
networkmanager |
Wi-Fi panel |
qrencode |
The QR code that shares a saved Wi-Fi network. Without it the password still shows, with no code |
bluez, bluez-utils |
Bluetooth panel and the Bluetooth settings page |
bluez-obex, python-gobject |
Sending and receiving files over Bluetooth. Without bluez-obex the page says so, files sent to the machine are turned away and sending says what is missing |
kdeconnect, python-gobject |
The KDE Connect page. The daemon is the backend and starts itself; python-gobject backs the bridge Lucid talks to it through. Without either the page says so and does nothing else |
sshfs |
Browsing a phone's files from the phone widget or the KDE Connect page. Without it KDE Connect cannot mount the phone and the button does nothing |
libpulse, wireplumber |
Volume, audio devices, and playing Lucid's sounds |
inotify-tools |
The camera on/off toast and sound. Without it the camera is never watched; nothing else changes |
smartmontools, udisks2 |
The Storage page's drive health and mounting. Without them those two rows say so; the map and the cleanup work either way |
ffmpegthumbnailer, gvfs |
The desktop icons: thumbnails of videos and music with cover art, and the drives and Trash shown on the desktop |
pipewire-audio, sound-theme-freedesktop |
The Sound page's Left/Right test: pw-play, and the voice that names each side. Without them the test plays nothing |
brightnessctl, upower |
Brightness, battery |
hyprsunset |
Night light. Lucid starts it when night light first comes on and talks to it over hyprctl hyprsunset; one you already run is used as it is, and never reset unless Lucid warmed it |
hypridle |
The Idle page: dimming, locking, screen off and suspend when you walk away. Without it the page says so and writes nothing |
grim, wf-recorder, ffmpeg, imagemagick |
Screenshots and recording |
tesseract, tesseract-data-eng |
The Text mode's OCR. Without them Text mode says so and copies nothing. Add tesseract-data-<lang> and set ocrLang in lucidshot/Screenshot.qml for another language |
python-pillow, python-numpy, python-fonttools |
Emoji in copied text. Without them the text still copies, minus the emoji. The glyph atlas is built once and cached in ~/.cache/lucidshot-ocr; lucidshot/emoji-ocr.py --atlas builds it up front so the first copy is not slow |
wl-clipboard, wtype |
Emoji and GIF pasting |
cliphist |
Clipboard history. Without it the launcher's Clipboard mode says so and the Launcher page's switch is greyed out |
cava |
Audio visualisers — the media panel's strip (its config is installed to ~/.config/cava/quickshell.conf; the strip needs that file's raw-ascii output settings) and the desktop widget, which writes its own ~/.cache/quickshell/lucid-cava.conf at whatever band count the widest card asks for |
songrec |
Song identification |
curl |
Weather, location lookup and GIF search |
polkit |
Every administrator prompt. The shell registers itself as the session's authentication agent and drives polkit's own setuid helper, so no separate agent is needed — and no other agent should be started, as only one can hold the session |
accountsservice |
The Users and Accounts page. Every change goes through it, so the shell's own polkit dialog asks and nothing runs as root |
libnotify |
Notification actions |
swappy |
Marking up a screenshot, from its preview card or notification |
hyprpicker |
The Colour mode. Without it the mode says so and picks nothing |
xdg-utils |
Opening links and files from the shell |
librsvg |
Turning the pointer's shadow off — the cursor theme is rendered again from its vector sources |
noto-fonts-emoji |
Emoji rendering |
The Hyprland config and the look — installed unless you pass --no-hypr
or --no-look. The binds shell out to these, so a missing one is a dead key:
| Package | Backs |
|---|---|
kitty |
Terminal (F9), and the themed terminal colours |
fish |
The shell kitty opens |
nautilus |
Files (SUPER+E) |
playerctl |
The media keys |
gnome-calculator |
Calculator (F12) |
starship |
The prompt |
ttf-jetbrains-mono-nerd |
The glyphs the prompt and kitty are drawn with |
adw-gtk-theme |
Provides adw-gtk3-dark, the GTK theme Lucid selects |
papirus-icon-theme |
Fallback icons — FairyWren declares Inherits=Papirus |
The dock's default pins — installed unless you pass --no-apps. Several
GB, mostly from the AUR:
zen-browser-bin · vscodium-bin · spotify · vesktop · nautilus ·
steam · proton-vpn-gtk-app
Anything you already have an equivalent of is left alone — vscodium counts
for vscodium-bin, discord for vesktop, and so on. steam is skipped
unless the multilib repo is enabled; with it come the Vulkan drivers for the
graphics cards the machine has (vulkan-radeon, vulkan-intel, NVIDIA's own or
nouveau, and their 32-bit halves), so pacman never has to guess one.
Lucid uses Hyprland-specific APIs for workspaces and window management. It will not work on other compositors.
The default UI font is Google Sans, which is not in the Arch repos. If you don't have it, Qt falls back to your default sans and everything still works — or pick any installed font in Settings → General.
GIF search needs a free Giphy key (email only, no card) from
developers.giphy.com. Put it in
~/.config/quickshell/lucidmoji/config.json:
{ "giphyKey": "your-key-here", "tenorKey": "", "gifDir": "" }Tenor works too if you'd rather use that. Emoji and kaomoji need no key.
Wallpapers default to ~/Pictures/wallpapers, one folder per theme —
~/Pictures/wallpapers/gruvbox is what the strip shows while you are on
Gruvbox. The installer puts a set in each of them, skipping any file you already
have, and --no-wallpapers leaves the folder alone entirely. Change the folder
in Settings → General, which then applies to every theme.
Every surface is scriptable. qs ipc call -- <target> <function> [arg]:
| Target | Functions |
|---|---|
launcher |
toggle open close wallpaper theme power blur command shuffle clipboard emoji search <query> hide <id> unhide <id> hidden |
settings |
toggle open close show <page> general users glass bar dock colours palettes environment keybinds input displays widgets windows workspaces notifications sound network bluetooth kdeconnect idle datetime font search <words> reset |
idle |
status keepawake awake normal on off restart |
network |
status list rescan |
nightlight |
toggle on off status |
kdeconnect |
status list rescan ring <id> ping <id> clipboard <id> files <id> send <id> <path> |
desktop |
icons (hide or show the desktop icons) arrange selectAll undo refresh |
bluetooth |
send <address> <path> (an empty path opens the file chooser) |
widgets |
panel openPanel <screen> closePanel add <type> <variant> remove <uid> clear toggle lock unlock list catalogue settings resize <uid> <w> <h> |
moji |
toggle open close emoji kaomoji gif center |
keyboard |
toggle open close letters fnkeys center bigger smaller |
notifs |
toggle open close clear toggleDnd expandAll settings count |
lock |
lock unlock isLocked status — nothing here bypasses the password; PAM is the only way in |
snap |
toggle open close text color video |
session |
toggle open close |
switcher |
next prev toggle open close status — next/prev open it when it is closed |
timer |
start <seconds> stopwatch pomodoro pomodoroSkip pomodoroStop pomodoroAdd <minutes> status |
clock |
open <tab> toggle close — tab is today, calendar, timer, stopwatch or world |
toast |
show <icon> <label> warn <icon> <label> |
sounds |
play <name> list — at the system-sound volume |
screenshot |
full text |
media |
toggle open close identify playPause next previous |
workspaces |
toggle open close |
updates |
status check whatsnew (the What's new sheet for this version) update (install the newest release) beta (install the newest commit on main) show (bring back a hidden update pop-up) |
displays |
list settings shell <where> bar <where> dock <where> — where is an output name, left/middle/right, here, next, prev or auto |
polkit |
status demo <action-id> fail grant close — demo raises the dialog with no PAM session behind it, for previewing a theme |
debug |
toggle on off — draws input and blur region outlines |
./uninstall.shMoves ~/.config/quickshell aside rather than deleting it, so your settings
survive. Packages installed by install.sh are left alone. It prints what else
it left in place — the matugen template blocks, ~/.config/hypr,
starship.toml and its init lines in your rc files, the fastfetch config,
kitty's colour and opacity includes — each with a timestamped backup beside it, so you can undo
them by hand.
The media popup's visualiser sits flat and never moves.
cava is running without ~/.config/cava/quickshell.conf — its own defaults emit
ncurses output rather than the raw ascii frames the strip parses, so there is
nothing to draw. Re-run the installer, or copy support/cava/quickshell.conf
there yourself. Before v1.0.0 this showed as one enormous bar covering the
popup instead.
Another app's notifications show instead of Lucid's.
org.freedesktop.Notifications is a single-owner D-Bus name. Lucid's bar
serves it, but any other notification daemon that is merely installed —
swaync, dunst, mako — gets D-Bus-activated by the first notification and then
keeps the name for the whole session. It does not need to be autostarted to
win. Check who holds it:
busctl --user status org.freedesktop.Notifications | grep PIDIf that is not quickshell, mask the daemon and log back in:
systemctl --user mask swaync.service # or dunst.service, mako.service
pkill swayncThe installer offers to do this for you.
GTK apps are light, or their icons are wrong.
Under Hyprland there is no xsettings daemon, so GTK3/GTK4 read
~/.config/gtk-{3,4}.0/settings.ini while GNOME apps and portals read
gsettings. The installer writes both. If only some apps changed, check they
agree:
gsettings get org.gnome.desktop.interface gtk-theme # adw-gtk3-dark
gsettings get org.gnome.desktop.interface icon-theme # FairyWren_Dark
grep -E 'theme-name' ~/.config/gtk-3.0/settings.ini ~/.config/gtk-4.0/settings.iniThe icons live in ~/.local/share/icons/FairyWren_Dark. If that directory is
missing the installer could not reach GitLab — clone it by hand from
https://gitlab.com/FreshDoctor/FairyWren-Icons.
Nothing appears when I run qs. Check qs log for QML errors, and
confirm you're on Hyprland — Lucid needs its Wayland protocols.
Everything is grey / colours look wrong. The palette cache is missing or
empty. Set a wallpaper through Settings → General, or copy a bundled palette:
cp ~/.config/lucid/themes/nord/quickshell.json ~/.cache/quickshell/matugen.json
The blur frosts my windows instead of the desktop. Hyprland's blur samples
whatever is behind the layer. Lucid leaves that on so a panel opened over a
window shows the window; if you would rather have every pill frost the
wallpaper, uncomment the xray line at the end of
~/.config/hypr/modules/layerrules.lua, or add this to hyprland.lua:
hl.layer_rule({ match = { namespace = "quickshell" }, xray = true })A Lua config cannot source a .conf file, so the old layerrule = xray 1, quickshell line has nowhere to go.
Icons look blurry. A fractional monitor scale factor puts icons on
fractional pixels. Use an integer scale, or adjust the icon size in Settings.
Animations feel choppy on an NVIDIA card, even at 144Hz or higher. Qt's Wayland plugin refuses threaded OpenGL on the proprietary NVIDIA driver — that is its workaround for QTBUG-95817 — so Qt Quick falls back to the basic render loop, whose animation driver is a fixed ~16ms timer with no vsync awareness. Every animation in the shell is then pinned to ~60fps however fast the monitor runs, which is why Hyprland stays smooth while Lucid does not.
Lucid starts through ~/.config/lucid/launch-shell.sh, which moves those
machines to Qt's Vulkan backend — Vulkan carries no such vendor check, so the
threaded loop and its vsync-driven animations come back. Ask it what it decided:
~/.config/lucid/launch-shell.sh --explainIt only switches when NVIDIA is the GPU the compositor actually renders on, the
driver is 555 or newer, and an NVIDIA Vulkan driver is present. Mesa already
gets the threaded loop and is left alone. Override the detection with
LUCID_RHI_BACKEND=vulkan or LUCID_RHI_BACKEND=opengl; an existing
QSG_RHI_BACKEND in your environment always wins.
A keybind with an argument does nothing. Add -- before the target:
qs ipc call -- settings show bar. Without it qs parses the argument as its
own and refuses the call. Argument-free calls work either way.
Issues and PRs welcome. If you're reporting a bug, qs log output and your
Hyprland version help a lot.
The logo is Lucida — the astronomical term for the brightest star in a constellation, sharing its Latin root (lux) with "Lucid". A broken orbit ring, a four-point star at the centre, and one companion dot outside the gap.
Its official colour is coral #FF7F50. In the shell itself the ring and the
companion dot track your accent, so the mark on the dock launcher recolours with
whatever palette you are running — but coral is the canonical brand colour, and
what you see above.
assets/logo.svg is the mark on its dark plate; assets/logo-mark.svg is the
bare coral mark for light and dark backgrounds alike. Both are drawn from the
same 24×24 geometry as LucidaMark.qml.
MIT — see LICENSE.
Built on Quickshell. Colour generation by matugen. Design follows Material 3 Expressive.








