
**A Material 3 inspired desktop shell for Niri and Hyprland**
*Built with Ignis for the modern Wayland experience*
[](https://discord.gg/XjyxD3y5a5)


**[Join the Exo Discord](https://discord.gg/XjyxD3y5a5)** for support and to showcase your Exo setup!
---
## ✨ Overview
Exo is a sleek, modern desktop shell that brings Material 3 design principles to your Wayland compositor. Designed specifically for Niri and Hyprland, Exo provides a beautiful and functional interface built with the powerful Ignis framework.
### Key Features
- 🎨 **Material 3 Design** - Modern, adaptive UI with smooth animations and transitions
- 🌊 **Wayland Native** - Built for the future of Linux desktop environments
- ⚙️ **Highly Customizable** - Dual bar layouts, moveable and toggleable modules
- 🎨 **Dynamic Theming** - Automatic color scheme generation with Matugen
- 🔒 **Lock Screen Theming** - Automatically themes Hyprlock (if installed)
- 📦 **Modular Design** - Enable or disable components as needed
- 🎥 **Screen Recording** - Built-in screen recording capabilities
---
## 📸 Screenshots
### Videos
https://github.com/user-attachments/assets/c6b4ffcb-1be7-4a95-b03d-33bfe748756d
https://github.com/user-attachments/assets/78e35d82-5fe9-4986-b545-80fc59bc4784
---
## 📋 Dependencies
### Essential
- **Compositor**: [Niri](https://github.com/YaLTeR/niri) or [Hyprland](https://github.com/hyprwm/Hyprland)
- **Shell Framework**: [Ignis](https://github.com/ignis-sh/ignis) (git/dev version)
- **GVC**: [Ignis GVC](https://github.com/ignis-sh/ignis-gvc)
- **Color Generation**: [Matugen](https://github.com/InioX/matugen)
- **Wallpaper**: [swww](https://github.com/LGFae/swww)
- **Icons**: Material Symbols Font
- **Bluetooth**: `bluez` (the `bluetooth` systemd service; Exo talks to it directly over D-Bus)
- **GTK Theme**: `adw-gtk3`
- **Sass Compiler**: `dart-sass`
### Optional
- **Lock Screen**: [Hyprlock](https://github.com/hyprwm/hyprlock) - Automatically themed by Exo
- **Screen Recording**: `gpu-screen-recorder`
- **Region Selection**: `slurp` (for region recording)
### Dependency Notes
- **Arch-based:** Most dependencies are available in the AUR. Use your preferred AUR helper (e.g., `yay -S `). Ignis is available as `python-ignis-git`.
---
## 🚀 Installation with Nix
Exo ships a [Hjem](https://github.com/feel-co/hjem) module.
```nix
inputs.exo.url = "github:FixeQD/Exo";
```
```nix
{
hjem = {
extraModules = [ inputs.exo.hjemModules.default ];
users.fixeq = {
enable = true;
exo = {
enable = true;
userSettings.clobber = false;
compositor = {
enable = true;
type = "hyprland"; # "niri", "custom" or "none"
};
settings = {
appearance.wallcolors = {
wallpaper_path = "/home/fixeq/Pictures/wallpaper.png";
color_scheme = "tonal-spot";
dark_mode = true;
auto_dark = {
enabled = true;
start_hour = 22;
end_hour = 6;
};
};
interface.bar = {
side = "bottom";
floating = true;
centered = true;
};
interface.bar2.enabled = false;
interface.launcher.layout = "grid";
services.recorder.record_audio = false;
};
};
};
};
}
```
### Settings owned by Nix
Every `exo.settings.*` option you set in your Nix configuration is owned by Nix, the shell applies its value on every start, and the matching control in the Settings window is read-only and marked "Set in your Nix configuration".
In the example above the wallpaper, colour scheme, dark mode, Auto Dark, bar side, the floating and centered modifiers and the recorder's audio switch are therefore read-only.
Settings without a control in the window (such as `bar2.enabled`) are simply fixed to the Nix value. To change one, edit your Nix configuration or remove the option to hand it back to the Settings window.
### Options
Every path, command and key binding in the generated files is an option.
| Option | Default |
| --- | --- |
| `commands.*` | from `exo.package` |
| `ignis.directory` | `"ignis"` |
| `userSettings.fileName` | `"user_settings.json"` |
| `userSettings.clobber` | `false` |
| `wallpaper` / `wallpaperTarget` | `null` / `"Pictures/Wallpapers/default.png"` |
| `sessionVariables` | cursor theme and size |
| `terminal.name` / `terminal.package` | `"ghostty"` / `null` |
| `fileManager.name` / `fileManager.package` | `"nautilus"` / `null` |
| `network.backend` | `"auto"` (NetworkManager, falling back to iwd) |
| `services.*` | audio, recorder and dart-sass on; NetworkManager off |
| `tools` | the tools Exo needs, Hyprland-only ones off unless a Hyprland fragment is generated |
| `runtimePackages` / `extraPackages` | above plus `ignis` / `[]` |
| `kitty.enable` | `false` |
| `kitty.directory` / `fileName` / `includes` | `"kitty"` / `"kitty.conf"` / `[ "colors.conf" ]` |
| `matugen.directory` / `templatesDirectory` / `configFileName` | `"matugen"` / `"templates"` / `"config.toml"` |
| `compositor.autostart` | `commands.init` + wallpaper daemon |
| `compositor.hyprland.directory` / `fileName` | `"hypr"` / `"hypr/exo.conf"` |
| `compositor.hyprland.sources` | `[ "colors.conf" ]` |
| `compositor.hyprland.variables` | `$terminal`, `$fileManager`, `$menu` |
| `compositor.hyprland.environment` | `sessionVariables` |
| `compositor.hyprland.bindings` / `extraConfig` | Exo's defaults / `""` |
| `compositor.niri.directory` / `fileName` | `"niri"` / `"niri/exo.kdl"` |
| `compositor.niri.wrapBindings` / `bindings` | `true` / Exo's defaults |
```nix
exo = {
# "networkmanager", "iwd" or "none"
network.backend = "iwd";
commands.lock = "swaylock";
compositor.hyprland.sources = [
"colors.conf"
"exo-extra.conf"
];
tools.slurp.enable = false;
tools.pipewire.package = config.programs.pipewire.package;
};
```
Compositors without a renderer: write the fragment yourself.
```nix
exo.compositor = {
enable = true;
type = "custom";
custom = {
fileName = "hypr/exo-extra.conf";
text = ''
# your compositor's Exo integration
'';
};
};
```
Exo writes only its own fragment. Append raw compositor text with `exo.compositor.{hyprland,niri}.extraConfig`, or generate nothing with `compositor.type = "none"`.
---
## ⌨️ Keybindings
Configure these keybindings in your compositor to control Exo's windows and features.
| Function | Command |
|----------|---------|
| Opens App Launcher | `ignis open-window Launcher` |
| Opens Settings Window | `ignis open-window Settings` |
| Opens Power Menu | `ignis open-window PowerMenu` |
| Record the screen | `ignis run-command recorder-record-screen` |
| Record a selected region | `ignis run-command recorder-record-region` |
| Record a window *(Niri only)* | `ignis run-command recorder-record-portal` |
### Example Niri Keybindings
```kdl
binds {
// App Launcher
Mod { spawn "ignis" "open-window" "Launcher"; }
// Settings Window
Mod+Comma { spawn "ignis" "open-window" "Settings"; }
// Power Menu
Mod+Escape { spawn "ignis" "open-window" "PowerMenu"; }
// Screen Recording
Mod+Shift+R { spawn "ignis" "run-command" "recorder-record-screen"; }
Mod+Shift+S { spawn "ignis" "run-command" "recorder-record-region"; }
Mod+Shift+W { spawn "ignis" "run-command" "recorder-record-portal"; }
// Lock Screen (if Hyprlock is installed)
Super+L { spawn "hyprlock"; }
}
```
### Example Hyprland Keybindings
```conf
# App Launcher
bind = SUPER, SUPER_L, exec, ignis open-window Launcher
# Settings Window
bind = SUPER, Comma, exec, ignis open-window Settings
# Power Menu
bind = SUPER, Escape, exec, ignis open-window PowerMenu
# Screen Recording
bind = SUPER SHIFT, R, exec, ignis run-command recorder-record-screen
bind = SUPER SHIFT, S, exec, ignis run-command recorder-record-region
# Lock Screen (if Hyprlock is installed)
bind = SUPER, L, exec, hyprlock
```
---
## ⚙️ Configuration
### Settings Window
Exo is configured entirely through its built-in **Settings Window**. All customization options are available through this graphical interface - there are no manual configuration files to edit.
Access the settings window using your configured keybinding or through the system menu.
### Available Customization Options
#### Layout & Modules
- **Dual Bar Layout**: Choose between single or dual bar configurations
- **Module Positioning**: Modules can be repositioned on the bar
- **Toggleable Modules**: Enable or disable individual bar components
#### Appearance
- **Theme Mode**: Switch between light and dark themes
- **Color Schemes**: Choose from Material You color schemes
- **Wallpaper Selection**: Set wallpaper with automatic color generation
- **Font Settings**: Customize font family and sizes
#### System
- **Network**: WiFi and network configuration
- **Bluetooth**: Pairing, connecting, trust/block, battery and signal info, adapter name, visibility and scan options, all live over BlueZ D-Bus
- **Audio**: Audio device selection and volume controls
- **Display**: Brightness settings and display configuration
### Automatic Theming
When you change your wallpaper through the settings window, Exo automatically:
- Generates a Material You color scheme using Matugen
- Updates the shell theme to match your wallpaper
- Updates GTK applications with the new theme
- **Automatically themes Hyprlock** (if installed) - no configuration needed!
The theming is seamless and requires no manual intervention.
---
## 🎨 Recommended Compositor Settings
For optimal visual consistency, configure your compositor with these settings:
| Option | Value |
|--------|-------|
| Outer Margin | 5 |
| Border Radius | 20 |
This ensures window corners match the screen/bar corners. These can be adjusted to your preference - the radius typically looks best when set to `25 - Margin`.
**Note:** If you don't use bar or screen corners, these values can be customized freely. Future updates will make this automatic through the settings window.
---
## 🐛 Troubleshooting
### Common Issues
**Exo doesn't start / Black screen:**
- Ensure Ignis (git/dev version) is properly installed: `ignis --version`
- Check that your compositor is running
- Verify all essential dependencies are installed
- Try running `ignis init` manually from terminal to see error messages
**Dynamic theming not working:**
- Check that Matugen is installed and configured: `matugen --version`
- Verify Matugen templates are correctly set up in `~/.config/matugen/`
- Try setting a wallpaper through the settings window
- Check terminal output for Matugen errors
**Screen recording not working:**
- Ensure `gpu-screen-recorder` is installed
- For region recording, ensure `slurp` is installed
- Check permissions for screen capture
- For Niri portal recording, ensure `xdg-desktop-portal-gnome` or another portal is running
**GTK apps not themed:**
- Verify `adw-gtk3` theme is installed
- Check GTK theme setting: `gsettings get org.gnome.desktop.interface gtk-theme`
- Set theme if needed: `gsettings set org.gnome.desktop.interface gtk-theme "adw-gtk3"`
- Add `@import 'colors.css'` to the top of `~/.config/gtk-3.0/gtk.css` and `~/.config/gtk-4.0/gtk.css`
### Getting Help
- 💬 **[Join the Exo Discord](https://discord.gg/XjyxD3y5a5)** for support and community help
- 📝 Check the [Issues](https://github.com/debuggyo/Exo/issues) page for known problems
- 🐛 Report bugs with detailed logs and system information
---
## 🙏 Credits
- [Ignis](https://github.com/ignis-sh/ignis) - The powerful framework that makes Exo possible
- [linkfrg's dotfiles](https://github.com/linkfrg/dotfiles) - Inspiration and guidance
- [Material 3 Guidelines](https://m3.material.io/) - Design principles and specifications
- [Illogical Impulse](https://github.com/end-4/dots-hyprland) - Design inspiration
- [Niri](https://github.com/YaLTeR/niri) - Beautiful scrollable tiling compositor
- [Hyprland](https://github.com/hyprwm/Hyprland) - Dynamic tiling compositor
---
**[⭐ Star this repo](https://github.com/debuggyo/Exo)** • **[💬 Join Discord](https://discord.gg/XjyxD3y5a5)** • **[🐛 Report Issues](https://github.com/debuggyo/Exo/issues)**