diff --git a/dotfiles/quickshell/CLAUDE.md b/dotfiles/quickshell/CLAUDE.md index 63995f2..c840656 100644 --- a/dotfiles/quickshell/CLAUDE.md +++ b/dotfiles/quickshell/CLAUDE.md @@ -14,7 +14,7 @@ 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. +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 diff --git a/flake.nix b/flake.nix index 457279b..7501c10 100644 --- a/flake.nix +++ b/flake.nix @@ -583,6 +583,7 @@ # instance is the identical build to the packaged one. qs = "${nixpkgs.legacyPackages.${system}.quickshell}/bin/qs"; git = "${nixpkgs.legacyPackages.${system}.git}/bin/git"; + grep = "${nixpkgs.legacyPackages.${system}.gnugrep}/bin/grep"; # Resolved at RUN time, not build time: the entire point is to run the # working tree, and `self` here is only a store snapshot of it. @@ -631,6 +632,33 @@ echo "qs-dev: live on $cfg — edits there now hot-reload" ''; + # qs log -f prints everything the instance logs; WARN and ERROR are the + # two that mean something is wrong with the QML in front of you. A + # binding loop or a failed binding is a WARN and easy to miss when it + # scrolls past inside a reload's worth of chatter. + qs-log = pkgs.writeShellScriptBin "qs-log" '' + set -uo pipefail + ${preamble} + + filter='WARN|ERROR' + case "''${1:-}" in + -a|--all) filter='.' ;; + esac + + # -t 1: `qs log -f` replays the whole backlog first, which would dump + # every historical warning into the terminal on shell entry. + # + # `qs log -f` ends when the instance it attached to exits, and the dev + # shell outlives individual instances — a QML error kills one, `qs-dev` + # starts another. Re-attach instead of going quiet for the session. + while :; do + if running "$cfg"; then + ${qs} log -p "$cfg" -t 1 -f 2>/dev/null | ${grep} --line-buffered -E "$filter" >&2 + fi + sleep 1 + done + ''; + qs-prod = pkgs.writeShellScriptBin "qs-prod" '' set -uo pipefail ${preamble} @@ -641,7 +669,7 @@ ''; in pkgs.mkShell { - packages = [ pkgs.quickshell qs-dev qs-prod ]; + packages = [ pkgs.quickshell qs-dev qs-prod qs-log ]; # Swap on entry, swap back on exit. Three guards: # - interactive only ($- has i). `nix develop --command X` EXECs X, @@ -655,9 +683,15 @@ shellHook = '' if [[ $- == *i* ]] && [ -n "''${WAYLAND_DISPLAY:-}" ] && [ -z "''${HOMELAB_QS_DEV:-}" ]; then export HOMELAB_QS_DEV=1 - qs-dev && trap qs-prod EXIT + if qs-dev; then + # Stream the dev instance's warnings and errors into this + # terminal, and take the follower down with the shell. + qs-log & HOMELAB_QS_LOG=$! + trap 'kill "$HOMELAB_QS_LOG" 2>/dev/null; qs-prod' EXIT + fi fi echo "homelab devshell — qs-dev (working tree) / qs-prod (packaged); exit restores" + echo "homelab devshell — quickshell WARN/ERROR stream here; qs-log -a for everything" ''; }; };