Skip to content
zaroc-devPublic

About

yuki: a Quickshell desktop shell for niri (bar, launcher, lock screen, Material You theming)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

yuki

A Quickshell desktop shell for niri. One frosted strip is fused to the top edge of each screen; its ends curve down into rounded screen corners. Every panel grows out of the bar's bottom edge, joined by concave fillets so the two read as one liquid surface. Panels near a screen edge snap to it and run down the side like a drawer. Along the bar's edge runs the horizon, a thin aurora line that carries on around every panel and gathers light: under the cursor, where panels join, in a sun that crosses the screen once a day, and in a comet that shoots across when a notification arrives.

Part Contents
left start badge + app launcher, niri workspaces of this output (the active one as a live minimap of its columns), its active window
middle clock/date (digits roll over) → dashboard
right now playing (cover in a progress ring, equalizer, controls) · tray · bluetooth, network (name on hover), volume, battery · notifications · power

Every widget has a panel: media controls + seek + player switcher, a dashboard, a notification center (with do-not-disturb), the network (wired, VPN and Wi-Fi; see below), and audio (output/input sliders and device pickers). The shell is also the notification daemon: toasts drop out of the bar's top-right corner as a drawer. The launcher and clipboard history grow out of the middle of the bar.

Desktop services

device battery, disconnect and forget buttons (forget asks for a second click). device battery, forget (right-click).

  • Network: Wi-Fi join form with password reveal and inline errors, enterprise (802.1X: PEAP/TTLS, identity, domain, CA) and hidden networks ("Add network…"), forget for saved networks. VPN on/off for Mullvad (its CLI) and NetworkManager VPN/WireGuard profiles, with a shield on the bar icon while one is up.
  • Clipboard: history via cliphist (the shell runs the wl-paste --watch recorders), a searchable panel with image thumbnails, Enter copies, Del removes.
  • Screenshots: niri's own tools (region/screen/window from the start menu or IPC); the shell shows a toast with a thumbnail and Open / Show folder.
  • Audio: the volume popup has output/input device pickers and a per-app mixer (a slider per playing app; click its icon to mute). While an app records from the microphone, a red mic shows next to the volume and the popup names the app.
  • OSD: volume/brightness drops out of the middle of the bar on the focused screen for any change (keys, apps).
  • Idle: lock and screen-off timers, respecting apps that inhibit idle; "Awake" toggle.
  • Dashboard: click the clock. A greeting with a giant clock, uptime and sunrise/sunset; weather now, the next hours as a temperature curve, the next 6 days; the calendar; now playing; CPU, memory, disk and CPU temperature gauges (polled only while it's open). The lock screen shows the current weather under the date.
  • Weather: Open-Meteo (no API key), cached in ~/.cache/quickshell/by-shell/yuki/weather.json and refreshed every 30 min while in use. Set a city or lat,lon in Settings → Bar; left empty, the location comes from your IP via ipinfo.io. Nothing is fetched until the dashboard or lock screen needs it.
  • Window switcher: Alt+Tab over the windows in most-recently-used order (Tab / Shift+Tab / arrows, release Alt to switch, Esc cancels), in three looks to pick from in Appearance: cards, list, or an island under the bar. App icons for now; live previews wait on window capture in niri. Your niri binds take precedence over niri's own switcher, so binding Alt+Tab (below) is all it needs.
  • Power: power-profiles-daemon picker (power menu, battery popup, settings).
  • Polkit: yuki is the authentication agent (pkexec, GNOME Disks, …): a centered dialog on the focused screen with the action, the identity (click to switch when there are several admins) and a password field. If another agent already runs, yuki logs a warning and leaves it alone.
  • App colors: niri, kitty and GTK snippets in ~/.local/state/yuki/theme/ (see App colors), plus a blurred wallpaper for niri's overview backdrop.

Start menu & settings

The distro icon opens the start menu:

  • Header: avatar, user@host and uptime, with buttons for settings, lock and power.
  • Pinned apps: right-click a tile to unpin.
  • Frequent apps: the ones you launch most.
  • Wallpaper card: previous, next and shuffle for that screen.
  • Quick toggles: Dark/Light, Dynamic colors, Silent (do not disturb).

The grid icon next to it opens the launcher. Right-click an app there to pin it; with an empty search, apps are sorted by how often you launch them.

Settings (gear in the start menu, or ipc call settings open [page]):

  • Appearance: color source, dark/light mode, which screen's wallpaper the colors come from, Material scheme (with live previews), Catppuccin flavor and accent, blur and opacity.
  • Wallpaper: management on/off, folder, per-screen or all-screen picker, shuffle.
  • Bar: clock format, date, media and active-window widgets.
  • Notifications: do not disturb, toast duration, clear all.
  • Start menu: reorder and unpin pinned apps.
  • About: paths and reload.

Wallpapers & dynamic colors

The shell draws the wallpaper itself, one per output, with a fade-and-settle transition. Outputs without their own wallpaper use the default (or the first image in the folder, ~/wallpapers by default).

Turn off Manage wallpapers in Settings → Wallpaper to let another app manage the compositor background. This removes yuki's desktop wallpapers and overview backdrops immediately. Choices are preserved and still used for the lock screen and dynamic colors; turning management back on restores them. The setting wallpaperEnabled defaults to true and persists across restarts.

With the color source set to wallpaper, the seed color of one output's wallpaper (the output at 0,0 unless set otherwise) is extracted with Google's material-color-utilities (vendored in lib/mcu, run in a WorkerScript) and turned into a Material You scheme. tonal-spot is the same scheme noctalia's m3-tonal-spot uses, so you get matching colors. Seeds are cached per image in the settings file.

Power menu & lock screen

The power button opens tiles for Lock, Suspend, Log out (E), Restart and Shut down (P). Log out, restart and shut down need a second press within 4 s. Suspend locks first and suspends once every output is covered. So does any other suspend (lid, systemctl suspend): yuki holds a logind delay inhibitor until the lock screen is up ("Lock before sleep" in System settings). loginctl lock-session and unlock-session lock and unlock it too.

The lock screen is a real ext-session-lock. Each output's wallpaper blurs in when it locks and back out on unlock. If the shell crashes while locked, it locks again as soon as it restarts. It shows a clock, your avatar (~/.face.icon), and a password field authenticated through PAM (pam/password.conf, plain pam_unix). Also: now-playing controls, the niri keyboard layout, and suspend/restart/shut down.

yuki ipc call lock preview shows the same UI without locking (Esc leaves). Use it to tweak the design safely.

If the shell ever dies while locked, niri keeps the session locked (by design). Recover from a TTY (Ctrl+Alt+F2):

WAYLAND_DISPLAY=wayland-1 yuki &   # start a new instance
WAYLAND_DISPLAY=wayland-1 yuki ipc call lock lock

and unlock normally on the new lock screen.

For idle locking, have swayidle/hypridle call yuki ipc call lock lock.

Nix flake

inputs.yuki.url = "github:zaroc-dev/yuki";
Output What
packages.<system>.yuki (default) yuki = qs -p <config> with cliphist, wl-clipboard, brightnessctl, xdg-utils on PATH. yuki ipc call … talks to it. .override { configDir = "/path"; } runs a checkout instead of the store copy
packages.<system>.sddm-theme .override { background = ./wall.jpg; settings = { accent = "#…"; }; }
packages.<system>.plymouth-theme .override { accent = …; base = …; surface = …; text = …; }
homeManagerModules.default programs.yuki = { enable; configDir; systemd.enable; gtk.enable; }
nixosModules.default programs.yuki = { sddm = { enable; background; }; plymouth.enable; palette = { … }; }

For hot reload, point configDir at a checkout (e.g. an out-of-store symlink): the shell then runs the live QML, and settings are shared with the packaged build because the shell id is pinned (//@ pragma ShellId yuki).

# home-manager
imports = [ inputs.yuki.homeManagerModules.default ];
programs.yuki = {
  enable = true;
  configDir = "${config.home.homeDirectory}/source/shell";
};

# nixos
imports = [ inputs.yuki.nixosModules.default ];
programs.yuki = {
  sddm = { enable = true; background = ./wallpapers/raiden.shogun.jpg; };
  plymouth.enable = true;
};

Running

Needs niri, NetworkManager, PipeWire, UPower, BlueZ, power-profiles-daemon, and the fonts Inter and JetBrainsMono Nerd Font (the home-manager module installs the fonts).

nix run github:zaroc-dev/yuki                       # try it
nix run nixpkgs#quickshell -- -p ~/source/shell     # from a checkout (hot reload)

In niri's config.kdl:

spawn-at-startup "yuki"

and in keybinds.kdl:

Mod+Space   hotkey-overlay-title="App Launcher"  { spawn "yuki" "ipc" "call" "launcher" "toggle"; }
Mod+N       hotkey-overlay-title="Notifications" { spawn "yuki" "ipc" "call" "bar" "toggle" "notifications"; }
Super+Alt+L hotkey-overlay-title="Lock"          { spawn "yuki" "ipc" "call" "lock" "lock"; }
Alt+Tab     hotkey-overlay-title="Switch Windows" { spawn "yuki" "ipc" "call" "switcher" "next"; }
Alt+Shift+Tab                                    { spawn "yuki" "ipc" "call" "switcher" "prev"; }

If another notification daemon is running, it owns org.freedesktop.Notifications and yuki shows no toasts until it exits; then yuki takes the name over.

Interaction

Where Action
start button click: start menu · right-click: cycle themes
launcher button click: launcher
media click: popup · middle: play/pause
workspaces click: focus · minimap tile: focus that window · scroll: up/down
notifications click: center · right-click: toggle do-not-disturb
volume click: popup · scroll: ±5% · middle: mute
tray item click: activate · right-click: menu · middle: secondary
power click: power menu (keys L S E R P inside)
launcher type to filter · ↑/↓/Tab · Enter launches · Esc closes

IPC

yuki ipc show
yuki ipc call launcher toggle|open|close
yuki ipc call switcher next|prev|close · style cards|list|island
yuki ipc call bar toggle media|dashboard|notifications|network|volume|power
yuki ipc call lock lock|preview|closePreview|isLocked
yuki ipc call vpn toggle|on|off <name or ""> · status
yuki ipc call settings open [appearance|wallpaper|bar|notifications|start|about]
yuki ipc call wallpaper enable true|false · toggle
yuki ipc call wallpaper set <output|all> <path>
yuki ipc call wallpaper random <output> · shuffle · get <output>
yuki ipc call theme source wallpaper|catppuccin|custom
yuki ipc call theme mode dark|light
yuki ipc call theme scheme tonal-spot|content|expressive|fidelity|fruit-salad|monochrome|neutral|rainbow|vibrant
yuki ipc call clipboard toggle|clear
yuki ipc call screenshot region|screen|window
yuki ipc call audio up <step>|down <step>|mute|micMute
yuki ipc call media toggle|next|previous
yuki ipc call brightness up|down|set <percent>
yuki ipc call idle toggleKeepAwake
yuki ipc call bar toggle start|media|dashboard|notifications|bluetooth|network|volume|battery|power
yuki ipc call shell reload [true = hard]
yuki ipc call power run lock|suspend|logout|reboot|poweroff
yuki ipc call theme flavor mocha|macchiato|frappe|latte|custom
yuki ipc call theme accent mauve|blue|pink|…
yuki ipc call theme cycle
yuki ipc call notifications toggleDnd|clear

The network popup lists NetworkManager VPN/WireGuard profiles and Mullvad. OpenConnect profiles launch browser authentication in the desktop session, then NetworkManager manages the tunnel without a terminal. Toggle off to disconnect, or to cancel a pending login. Session cookies are passed in memory and are not saved in the profile. Install the corresponding NetworkManager VPN plugin on the host (for NixOS, networking.networkmanager.plugins).

Theming

All colors come from config/Theme.qml. Whatever the source, it exposes the same Catppuccin-shaped palette, so every widget works with every theme. Settings persist in ~/.local/state/quickshell/by-shell/yuki/settings.json. The file is watched, so editing it by hand restyles the shell live.

  • themeSource: "wallpaper": Material You from the wallpaper (scheme, themeMode, colorScreen)
  • themeSource: "catppuccin": flavor + accent, with light mode = Latte
  • themeSource: "custom": Mocha overridden by any keys in custom

blur uses niri's ext-background-effect. With it off, surfaces fall back to near-opaque.

App colors

Whenever the palette changes, yuki writes color files to ~/.local/state/yuki/theme/ and nudges niri and kitty to reload. Include them from your configs (absolute paths):

// niri config.kdl
include optional=true "/home/you/.local/state/yuki/theme/niri.kdl"
# kitty.conf
include /home/you/.local/state/yuki/theme/kitty.conf

GTK 3/4 gtk.css are pointed at gtk3.css / gtk4.css by the home-manager module (programs.yuki.gtk.enable, on by default). colors.json has the full Material palette for anything else.

Layout

shell.qml            root: wallpapers, bars, toasts, launcher, lock screen, settings, IPC
lib/                 material.mjs (Material You), vendored material-color-utilities, color worker
wallpaper/           per-output Wallpaper windows, ColorExtractor
settings/            SettingsWindow and its pages
extras/sddm/yuki/    SDDM login theme in the lock screen's design
extras/plymouth/     Plymouth boot theme + image generator
config/              Settings (persisted), Theme (palette from wallpaper/Catppuccin), Wallpapers, Icons
services/            singletons: Niri (IPC event stream), Audio, Media, Net, Notifs, Apps, Lock, Power, Ui
components/          Surface (the fused panel shape), BarPopup, DropSheet, BarButton, PanelHeader, SectionLabel, StyledSlider, …
bar/                 Bar + one file per widget
popups/              per-widget popups (incl. PowerMenu, TrayMenu), Launcher, NotificationToasts
lock/                LockScreen (session lock + preview windows), LockSurface (the UI)
pam/                 PAM config used by the lock screen

Known limitations

  • Popups opened from IPC can't take a pointer grab (Wayland only grants that in response to a click). They close when window focus changes instead of on any outside click.

License

Apache-2.0, see LICENSE. lib/mcu is Google's material-color-utilities, also Apache-2.0 (its own LICENSE is kept there).

About

yuki: a Quickshell desktop shell for niri (bar, launcher, lock screen, Material You theming)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages