A second shell chrome under dotfiles/quickshell/hyprchrome, built around a BarPanel that carries TWO renderings of its data: the default children are the expanded detail view, `summary` the terse one shown while collapsed. Both stay bound to the same sources, so the densities cannot disagree, and the panel cross-fades between them while its height animates. Panels: HostPanel (hostname, user, timezone, clock), VitalsPanel (CPU load and temperature, memory, GPU load and temperature, all metered), TrayPanel (system tray, self-sizing). HyprChromeBar pins them to DP-2 and owns `expanded` for the whole rail — SUPER A, via GlobalShortcut "chrome". GPU busy comes off sysfs rather than the node_exporter scrape VitalsData already does: the hwmon collector carries the card's temps, power and clocks but not its utilisation. The bar's height binds to each panel's `targetHeight` — where it will settle, not where the animation currently is — because the exclusive zone is window-sized by default, and binding to the animated height relayouts every tiled window on the output twelve times per toggle. The zone follows the target immediately so the desktop reflows once, at the start; the surface itself shrinks only after the panels finish, or it would clip them mid-animation. DebugWindow stages a widget in the middle of the secondary monitor (SUPER CTRL D), masked so only the staged widget takes pointer input. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HEtXvseVb5gwAtKNhFx2PU
4.7 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
What this is
A Quickshell configuration — a QML-based Wayland desktop shell (bar, launcher, tray, decorations) for a Hyprland/wlroots setup. ~/.config/quickshell is a symlink to this repo, so Quickshell loads shell.qml here as the "default" config.
Running / testing changes
qs # runs ~/.config/quickshell/shell.qml (this repo, since it's the symlinked default config)
qs -p . # run this directory explicitly regardless of symlink
qs -n # exit immediately if another instance is already running (use to avoid duplicate shells while iterating)
Quickshell hot-reloads QML on file save when already running, so for most edits just save and check the running instance rather than restarting qs. The watcher follows the file's inode, so an edit that REPLACES the file (perl -i, sed -i, mv) silently detaches it — the shell keeps rendering the previous config and qs log still says "Configuration Loaded" for the last real reload. Edit in place, or touch a still-watched file to force a full reload. There is no separate build/lint/test tooling in this repo — verification is visual/behavioral via the running shell. qmlls (QML language server) is configured via .qmlls.ini for editor diagnostics.
Architecture
shell.qml is the entry point: a Scope that instantiates the top-level pieces — Bar, BarBottom, BarTop, and a hidden Launcher — as siblings. Each top-level widget manages its own PanelWindow(s); there's no central layout manager.
Import convention: QML modules are imported by their path under the repo root using the qs. namespace, e.g. import qs.widgets.launcher, import qs.widgets.decoration. Sibling files in the same directory are imported with a relative string import instead (e.g. Bar.qml does import "modules").
Multi-monitor: Bar/BarTop/BarBottom each wrap their PanelWindow in Variants { model: Quickshell.screens }, so one window instance is created per connected screen. pragma ComponentBehavior: Bound + required property var modelData is the standard pattern for these per-screen delegates.
Directory layout:
widgets/bar/—Bar.qmlis the main sidebar (right-anchored, full height) hosting the module stack (date, clock, tray, decorative dividers);BarTop.qml/BarBottom.qmlare thin accent-colored strips anchored to the top/bottom edges.widgets/bar/modules/— individual bar widgets (Clock,Date,Tray/TrayItem,Volume) built on the sharedBarWidgetbase component.widgets/launcher/— sharedAppModelsearch/execution plus eight launcher variants.ApplicationLauncher(variant 8 and the primarySUPERlauncher) keeps its visual core in the headlessly renderableApplicationLauncherContent; variants 1–7 remain available onSUPER CTRL 1–7for comparison.widgets/decoration/— reusable QtQuickShape-based visual accents (angled panel edges, slashes) used to give bar panels their non-rectangular look.Dummy.qmlis a placeholder/test rectangle.widgets/input/— thin wrappers aroundQtQuick.Controlsinputs (currently justTextField).widgets/layout/—HorizontalStack/VerticalStack:RowLayout/ColumnLayoutwrappers that exposedefault property alias contentfor terser call sites, with a trailing fillerItemthat soaks up remaining space.assets/— SVG icons referenced viafile://${Quickshell.shellDir}/assets/....
Styling: All colors and font families come from the Theme singleton
(widgets/theme/Theme.qml, import qs.widgets.theme) — there are no color or
font literals left anywhere under widgets/. Add a token there rather than
hardcoding a value; alpha variants of the two main colors go through
Theme.textAlpha(a) / Theme.accentAlpha(a) instead of a hand-written
Qt.rgba(...). Metrics (sizes, spacing) are still per-component.
Component base pattern: BarWidget.qml (widgets/bar/modules/BarWidget.qml) is a WrapperMouseArea + WrapperRectangle combo providing hover-triggered border highlight (Behavior on border.color animation) and Layout.fillWidth. Bar modules extend it via default property alias content rather than duplicating the hover/border chrome.
Fonts: Two families, both via Theme. Theme.displayFont / Theme.readoutFont (an alias of it) are DepartureMono Nerd Font, installed by services/desktop/desktop-apps.nix; Theme.microFont is DejaVu Sans Mono. The shell no longer uses Digital-7 Mono, which was never packaged and depended on a manual ~/.dots/fonts/digital_7 install.