crabshell
a full rust replacement for quickshell: everything quickshell does, crabshell will do. your whole desktop shell is a rust crate, with bars, popups, notifications, launchers, lock screens, osds and the rest. the first milestone, v0.1, is a bar for sway and other wlroots compositors, a checkpoint that proves the approach works before the rest of quickshell's features follow

the counter example, drawn at scale 2
status: v0.1. bars draw, take clicks, follow monitors as they come and go, and show the clock, sway's workspaces, the volume and the tray with its menus. crabshell run rebuilds your bar when you save it and swaps the running one in about a second
vibe coded: ai coding agents write the code, and other agents review each step against a design doc
get started
you need
~ rust 1.99 or newer
~ sway, or another wlroots compositor with layer-shell, like labwc. only sway shows workspaces for now
~ linux 5.3 or newer
~ pkg-config, fontconfig and libpulse with their development files, like pkg-config libfontconfig1-dev libpulse-dev on debian or ubuntu
~ pulseaudio or pipewire-pulse running, for the volume
~ a d-bus session bus for the tray, and a notification daemon like mako or dunst for build errors
install the crabshell command, make a config, and run it
init writes a config to ~/.config/crabshell, a normal cargo project that depends on the crabshell crate. it never overwrites one that's already there. to build against a clone of this repository instead, run crabshell init --path <clone>. the first crabshell run compiles the whole toolkit, which takes a few minutes. then a 30 px bar shows up at the top of every monitor: sway's workspaces at the left, the tray, the volume and the clock at the right. stop any other bar first, or both will reserve space
to start it with sway instead, add this to your sway config. sway's exec may not see ~/.cargo/bin, so give the full path, and make sure cargo is on the PATH your session starts with
exec ~/.cargo/bin/crabshell run
edit it
with crabshell run running, from a terminal or from sway, change ~/.config/crabshell/src/main.rs. when you save, it rebuilds, the running bar saves its state and exits, and the new one starts. a one-line edit takes about a second, and the bar is gone for about 20 ms. run only one crabshell run at a time, or you get two bars
if your edit doesn't build, the old bar stays up, the full error prints in the terminal and a notification shows its first line. if the new bar crashes, crabshell run starts it again, waiting longer each time, and after three quick crashes it goes back to the last build that ran for a minute, if there is one
crabshell check checks the config without running it, for editors and scripts
a config
use *;
every widget property takes a value or a closure. a closure runs again when a signal it reads changes, and only what changed is redrawn. per_output builds windows for every monitor, now and later, and drops them when the monitor goes. cx.persist keeps a value across reloads. the full example, with styles and hover, is examples/counter.rs
to try the examples without a config, from a clone of this repository
docs
~ docs/site, getting started, writing a config, how it fits together, the roadmap and every quickshell feature with what crabshell has today. open docs/site/index.html in a browser
~ the design doc, every decision and every rule settled while building each crate
numbers
measured on headless sway, from the design doc
~ the v0.1 bar, one 1920×1080 output: 18.7 MiB of memory, first frame in 10.8 ms
~ the counter example: 15.8 MiB, zero wakeups while idle
~ a reload, one 1280×720 output: 0.7 s to rebuild after a one-line edit, then 13 to 19 ms with no bar
for comparison, quickshell drawing the phase 0 test bar uses 125 MiB and needs 219 ms to its first frame
where it's going
v0.1 is the template bar plus crabshell run, on crates.io. after it come floating windows and keyboard input, animations and effects, a notifications server, media players, battery, bluetooth and networking, launchers and ipc, lock screens and greeters, then hyprland, niri and more compositors, until every quickshell feature is covered. the plan is in the design doc, and docs/site/roadmap.html shows where each phase stands
what's in it
~ crabshell, run(), per_output, cx.persist, the prelude and the examples
~ crabshell-reactive, signals, memos, effects and owners
~ crabshell-ui, widgets, styles, layout, text and hit testing
~ crabshell-render, drawing on the cpu with tiny-skia, damage tracking, glyphs and icons
~ crabshell-wayland, the event loop, layer-shell windows and popups, buffers, scaling, the pointer and monitors
~ crabshell-services, the clock, sway's workspaces, audio and the tray so far
~ crabshell-cli, the crabshell command: init, check, and run, which rebuilds and supervises your bar
~ spike and baseline, the phase 0 prototype and the quickshell bar it was measured against
tests
they need dbus-daemon and dbus-monitor for the tray and notification tests, and the golden images expect noto sans as your sans-serif, plus dejavu sans. ci runs fmt, clippy and these tests on every push. the headless sway tests only run on your machine
the headless sway tests are skipped by default. run them from any terminal, without your session's SWAYSOCK so nothing can reach your sway. they refuse to start with it set
they need sway, swaymsg, grim and labwc, plus pipewire and pactl for the audio ones. each test runs its own private sway from a copy of sway. the copy drops swayfx's cap_sys_nice, so it never goes realtime and a realtime cpu limit of 0 can't kill it. the audio ones also run their own pipewire-pulse, so your volume never moves. the last one builds a config from the template and checks reloads, crashes and the fallback to the last good build. CRABSHELL_BLESS=1 rewrites the golden images
formatting
2 spaces everywhere. cargo fmt --all reads it from rustfmt.toml, and the python, markdown and yaml get
license: mit or apache-2.0, your choice