181 lines
8.5 KiB
Markdown
181 lines
8.5 KiB
Markdown
# nova-shell
|
||
|
||
A minimal [Quickshell](https://quickshell.outfoxxed.me) bar for [niri](https://github.com/YarikTH/ycmd), lovingly hallucinated by a
|
||
statistical text blender. Every line of code in this repository was
|
||
produced by a glorified autocomplete engine and has not been meaningfully
|
||
reviewed by a human with a functioning brain.
|
||
|
||
**Use at your own risk.** The slop machine was very confident, which is
|
||
exactly when you should be most suspicious.
|
||
|
||
## "Features"
|
||
|
||
- Bar with workspaces, window title, clock, tray, and a regrettable number of widgets grouped into color-coded sections with glowing borders, because subtlety is dead
|
||
- Niri IPC integration — workspace indicator, focused window title with app icon, power menu with `niri msg action quit`. All event-driven, no polling
|
||
- Interactive hover panels — volume (with per-app mixer and output device switcher), brightness (with slider), media (with album art, transport controls, progress bar). Hover to peek, click to expand, leave to dismiss. The OSD and tooltip in one, because having three separate UI patterns for the same information was too reasonable
|
||
- Context menus for tray icons with submenu support, network chooser (known available WiFi/ethernet), bluetooth device manager (connect/disconnect, battery levels)
|
||
- Privacy indicators — screenshare and microphone icons pulse red/green when PipeWire detects active video/audio capture streams. Finally, you'll know when your webcam is on, which is more than can be said for most laptop manufacturers
|
||
- Per-module accent colors that change based on state, with animated transitions. Battery blinks when critical and sends desktop notifications, because the robot cares about your hardware more than you do
|
||
- Audio visualizer on album art via cava — because the robot watched too many r/unixporn posts and couldn't help itself
|
||
- Screen corner rounding — tiny overlay windows with quarter-circle masks, click-transparent, configurable via `screenRadius`. The gradient top border curves to match, because the robot has opinions about pixel alignment
|
||
- Background overlay — clock and date rendered on the background layer, visible behind windows and in niri overview gaps. Always there, never in the way
|
||
- Weather via wttrbar with configurable arguments and rich HTML tooltips
|
||
- Power menu with lock, suspend, logout, reboot, shutdown
|
||
- Event-driven updates for network, bluetooth, and power profiles via dbus-monitor/nmcli monitor — no more 5-second polling lag
|
||
- Animated everything: flyout tooltips slide in/out, modules fade on visibility change, icons crossfade on state change, notification count pops. The bar is basically a screensaver at this point
|
||
- Home Manager module with stylix integration, per-module config objects (enable/disable + module-specific settings like polling intervals, thresholds, brightness step), and a theme system that hot-reloads
|
||
- treefmt + nixfmt for formatting, because even AI slop deserves consistent indentation
|
||
|
||
## Installation
|
||
|
||
Add the flake input and import the Home Manager module. The robot did not test
|
||
any of this on real hardware, but it was extremely confident while writing it,
|
||
which is the next best thing.
|
||
|
||
```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
|
||
imports = [ inputs.nova-shell.homeModules.default ];
|
||
```
|
||
|
||
## 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 use
|
||
[stylix](https://github.com/danth/stylix), colors and fonts are populated
|
||
automatically — one fewer thing for the AI to have gotten wrong. If you do not
|
||
use stylix, you get Catppuccin Mocha, because the robot has taste and it is
|
||
purple.
|
||
|
||
### Disabling modules
|
||
|
||
All modules are enabled by default, because the robot 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
|
||
|
||
# modules with extra config
|
||
backlight.step = 2; # brightness adjustment %
|
||
weather.args = [ "--nerd" "--location" "Berlin" ]; # wttrbar arguments
|
||
temperature.warm = 55; # °C threshold for warm color
|
||
temperature.hot = 75; # °C threshold for hot color
|
||
battery.warning = 30; # % for warning notification
|
||
battery.critical = 10; # % for critical blink + notification
|
||
cpu.interval = 2000; # polling interval in ms
|
||
};
|
||
```
|
||
|
||
Each module is an object with `enable` (default `true`) and optional extra
|
||
settings. Full list: `workspaces`, `tray`, `windowTitle`, `clock`,
|
||
`notifications`, `mpris`, `volume`, `bluetooth`, `backlight`, `network`,
|
||
`powerProfile`, `idleInhibitor`, `weather`, `temperature`, `cpu`, `memory`,
|
||
`disk`, `battery`, `power`.
|
||
|
||
### Theme
|
||
|
||
Theme keys are merged on top of whatever stylix provides. You only need to
|
||
specify what you want to override. Values are written to
|
||
`~/.config/nova-shell/theme.json`, which the bar watches for changes at
|
||
runtime, so you can iterate on colors without restarting anything — a level
|
||
of polish that frankly raises uncomfortable questions about the rest of it.
|
||
|
||
```nix
|
||
programs.nova-shell.theme = {
|
||
barHeight = 28;
|
||
barOpacity = 0.85;
|
||
barPadding = 10;
|
||
barSpacing = 8;
|
||
radius = 6;
|
||
fontSize = 13;
|
||
fontFamily = "JetBrains Mono";
|
||
|
||
# override individual palette entries if stylix's choices personally offend you
|
||
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) |
|
||
| `barSpacing` | `12` | Gap between modules (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 this. If you
|
||
improve it, the license requires you to share those improvements — a higher standard of
|
||
accountability than the author has held themselves to.
|