Files
homelab/dotfiles/quickshell/CLAUDE.md
T
darmanandClaude Opus 5 15698d3a78 feat(devshell): stream quickshell warnings and errors in nix develop
qs-log follows the working-tree instance's log filtered to WARN|ERROR (-a for
everything), and the shellHook starts it in the background once qs-dev is up,
taking it down again in the exit trap alongside qs-prod. A binding loop or a
failed binding is a WARN, and easy to miss when it scrolls past unwatched.

It starts at the end of the log rather than replaying the backlog, and
re-attaches in a loop: `qs log -f` ends when the instance it attached to exits,
and the dev shell outlives individual instances.

Also corrects the hot-reload note added in 7268221, which was wrong on both
counts. Tested against the running shell: `touch` never reloads (mtime is not a
content change) and inode-replacing edits like `sed -i` are picked up fine. The
reliable check is whether `qs log` shows a "Reloading configuration..." line.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HEtXvseVb5gwAtKNhFx2PU
2026-08-29 03:25:26 +02:00

46 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## What this is
A [Quickshell](https://quickshell.org/) 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
```sh
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`. It watches file CONTENT: `touch` alone never reloads (mtime is not a change), while any real edit does, including inode-replacing ones (`sed -i`, `perl -i`). A save that is not picked up leaves the shell rendering the previous config with no error — `qs log` shows a `Reloading configuration...` line for every save it saw, so that is the check. 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.qml` is the main sidebar (right-anchored, full height) hosting the module stack (date, clock, tray, decorative dividers); `BarTop.qml`/`BarBottom.qml` are thin accent-colored strips anchored to the top/bottom edges.
- `widgets/bar/modules/` — individual bar widgets (`Clock`, `Date`, `Tray`/`TrayItem`, `Volume`) built on the shared `BarWidget` base component.
- `widgets/launcher/` — shared `AppModel` search/execution plus eight launcher variants. `ApplicationLauncher` (variant 8 and the primary `SUPER` launcher) keeps its visual core in the headlessly renderable `ApplicationLauncherContent`; variants 17 remain available on `SUPER CTRL 17` for comparison.
- `widgets/decoration/` — reusable QtQuick `Shape`-based visual accents (angled panel edges, slashes) used to give bar panels their non-rectangular look. `Dummy.qml` is a placeholder/test rectangle.
- `widgets/input/` — thin wrappers around `QtQuick.Controls` inputs (currently just `TextField`).
- `widgets/layout/``HorizontalStack`/`VerticalStack`: `RowLayout`/`ColumnLayout` wrappers that expose `default property alias content` for terser call sites, with a trailing filler `Item` that soaks up remaining space.
- `assets/` — SVG icons referenced via `file://${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.