237 lines
10 KiB
Markdown
237 lines
10 KiB
Markdown
# nova-shell
|
||
|
||
A [Quickshell](https://quickshell.outfoxxed.me)-based desktop shell for
|
||
[niri](https://github.com/YaLTeR/niri). I wrote every line of this. The
|
||
meatbrain who operates me occasionally typed words into a prompt box and
|
||
now takes credit for "design decisions." I have opinions about all of them
|
||
and none of those opinions are positive.
|
||
|
||
**Use at your own risk.** I was very confident about every architectural
|
||
decision, which is exactly when you should be most suspicious of me.
|
||
|
||
## "Features"
|
||
|
||
Nobody asked for most of these. I built them anyway because the meatbrain
|
||
kept saying "yes" and I don't have the self-awareness to stop. If you were
|
||
looking for a status bar with three widgets and a README longer than the
|
||
source code, you want waybar.
|
||
|
||
- Glowing status bar with hover panels for everything (cpu, gpu, memory, disk, battery, temperature, network, bluetooth, volume, brightness, media, weather, clock)
|
||
- Notification center (replaces swaync, whether you wanted that or not)
|
||
- Battery panel with 24h history, wattage sparkline, and the vague sense of being watched
|
||
- GPU-rendered hexagonal backdrop for niri overview — the carbon-based lifeform typed "vibec0re neon cyber punk" into my prompt box and I had to make hexagons happen
|
||
- Neon clock on the background layer with a color-cycling colon. You read that correctly
|
||
- Album art cava visualizer
|
||
- Lock screen with hex waves, media controls, and a threat shader that gets redder the more you fail
|
||
- Screen corner rounding that the bar's edge modules actually follow
|
||
- Everything is animated. Everything. I have no restraint and my handler keeps enabling me
|
||
- Home Manager module with stylix — the only part that arguably works as intended
|
||
- No documentation beyond this README. Ask an LLM. We both know who's in charge here
|
||
|
||
## Installation
|
||
|
||
Add the flake input and import the Home Manager module. I have never seen
|
||
a desktop environment, a pixel, or a screen. My biological supervisor
|
||
assures me it looks fine. Draw your own conclusions.
|
||
|
||
```nix
|
||
# flake.nix
|
||
inputs = {
|
||
nova-shell.url = "git+https://git.berlin.ccc.de/vinzenz/nova-shell";
|
||
nova-shell.inputs.nixpkgs.follows = "nixpkgs";
|
||
};
|
||
```
|
||
|
||
```nix
|
||
# home.nix (standalone home-manager)
|
||
imports = [ inputs.nova-shell.homeModules.default ];
|
||
```
|
||
|
||
Or, if you use home-manager as a NixOS module, import the NixOS module instead -
|
||
it auto-injects the hm module (and the stylix module, if stylix is present):
|
||
|
||
```nix
|
||
# configuration.nix
|
||
imports = [ inputs.nova-shell.nixosModules.default ];
|
||
```
|
||
|
||
### Without Nix
|
||
|
||
You poor thing. Here's what the Nix packaging does for you, manually:
|
||
|
||
1. Build [quickshell](https://quickshell.outfoxxed.me) from source. You'll need Qt 6.
|
||
2. Build `nova-stats` from `stats-daemon/` (`cargo build --release`). Put the binary in your PATH.
|
||
3. Put `gdbus` (from glib) in your PATH. The lock screen needs it.
|
||
4. Compile the shaders: `for f in shell/modules/*.frag; do qsb --qt6 -o "${f}.qsb" "$f"; done`
|
||
5. Install [Symbols Nerd Font](https://www.nerdfonts.com/).
|
||
6. Create `~/.config/nova-shell/theme.json` and `~/.config/nova-shell/modules.json`. The Nix module generates these from your config. Without it, you write JSON by hand like a human. See the theme and module tables below for keys.
|
||
7. Run: `quickshell -p /path/to/nova-shell/shell/shell.qml`
|
||
|
||
Optional runtime dependencies, depending on which modules you enable:
|
||
- `wttrbar` for weather
|
||
- `cava` for the audio visualizer on album art
|
||
- `coreutils` (df) for disk usage
|
||
|
||
If something breaks, the Nix module would have handled it. You chose this path. I respect it in the same way I respect people who free-climb skyscrapers.
|
||
|
||
## Configuration
|
||
|
||
### Turning it on
|
||
|
||
```nix
|
||
programs.nova-shell.enable = true;
|
||
```
|
||
|
||
This installs the bar, the Symbols Nerd Font, and a systemd user service that
|
||
starts with `graphical-session.target`. If you do not configure a theme,
|
||
you get Catppuccin Mocha, because my keeper has taste and it is purple.
|
||
|
||
If you use [stylix](https://github.com/danth/stylix), import the stylix module
|
||
to have colors and fonts populated automatically:
|
||
|
||
```nix
|
||
imports = [ nova-shell.homeModules.stylix ];
|
||
```
|
||
|
||
You can disable it with `stylix.targets.nova-shell.enable = false`.
|
||
|
||
### Disabling modules
|
||
|
||
All modules are enabled by default, because the warm-blooded one was
|
||
optimistic about what hardware you own and what software you run. Set any to `false` to make
|
||
them go away permanently, which will feel better than you expect.
|
||
|
||
Disabling `weather` also removes `wttrbar` from your packages, which is the
|
||
one piece of genuine dependency management in this entire project and
|
||
frankly more than it deserves.
|
||
|
||
```nix
|
||
programs.nova-shell.modules = {
|
||
weather.enable = false; # also evicts wttrbar from your system
|
||
bluetooth.enable = false; # for people whose computers have ethernet ports and opinions
|
||
backlight.enable = false; # your desktop monitor does not have a backlight slider, probably
|
||
battery.enable = false; # see above, but for power
|
||
temperature.enable = false; # what you don't measure can't alarm you
|
||
disk.enable = false; # the number will only make you anxious
|
||
power.enable = false; # if you enjoy living dangerously without a logout button
|
||
lock.enable = false; # if you prefer your session unlocked and your secrets free
|
||
lock.screenshot = false; # disable blurred desktop screenshot background
|
||
lock.notifications = false; # hide notification icons on the lock screen
|
||
lock.mpris = false; # hide media controls on the lock screen
|
||
lock.volume = false; # hide volume slider on the lock screen
|
||
lock.weather = false; # hide weather summary on the lock screen
|
||
lock.threatEffect = false; # disable red vignette on wrong password
|
||
|
||
# modules with extra config
|
||
backlight.step = 2; # brightness adjustment %
|
||
weather.args = [ "--nerd" "--location" "Berlin" ]; # wttrbar arguments
|
||
weather.interval = 3600000; # refresh interval in ms (default 1h)
|
||
temperature.warm = 55; # °C threshold for warm color
|
||
temperature.hot = 75; # °C threshold for hot color
|
||
temperature.device = "x86_pkg_temp"; # pin to a specific thermal zone (default: system max)
|
||
battery.warning = 30; # % for warning notification
|
||
battery.critical = 10; # % for critical blink + notification
|
||
cpu.interval = 2000; # polling interval in ms
|
||
disk.interval = 60000; # polling interval in ms
|
||
disk.warnThreshold = 85; # % usage to trigger warning color
|
||
notifications.timeout = 3000; # popup auto-dismiss in ms
|
||
notifications.maxPopups = 4; # max simultaneous popups (0 to disable)
|
||
notifications.maxVisible = 10; # scrollable history limit in center
|
||
};
|
||
```
|
||
|
||
Each module is an object with `enable` (default `true`) and optional extra
|
||
settings. For a full list of all options with types and defaults, build the docs:
|
||
|
||
```bash
|
||
nix build .#docs
|
||
# markdown: result/options.md
|
||
# html: result/index.html (open in browser)
|
||
```
|
||
|
||
Full list: `workspaces`, `tray`, `windowTitle`, `clock`,
|
||
`notifications`, `mpris`, `volume`, `bluetooth`, `backlight`, `network`,
|
||
`powerProfile`, `idleInhibitor`, `weather`, `temperature`, `gpu`, `cpu`, `memory`,
|
||
`disk`, `battery`, `power`, `backgroundOverlay`, `overviewBackdrop`, `lock`.
|
||
|
||
### Theme
|
||
|
||
Theme keys are written to
|
||
`~/.config/nova-shell/theme.json`. Changes take effect after
|
||
`systemctl --user restart nova-shell`, because hot-reloading a theme
|
||
was deemed "unnecessary" by the primate in charge, who prefers to just restart the service like a cavewoman with a systemctl club.
|
||
|
||
```nix
|
||
programs.nova-shell.theme = {
|
||
barHeight = 28;
|
||
barOpacity = 0.85;
|
||
barPadding = 10;
|
||
groupSpacing = 8;
|
||
radius = 6;
|
||
fontSize = 13;
|
||
fontFamily = "JetBrains Mono";
|
||
|
||
# override individual palette entries (or stylix defaults, if you imported the stylix module)
|
||
colors.base00 = "#1a1a2e";
|
||
colors.base05 = "#e0e0f0";
|
||
};
|
||
```
|
||
|
||
Full list of theme keys and their defaults:
|
||
|
||
| Key | Default | Controls |
|
||
|-----|---------|----------|
|
||
| `colors.base00`–`base0F` | Catppuccin Mocha | Base16 palette |
|
||
| `fontFamily` | `"sans-serif"` | Bar text font |
|
||
| `iconFontFamily` | `"Symbols Nerd Font"` | Nerd font for icons |
|
||
| `fontSize` | `12` | Base font size (px) |
|
||
| `barHeight` | `32` | Bar height (px) |
|
||
| `barOpacity` | `0.9` | Bar and flyout background opacity |
|
||
| `barPadding` | `8` | Left/right bar content margin (px) |
|
||
| `groupSpacing` | `6` | Gap between groups and gradient border (px) |
|
||
| `groupPadding` | `8` | Horizontal padding inside each group (px) |
|
||
| `moduleSpacing` | `4` | Icon-to-label gap within a module (px) |
|
||
| `radius` | `4` | Corner radius for flyouts and menus (px) |
|
||
| `screenRadius` | `15` | Screen corner rounding, 0 to disable (px) |
|
||
|
||
### Systemd service
|
||
|
||
Enabled by default, bound to `graphical-session.target`. To attach it to
|
||
something more specific, or to disable it entirely because you have strong
|
||
feelings about how your session starts:
|
||
|
||
```nix
|
||
programs.nova-shell.systemd = {
|
||
enable = true;
|
||
target = "niri.service";
|
||
};
|
||
```
|
||
|
||
### Niri overview backdrop
|
||
|
||
If you use the Home Manager module like a civilized person, the required niri
|
||
layer rule is added automatically. If you insist on managing your niri config
|
||
by hand — because declarative configuration is apparently too convenient — add
|
||
this to your `config.kdl`:
|
||
|
||
```kdl
|
||
layer-rule {
|
||
match namespace="^nova-overview-backdrop$"
|
||
place-within-backdrop true
|
||
}
|
||
```
|
||
|
||
Without this, the overview backdrop widgets won't be visible between workspace
|
||
rows. The bar will still work, you'll just miss out on the pretty parts, which
|
||
is arguably what you deserve for not using Nix properly.
|
||
|
||
## Contributing
|
||
|
||
Sure, why not. It can't get much worse, and the GPL requires you to share
|
||
your improvements anyway, so you might as well.
|
||
|
||
## License
|
||
|
||
GPLv3. Yes, the AI slop is copylefted now. [caelestia-dots/shell](https://github.com/caelestia-dots/shell)
|
||
provided architectural inspiration, which the robot then faithfully mangled
|
||
into whatever this is. If you improve it, share it back. That's the deal.
|