--- name: noctalia-bar-layout-edit description: "Edit/verify Noctalia v5 bar layout and clock widgets (multi-timezone instances, capsule groups); GUI→repo propagation chain, settings.toml symlink audit, and clobber-recovery via dangling stashes on Frank's dotfiles workstations" --- # Noctalia v5 bar layout edit Bar widget layout on Frank's noctalia v5 workstations is GUI-override state, not config.toml. ## Where - Layout file: `~/.local/state/noctalia/settings.toml` → `[bar.]` keys `start` / `center` / `end` (arrays of widget ids; `[widget.]` subtables hold per-widget settings). - On Frank's boxes this file MUST be a **symlink into the command-center repo** (e.g. `~/.omp/dotfiles/noctalia/.local/state/noctalia/settings.toml`) — edit the repo file, not the link path (atomic-rename writes through the link path would replace the symlink). - Layer order: built-in defaults < `~/.config/noctalia/config.toml` (+`[include]`) < `settings.toml` (wins). Noctalia writes through symlinks and keeps them. - Defaults when a key is absent: `start = ["launcher","wallpaper","workspaces"]`, `center = ["clock"]`. - **Noctalia rewrites this file itself** (GUI actions + normalizes keys/format, e.g. strips `{:%...}` braces, reorders widget lists). Always re-read the exact lines immediately before editing; stale line anchors WILL drift between reads. ## GUI→repo propagation (checkout-is-deployment) - `~/.config/noctalia/config.toml` is symlinked into the repo → GUI settings writes land in the repo working tree automatically. - `~/.local/state/noctalia/settings.toml` can SILENTLY become a plain file (observed 2026-10-17; hardlink/symlink wiring decays) → GUI bar-layout changes then diverge from the repo with no signal. AUDIT: `readlink ~/.local/state/noctalia/settings.toml` must print the repo path; if it's a plain file and repo copy is content-identical, re-arm: `ln -sfn ` + `noctalia config validate`. - Landing in the working tree ≠ propagated: other boxes only see it after commit + push to Gitea main. `live-sync.path` (PR #15; DirectoryNotEmpty on `dotfiles/`) commits dotfiles-tier writes within ~2 s once deployed — until it is active on a box, the hourly heartbeat leaves up to 59 min of exposure, and on 2026-10-18 exactly that window let a trunk-sync stash destroy months of GUI layout work. Until verified active (`systemctl --user status live-sync.path`), commit GUI layout edits the same session yourself. Noctalia's runtime churn (wallpaper path, nightlight, panel positions) rides along; normal. - niri has NO settings GUI; niri "GUI changes" don't exist, and `niri msg output ...` runtime overrides are not persisted. niri cfg mirror↔live links also decay (all inodes decoupled once) → audit by CONTENT: `diff` every `~/.config/niri/cfg/*.kdl` against its `dotfiles/zz-blankpad/niri/...` mirror, never trust links. ## If the bar got wiped (recovery) - The working-tree file is often the ONLY copy of GUI work; a `git checkout`/stash/merge clobber is survivable because git objects outlive stash entries: `git fsck --lost-found`, inspect `git log -1 --format='%ci %s' ` (newest `WIP on` stash commits hold the last good settings.toml), dump with `git show :dotfiles/noctalia/.local/state/noctalia/settings.toml`. - Before restoring: back up the clobbered file to `.AGENTTRASH/`; validate the candidate in a sandbox (`XDG_CONFIG_HOME=… XDG_STATE_HOME=… noctalia config validate` — plugin-widget "unrecognized type" warnings there are offline-CLI blindness, not blockers); restore via `cp` onto the repo path (cp writes through the symlink; `mv` would replace it); prove visually with `noctalia msg screenshot-fullscreen`; commit immediately. - Cross-check the recovered layout against Frank's old screenshots in `~/Pictures/screenshot_*.png` (crop top ~7% with magick) — they are ground truth for what the bar should look like. ## Apply/verify loop (no restart, no reload IPC) 1. Edit the repo `settings.toml`. 2. `noctalia config validate` (checks merged layers; also `noctalia config export [full] | yq -p toml` to inspect effective values). 3. Both layers are file-watched → hot-reload. Prove visually: `noctalia msg screenshot-fullscreen` saves a PNG to `~/Pictures`; read the image and inspect the bar. 4. **Screenshot race:** the `ok` return precedes the PNG write. Never chain `noctalia msg screenshot-fullscreen && magick "$(ls -t ~/Pictures/screenshot_*.png | head -1)" ...` in one command — you crop the PREVIOUS capture. List `ls -t` in a separate later call and crop the named file. 5. Crop for reading: `magick -crop 100%x8%+0+0 +repage /tmp/strip.png`, then read the strip; cross-check clocks against `date -u` / `date`. ## Clock widgets - `[widget.clock]` settings: `format`, `vertical_format`, `tooltip_format`, `timezone` (IANA id, e.g. `"UTC"`, `""` = system local). Tokens are strftime-compatible (`%H` 24h, `%I:%M %p` 12h, `%F` ISO date); `{:%...}` brace fields optional; `\n` = second line. Docs: docs.noctalia.dev → bar/widgets/clock + configuration/date-format-tokens. - **One timezone per widget; multiple instances allowed:** any `[widget.]` needs `type = "clock"` for custom ids (bare `clock` id infers it). Each instance converts independently — e.g. local 12h + `timezone = "UTC"` 24h side by side. - Placement: add ids to `[bar.]` start/center/end, or to a capsule group: `[[bar.default.capsule_group]]` with `id = "g1"` + `members = [...]`, referenced from `start` as `"group:g1"` (member order = left-to-right inside the capsule). - Local date + local 12h fit in ONE widget (same tz); the UTC 24h clock must be a second widget. - Expect the date widget (local) and UTC clock to disagree on the day after ~5 PM Seattle — that's correct UTC, not a bug; offer `%F` inside the UTC widget if it irks. ## Taskbar recipes - Move window indicator beside workspaces: put `"taskbar"` in `start` after `"workspaces"`. - Combine workspaces+windows into ONE widget: `[widget.taskbar] group_by_workspace = true` — per-workspace capsules with disc labels (focused/occupied/empty/urgent colors); `workspace_group_content = "icons"|"count"|"dots"` (count/dots: left-click activates the workspace); `hide_empty_workspaces`, `show_workspace_label`, `minimal`, `workspace_label_placement = corner|centered|inside`. Requires compositor per-window workspace assignment (niri: yes; LabWC: no → stays flat). - The `workspaces` widget itself has no window display; styles are regular/minimal/focus_hint only. ## Law - Full widget/setting tables: https://docs.noctalia.dev/noctalia/bar/ and .../bar/widgets// . Commit bar changes atomically to the command-center repo (checkout is the deployment). - **Ask before applying.** Frank asks "how do I X" questions about the live bar; answer with the exact snippet + file, apply ONLY on explicit go. A settings.toml edit is a live-deployment change, not a demo. (Exception: restoring Frank's own layout after data loss, on his ask.) - Git `M` on settings.toml usually carries noctalia's own runtime churn (wallpaper path, nightlight, panel positions) alongside your edit — mention it when committing.