Personal fork of jutraim's niri-caelestia-shell (Niri adaptation of Caelestia Shell) with my tweaks. WIP ๐ง
out.mp4
Caution
This is my personal fork and it's STILL WORK IN PROGRESS.
I am still learning Quickshell and this is my first time working with it. I'm trying to learn and improve! ๐
This repo is ONLY for the desktop shell of the Caelestia dots. For the default Caelestia dots, head to the main repo instead.
Based on jutraim's niri-caelestia-shell with these additions:
- Config Editor: Visual JSON editor with searchable icon/font pickers, array editing (battery warnings, idle timeouts), nested object support
- Battery Monitor: Configurable warning notifications at custom levels with icons and messages
- Enhanced Workspace Bar: Program icons, drag-to-reorder windows, context menus, app grouping
- System Monitor: Real-time CPU/GPU/Memory stats (AMD/NVIDIA, no Intel yet)
- Niri Integration: Dashboard controls for Niri IPC commands
- Launcher Modes: Integrated clipboard, web search, calculator, and more โ all triggered via
>prefix - OCR & Google Lens: Region picker modes for text extraction (Tesseract) and visual search (Google Lens)
- Area Picker Modes: Custom cursor indicators for screenshot, OCR, and Lens modes
All built on top of the Niri window manager adaptation from the upstream fork.
You need both runtime dependencies and development headers.
- All dependencies in plain text:
quickshell-git networkmanager fish glibc qt6-declarative gcc-libs cava libcava aubio libpipewire ddcutil brightnessctl ttf-material-icons-git ttf-jetbrains-mono grim swappy app2unit libqalculate python-materialyoucolor wl-clipboard cliphist tesseract tesseract-data-eng curl
Note
Unlike the default shell,
caelestia-cli is not required for Niri.
Detailed info about all dependencies
| Category | Packages |
|---|---|
| Core | quickshell-git, networkmanager, networkmanager-qt, fish, glibc, qt6-declarative, gcc-libs |
| Audio & Visual | cava, libcava, aubio, libpipewire, ddcutil, brightnessctl, materialyoucolor |
| Fonts | ttf-material-icons-git, ttf-jetbrains-mono |
| Screenshot & Utils | grim, swappy, app2unit, libqalculate, tesseract, tesseract-data-eng, curl |
| Clipboard | wl-clipboard, cliphist |
| Build | cmake, ninja |
To install the shell manually, install all dependencies and clone this repo to ~/.config/quickshell/niri-caelestia-shell.
Then simply build and install using cmake.
For a fully automated installation including all dependencies, system configuration, and building the shell:
git clone https://github.com/Ayushkr2003/niri-caelestia-shell && cd niri-caelestia-shell && ./scripts/setup/v2/setup installWarning
This automated installer is currently in beta and may contain bugs. I am still working on refining the process! If you encounter issues, please use the Manual Build steps below.
-
Install dependencies.
-
Clone the repo:
cd ~/.config/quickshell git clone https://github.com/Ayushkr2003/niri-caelestia-shell
-
Build:
cd ~/.config/quickshell/niri-caelestia-shell cmake -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/ cmake --build build sudo cmake --install build
It's trying to install into system paths (
/usr/lib/qt6/qml/Caelestia/...), so grab the necessary permissions or use sudo while installing.If you get
VERSION is not set and failed to get from giterror, that means I forgot to tag version. You can dogit tag 1.1.1to work around it :) -
Run the setup script (installs system packages, Python venv, services):
./scripts/setup/setup.sh
The setup script supports flags:
--skip-deps,--skip-python,--skip-services -
Deploy dotfiles:
cp -r dotfiles/.config/* ~/.config/
[!IMPORTANT] Copying the
matugenfolder to~/.config/is mandatory for system-wide color syncing to work. -
(Optional) Setup SDDM Theme:
bash dotfiles/niri-caelestia-sddm/setup.sh
Select option
1during setup to sync colors directly with the shell.
You can update by running git pull in ~/.config/quickshell/niri-caelestia-shell.
cd ~/.config/quickshell/niri-caelestia-shell
git pullDetailed prerequisites and step-by-step setup for wallpaper-driven theming are provided in THEME.md. See: THEME.md
The shell can be started via the qs -c niri-caelestia-shell on your preferred terminal.
(qs and quickshell are interchangable.)
-
Example line for niri
config.kdlto launch the shell at startup:spawn-at-startup "quickshell" "-c" "niri-caelestia-shell" "-n"
All IPC commands can be called via quickshell -c niri-caelestia-shell ipc call ...
-
For example:
qs -c niri-caelestia-shell ipc call mpris getActive <trackTitle>
-
Example shortcut in
config.kdlto toggle the launcher drawer:Mod+Space { spawn "qs" "-c" "niri-caelestia-shell" "ipc" "call" "drawers" "toggle" "launcher"; }Mod+Space hotkey-overlay-title="Caelestia app launcher" { spawn-sh "qs -c niri-caelestia-shell ipc call drawers toggle launcher"; }
The list of IPC commands can be shown via qs -c niri-caelestia-shell ipc show.
Ipc Commands
โฏ qs -c niri-caelestia-shell ipc show
target picker
function open(): void
function openFreeze(): void
function regionOcr(): void
function regionSearch(): void
target quicktoggles
function open(): void
function toggle(): void
function close(): void
target idleInhibitor
function toggle(): void
function enable(): void
function isEnabled(): bool
function disable(): void
target wallpaper
function get(): string
function set(path: string): void
function list(): string
target clipboard
function open(): void
function toggle(): void
function close(): void
target drawers
function toggle(drawer: string): void
function list(): string
target controlCenter
function open(): void
target toaster
function info(title: string, message: string, icon: string): void
function success(title: string, message: string, icon: string): void
function warn(title: string, message: string, icon: string): void
function error(title: string, message: string, icon: string): void
target lock
function isLocked(): bool
function lock(): void
function unlock(): void
target mpris
function playPause(): void
function pause(): void
function getActive(prop: string): string
function play(): void
function next(): void
function list(): string
function stop(): void
function previous(): void
target notifs
function clear(): void
target brightness
function setFor(query: string, value: string): string
function get(): real
function set(value: string): string
function getFor(query: string): reallayer-rule {
match namespace="quickshell:Backdrop"
place-within-backdrop true
opacity 1.0
}Example Niri config.kdl
// Startup commands
spawn-sh-at-startup "wl-paste --type text --watch cliphist store &"
spawn-sh-at-startup "wl-paste --type image --watch cliphist store &"
spawn-sh-at-startup "qs -c niri-caelestia-shell"
environment {
XDG_CURRENT_DESKTOP "niri"
XDG_MENU_PREFIX "plasma-" // Required for Dolphin file associations
QT_QPA_PLATFORM "wayland"
ELECTRON_OZONE_PLATFORM_HINT "auto"
QT_QPA_PLATFORMTHEME "kde"
QT_STYLE_OVERRIDE "Darkly"
}
binds {
// System
Mod+Tab repeat=false { toggle-overview; }
Mod+Shift+E { quit; }
Mod+Escape allow-inhibiting=false { toggle-keyboard-shortcuts-inhibit; }
// Launcher
Mod+Space repeat=false { spawn-sh "qs -c niri-caelestia-shell ipc call drawers toggle launcher"; }
// Clipboard
Mod+V repeat=false { spawn-sh "qs -c niri-caelestia-shell ipc call clipboard open"; }
// Lock screen
Mod+L { spawn-sh "qs -c niri-caelestia-shell ipc call lock lock"; }
// Region/Screenshot tools
Mod+Shift+S { spawn-sh "qs -c niri-caelestia-shell ipc call picker open"; }
// OCR (extract text from screen region)
Mod+Shift+X { spawn-sh "qs -c niri-caelestia-shell ipc call picker regionOcr"; }
// Google Lens (visual search from screen region)
Mod+Shift+A { spawn-sh "qs -c niri-caelestia-shell ipc call picker regionSearch"; }
// Applications (change "kitty" to your preferred terminal)
Mod+T { spawn "kitty"; }
Mod+Return { spawn "kitty"; }
Super+E { spawn "dolphin"; }
// Window management
Mod+Q repeat=false { close-window; }
Mod+D { maximize-column; }
Mod+F { fullscreen-window; }
Mod+Alt+Space { toggle-window-floating; }
// Screenshots (native)
Print { screenshot; }
Ctrl+Print { screenshot-screen; }
Alt+Print { screenshot-window; }
// ========================================================================
// HARDWARE KEYS - Audio, Brightness, Media
// ========================================================================
// Volume (hardware keys)
XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ 0; wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+"; }
XF86AudioLowerVolume allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ 0; wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"; }
XF86AudioMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; }
XF86AudioMicMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; }
// Brightness (hardware keys) - change eDP-1 to your monitor name by running "niri msg outputs"
XF86MonBrightnessUp { spawn-sh "qs -c niri-caelestia-shell ipc call brightness setFor eDP-1 +5%"; }
XF86MonBrightnessDown { spawn-sh "qs -c niri-caelestia-shell ipc call brightness setFor eDP-1 10%-"; }
// Session/Power menu
Ctrl+Alt+Delete { spawn-sh "qs -c niri-caelestia-shell ipc call drawers toggle session"; }
}
layer-rule {
match namespace="quickshell:Backdrop"
place-within-backdrop true
opacity 1.0
}Config lives in:
~/.config/niri_caelestia/shell.json
Example JSON
{
"appearance": {
"anim": {
"durations": {
"scale": 1
}
},
"font": {
"family": {
"clock": "Rubik",
"material": "Material Symbols Rounded",
"mono": "JetBrains Mono Nerd Font",
"sans": "Rubik"
},
"size": {
"scale": 1
}
},
"padding": {
"scale": 1
},
"rounding": {
"scale": 1
},
"spacing": {
"scale": 1
},
"transparency": {
"enabled": false,
"base": 0.85,
"layers": 0.4
}
},
"general": {
"apps": {
"terminal": ["kitty"],
"audio": ["pavucontrol"],
"playback": ["mpv"],
"explorer": ["thunar"]
},
"battery": {
"warnLevels": [
{
"level": 30,
"title": "Low battery",
"message": "You might want to plug in a charger",
"icon": "battery_android_frame_2"
},
{
"level": 20,
"title": "Did you see the previous message?",
"message": "You should probably plug in a charger <b>now</b>",
"icon": "battery_android_frame_1"
},
{
"level": 10,
"title": "Critical battery level",
"message": "PLUG THE CHARGER RIGHT NOW!!",
"icon": "battery_android_alert",
"critical": true
}
],
"criticalLevel": 3
},
"idle": {
"lockBeforeSleep": true,
"inhibitWhenAudio": true,
"timeouts": [
{
"timeout": 180,
"idleAction": "lock"
},
{
"timeout": 300,
"idleAction": "dpms off",
"returnAction": "dpms on"
},
{
"timeout": 600,
"idleAction": ["systemctl", "suspend-then-hibernate"]
}
]
}
},
"background": {
"desktopClock": {
"enabled": true
},
"enabled": true,
"visualiser": {
"blur": false,
"enabled": false,
"autoHide": true,
"rounding": 1,
"spacing": 1
}
},
"bar": {
"clock": {
"showIcon": true
},
"dragThreshold": 20,
"entries": [
{
"id": "logo",
"enabled": true
},
{
"id": "workspaces",
"enabled": true
},
{
"id": "spacer",
"enabled": true
},
{
"id": "activeWindow",
"enabled": true
},
{
"id": "spacer",
"enabled": true
},
{
"id": "tray",
"enabled": true
},
{
"id": "clock",
"enabled": true
},
{
"id": "statusIcons",
"enabled": true
},
{
"id": "power",
"enabled": true
}
],
"persistent": true,
"popouts": {
"activeWindow": true,
"statusIcons": true,
"tray": true
},
"scrollActions": {
"brightness": true,
"workspaces": true,
"volume": true
},
"showOnHover": true,
"status": {
"showAudio": false,
"showBattery": true,
"showBluetooth": true,
"showKbLayout": false,
"showMicrophone": false,
"showNetwork": true,
"showLockStatus": true
},
"tray": {
"background": false,
"compact": false,
"iconSubs": [],
"recolour": false
},
"workspaces": {
"label": " ",
"activeIndicator": true,
"activeLabel": "๓ฐฎฏ",
"activeTrail": false,
"groupIconsByApp": true,
"groupingRespectsLayout": false,
"windowRighClickContext": true,
"label": "โ",
"occupiedBg": true,
"occupiedLabel": "๓ฐฎฏ",
"showWindows": false,
"shown": 4,
"windowIconImage": false,
"focusedWindowBlob": false,
"windowIconGap": 0,
"windowIconSize": 30
},
"excludedScreens": [""],
"activeWindow": {
"inverted": false
}
},
"border": {
"rounding": 10,
"thickness": 10
},
"dashboard": {
"enabled": true,
"dragThreshold": 50,
"mediaUpdateInterval": 500,
"showOnHover": true
},
"launcher": {
"actionPrefix": ">",
"dragThreshold": 50,
// ...existing code...
"enableDangerousActions": false,
"maxShown": 8,
"maxWallpapers": 9,
"specialPrefix": "@",
"useFuzzy": {
"apps": false,
"actions": false,
"schemes": false,
"variants": false,
"wallpapers": false
},
"showOnHover": false
},
"lock": {
"recolourLogo": false,
"enableFprint": true,
"showExtras": true,
"maxFprintTries": 3,
"sizes": {
"heightMult": 0.7,
"ratio": 1.7778,
"centerWidth": 600
}
},
"notifs": {
"actionOnClick": false,
"clearThreshold": 0.3,
"defaultExpireTimeout": 5000,
"expandThreshold": 20,
"openExpanded": false,
"expire": true
},
"osd": {
"enabled": true,
"enableBrightness": true,
"enableMicrophone": false,
"hideDelay": 2000
},
"paths": {
"mediaGif": "root:/assets/bongocat.gif",
"sessionGif": "root:/assets/kurukuru.gif",
"wallpaperDir": "~/Pictures/Wallpapers",
"wallpaper": "~/Pictures/Wallpapers/default.jpg"
},
"services": {
"audioIncrement": 0.1,
"maxVolume": 1.0,
"defaultPlayer": "Spotify",
"gpuType": "",
"playerAliases": [{ "from": "com.github.th_ch.youtube_music", "to": "YT Music" }],
"weatherLocation": "New York",
"useFahrenheit": false,
"useTwelveHourClock": true,
"smartScheme": true,
"visualiserBars": 45
},
"session": {
"dragThreshold": 30,
"enabled": true,
"vimKeybinds": false,
"commands": {
"logout": ["loginctl", "terminate-user", ""],
"shutdown": ["systemctl", "poweroff"],
"hibernate": ["systemctl", "hibernate"],
"reboot": ["systemctl", "reboot"]
}
},
"sidebar": {
"dragThreshold": 80,
"enabled": true
},
"utilities": {
"enabled": true,
"maxToasts": 4,
"toasts": {
"audioInputChanged": true,
"audioOutputChanged": true,
"capsLockChanged": true,
"chargingChanged": true,
"configLoaded": true,
"dndChanged": true,
"gameModeChanged": true,
"kbLayoutChanged": true,
"numLockChanged": true,
"vpnChanged": true,
"nowPlaying": false
},
"vpn": {
"enabled": false,
"provider": [
{
"name": "wireguard",
"interface": "your-connection-name",
"displayName": "Wireguard (Your VPN)"
}
]
}
}
}
Example Nix Home Manager
I don't have nix, plz help :D
{
programs.niri-caelestia-shell = {
enable = true;
with-cli = true;
settings.theme.accent = "#ffb86c";
};
}The profile picture for the dashboard is read from the file ~/.face, so to set
it you can copy your image to there or set it via the dashboard. It's not a directory.
The wallpapers for the wallpaper switcher are read from ~/Pictures/Wallpapers
by default. To change it, change the wallpapers path in ~/.config/niri_caelestia/shell.json.
To set the wallpaper, you can use the app launcher command > wallpaper.
- Task manager has no Intel GPU support (AMD/NVIDIA only)
- Focus grabbing for Quickshell windows behaves awkwardly due to Niri limitations
- Quickshell may occasionally crash due to upstream issues (auto-restarts)
- Quickshell โ Core shell framework
- Caelestia โ Original project
- Niri-Caelestia-Shell โ Niri adaptation this fork is based on
- end-4/dots-hyprland โ Many features and ideas inspired from
- Niri โ Window manager backend
- All upstream contributors :)





