add full proj
This commit is contained in:
80
CLAUDE.md
Normal file
80
CLAUDE.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
A Wayland status bar for Sway/i3, written entirely in **QML** and driven by
|
||||
[Quickshell](https://quickshell.outfoxxed.me/), packaged with a Nix flake.
|
||||
|
||||
## Commands
|
||||
|
||||
```sh
|
||||
# run without building (hot-reloads on file save)
|
||||
nix develop # shell with quickshell + qmlls/qmlformat on PATH
|
||||
quickshell --path . # or: qs -p .
|
||||
|
||||
nix run . # run straight from the flake
|
||||
nix build . && ./result/bin/quickshell-bar # build the wrapper, then run
|
||||
```
|
||||
|
||||
There is **no test suite, no linter, and no build step** for the QML itself —
|
||||
it's interpreted and hot-reloaded. The only "build" is the Nix wrapper that
|
||||
pins fonts and runtime tools. `qmlformat`/`qmlls` (from `qt6.qtdeclarative`,
|
||||
available in the dev shell) are the only static tooling. Verify changes by
|
||||
running the bar and looking at it.
|
||||
|
||||
## Architecture
|
||||
|
||||
**Entry point.** `shell.qml` → `ShellRoot` with `Variants { model: Quickshell.screens }`
|
||||
spawns one `widgets/Bar.qml` (`PanelWindow`) per monitor. `Bar.qml` is a fixed
|
||||
three-zone layout: workspaces (left), clock (center), a `RowLayout` of metric
|
||||
modules (right). Changing module order/presence is purely editing that RowLayout.
|
||||
|
||||
**Three import roots, registered via `qmldir`:**
|
||||
- `config/` — `Theme` and `Icons`, both **singletons** (`pragma Singleton` +
|
||||
`singleton` line in `config/qmldir`). Global palette/geometry/fonts and Nerd
|
||||
Font glyphs. Import with `import "../config"`, reference as `Theme.x` / `Icons.x`.
|
||||
- `services/` — `SysStats`, a **singleton** that is the single source of truth
|
||||
for all `/proc` + `/sys` metrics. Import with `import "../services"`.
|
||||
- `widgets/` — the visual modules. `Pill.qml` is the rounded container every
|
||||
module reuses (`default property alias content` lets children sit inside a
|
||||
centered RowLayout); `MetricPill.qml` adds the icon + value convention.
|
||||
|
||||
**The metrics pipeline (`services/SysStats.qml`) is the core design.** One `Timer`
|
||||
(1 Hz, `interval` property) calls `_tickOnce()`, which `reload()`s a set of
|
||||
`FileView`s and parses them into reactive properties (`cpu`, `cpuFreq`, `mem`,
|
||||
`temp`, rates, battery, …). Widgets just bind to those properties. Key conventions:
|
||||
- `FileView { blockLoading: true }` makes `reload()` synchronous so `text()` is
|
||||
fresh on the same tick. Use this for tiny virtual files in `/proc`/`/sys`.
|
||||
- Add a metric by: declaring a property, adding a `FileView` (or reusing one by
|
||||
reassigning its `path`, as `_parseNet` does for the active interface), writing
|
||||
a `_parseX()`, and calling `reload()` + `_parseX()` inside `_tickOnce()`.
|
||||
- Deltas (CPU%, net rates) keep a `_prev*` field and diff against the last tick.
|
||||
- **Two metrics escape the pure-virtual-file rule:** disk usage runs `df` via a
|
||||
`Process` only every 30 ticks (`_tick % 30`), and a one-shot `Process` runs
|
||||
`services/discover.sh` at startup. The bar avoids per-tick subprocess spawns
|
||||
by design — keep new metrics reading virtual files, not shelling out.
|
||||
|
||||
**`discover.sh` handshake.** At startup it prints `TEMP <path>` and `BAT <path>`
|
||||
(hwmon temp sensor + main battery, skipping `scope=Device` peripherals) on stdout;
|
||||
the QML side parses those lines into `tempPath`/`batPath`, which then feed
|
||||
`FileView`s. sysfs paths are stable for a boot, so this runs once, not per tick.
|
||||
|
||||
## Conventions & gotchas
|
||||
|
||||
- **Icons are referenced by Unicode codepoint** (`config/Icons.qml`,
|
||||
`String.fromCharCode(0x...)`) so source stays ASCII. The glyph **must exist in
|
||||
the bundled Nerd Font** — `flake.nix` bundles `nerd-fonts.jetbrains-mono` +
|
||||
`nerd-fonts.symbols-only` (Font Awesome 4 range, plus Material Design). Font
|
||||
Awesome 5+ codepoints are NOT present and render as tofu squares; verify a
|
||||
codepoint is covered before using it. Codepoints above `0xFFFF` (e.g. Material
|
||||
Design `0xf0xxx`) need `String.fromCodePoint`, not `String.fromCharCode`.
|
||||
- **Fonts are pinned via `FONTCONFIG_FILE`** in the flake wrapper, so glyphs
|
||||
render regardless of the host's installed fonts. Adding a font means editing
|
||||
`fontsConf` in `flake.nix`.
|
||||
- **`Bar.qml` remaps its layer surface on geometry change** (`geomKey` →
|
||||
toggle `visible`). This is a deliberate workaround for stale-buffer garbage
|
||||
after output rotation/transform under Sway — don't remove it.
|
||||
- **Quickshell upstream is tracked directly** in `flake.nix` (git, not nixpkgs)
|
||||
to pick up layer-surface fixes ahead of release.
|
||||
- Native Quickshell services back some modules: `Quickshell.I3` (workspaces),
|
||||
`Quickshell.Services.SystemTray` (tray), PipeWire (volume).
|
||||
Reference in New Issue
Block a user