Continues reducing terminal-reliance for graphical system control. Five
new panels, plus three GUI apps shipped for things better served by an
existing dedicated tool than reimplemented in bos-settings
(gnome-disk-utility, gufw, mission-center).
- Power: battery status/health, brightness, charge-limit thresholds where
the hardware exposes them, TLP profile shown read-only by design (no
Balanced/Performance switcher — TLP auto-selects by power source, and
power-profiles-daemon isn't installed because it conflicts with tlp).
- Firewall: ufw enable/disable, add/remove rules, view active rules.
ufw's own status check requires root (confirmed against the installed
script — not just changes, reads too), so unlike every other panel this
one does NOT query state in build(): every view is constructed eagerly
at app launch, and an unconditional privileged read here would mean a
polkit prompt on every single bos-settings open. Starts blank with a
"Status not loaded" placeholder; state loads only on an explicit Refresh
click, with a guard so refresh's own set_active() doesn't loop back into
triggering ufw enable/disable.
- Users: add/remove accounts, change passwords. All through pkexec on a
background thread. Can't remove the account you're currently running as.
- AUR: search via yay. Installing deliberately opens a terminal instead of
a silent --noconfirm install — yay's interactive PKGBUILD diff review and
sudo prompt are the actual safety mechanism against a malicious AUR
package, not a formality worth automating away.
- Firmware: fwupd device list + updates, same stream-output-then-refresh
pattern as Packages.
packages.x86_64: gnome-disk-utility, gufw, mission-center for disk/firewall/
task-manager GUIs that don't need reinventing inside bos-settings.
yay (yay-bin, AUR-only like calamares/bibata) republished to [breadway] via
the same PKGBUILD + Forgejo workflow pattern, so users can reach the wider
AUR beyond bakery's bread ecosystem.
Disk encryption: Calamares' partition module already has LUKS support
enabled by default, but the checkbox led nowhere — no cryptsetup on the
live/target image, no mkinitcpio encrypt hook, no GRUB cryptodisk wiring.
An encrypted install would partition fine and then never boot. Added
cryptsetup, pinned luksGeneration to luks1 (GRUB doesn't support LUKS2 +
Argon2id), and post-install.sh now detects an encrypted root (lsblk TYPE
== crypt) and conditionally adds the encrypt hook + GRUB_ENABLE_CRYPTODISK +
--modules="cryptodisk luks luks2" on both grub-install passes. No effect on
a normal unencrypted install.
Secure Boot: self-signed via sbctl (shipped in packages.x86_64). BOS can't
ship a Microsoft-signed shim without going through Microsoft's own paid
UEFI CA process, so post-install.sh enrolls BOS's own keys automatically
only when the firmware is already in Setup Mode (sbctl status --json),
signs the kernel/bootloader, and leaves it alone otherwise — sbctl's own
pacman hook re-signs on every future kernel/GRUB update, no further
wiring needed.
Release signing: generated a dedicated Ed25519 "BOS Release Signing" key
(not reused from anything else), stored as the GPG_PRIVATE_KEY Forgejo
Actions secret. release-iso.yml now generates SHA256SUMS and a detached
SHA256SUMS.asc signature alongside every ISO upload; public key committed
at KEYS.asc with verification instructions in the README.
README updated: fixed a stale "greetd + tuigreet" line (breadgreet since
round 3), documented yay/encryption/secure-boot/verification.
Snapshots panel was non-functional (wrong snapper flag); breadgreet picked
the wrong session .desktop and skipped bos-session's PATH fixup; Calamares
aborted offline installs over an unnecessary packages module; snapshot
rollback silently no-op'd on BOS's pinned-subvolume layout (now points at
grub-btrfs instead); breadcrumbs was configurable but had no daemon to run
it. Also: SUPER+I double-bind, breadpaper/packages panels blocking the GTK
main thread, dead polkit rule, and a sweep of smaller drift (default
sidebar view, stale wording, missing .desktop launchers, wallpaper daemon
not recording its own default).
Boot-critical (each confirmed with a real boot/install cycle, not just
code review):
- Live ISO's liveuser shell is zsh, but Hyprland autostart was written
to .bash_profile (never runs) — moved to .zprofile, and switched to
start-hyprland (Hyprland's own watchdog wrapper; raw `exec Hyprland`
is no longer the recommended launch method).
- copytoram (self-enables on most real hardware: non-optical boot +
image < 4GiB + enough free RAM) unmounts /run/archiso/bootmnt, which
unpackfs.conf and bos-copy-kernel both hardcoded as their source —
broke the installer outright on real hardware, confirmed by forcing
copytoram=y. Added a resolver step for unpackfs, and switched the
kernel copy to /usr/lib/modules/$(uname -r)/vmlinuz (part of the live
squashfs itself, unaffected by copytoram).
- BIOS installs got no bootloader — post-install.sh only ever ran the
UEFI grub-install path despite BOS shipping bios.syslinux. Added a
BIOS branch with disk auto-detection.
- @snapshots/@log/@cache were never real: iso/partition.conf's
btrfsSubvolumes key isn't part of this Calamares version's partition
module schema at all (same class of bug as the userShell fix below —
silently ignored). Calamares only natively creates @ and @home.
post-install.sh now creates the three subvolumes by hand after
unpackfs, migrates existing /var/log + /var/cache content into them
before mounting over, and adds the fstab entries — verified end to
end on real hardware, including grub-btrfs generating bootable
snapshot menu entries. The unmount step in the existing snapper
create-config dance also gained retry + lazy-unmount fallback after
a real chroot run hit a transient busy-mount race.
- Default shell was bash instead of zsh post-install: users.conf's
top-level `userShell` key isn't part of this Calamares version's
users module schema either — the real key is nested (user.shell).
- graphical-session.target ships RefuseManualStart=yes (systemd
convention), so the earlier attempt to activate it from hyprland.lua
silently failed and breadclipd (WantedBy=graphical-session.target)
never started. Starts breadclipd.service directly instead.
- /etc/os-release was never set (showed "Arch Linux"); live boot never
had quiet/splash/plymouth wired in (raw kernel scroll the whole
time) despite BOS already shipping a complete bread-logo+spinner
plymouth theme for the installed system.
Also: generalized build-local.sh's per-service skel baking (previously
only breadd.service was hand-committed; breadbox-sync/breadmill/
breadclipd never shipped), added the four new bakery packages to
BREAD_BINS, removed the redundant cliphist/fzf clipboard pipeline in
favor of breadclip, mirrored fastfetch's bread-logo config into skel,
and fixed a stale bos-update comment.
- post-install: ensure the `microcode` initramfs hook (after autodetect) so
installed systems carry CPU ucode — the live ISO embeds it, so nothing is
staged onto the target otherwise. Rebuild all presets with `mkinitcpio -P`.
- post-install: drop the nonexistent `sd-plymouth` hook branch; only the udev
`plymouth` hook exists. Set the theme then rebuild once.
- packages: add zathura + zathura-pdf-mupdf (BOS had no PDF viewer) and
libva-utils (`vainfo`); the Mesa VA-API backend now ships in `mesa` itself.
- bos-welcome: on first run, if NetworkManager isn't fully online, open nmtui
so the user connects before the first bos-update/pacman (avoids confusing DNS
errors on a fresh install). Float the bos-netsetup window like bos-welcome.
bos-update: one command that updates both BOS channels — pacman -Syu (snap-pac
snapshotted) and bakery update --all — best-effort so one failing doesn't abort
the other. Baked into the live env and skel.
Shell: match the dev laptop's zsh. Ship Powerlevel10k + zsh-autosuggestions,
zsh-history-substring-search and zsh-syntax-highlighting, sourced from the distro
packages (no oh-my-zsh framework) in the correct order, plus the dev .p10k.zsh.
Powerlevel10k is AUR-only, so it's republished to [breadway] via
packaging/powerlevel10k + a CI workflow (builds libgit2 + gitstatus from source),
same pattern as bibata / zen-browser-bin. skel/.zshrc keeps the BOS QoL aliases
and pywal palette import, with `update` aliased to bos-update.
- libadwaita apps (nautilus, gnome-text-editor) rendered light because
gsettings-desktop-schemas + dconf were missing, so the color-scheme
prefer-dark autostart silently no-op'd. Add both packages.
- Replace Hyprland's slow default animations with the reference laptop's
bezier curves + per-leaf speeds (hl.curve + hl.animation).
- kitty background_opacity 0.88 -> 0.6 to match the laptop; drop the
macOS-only background_blur line (Hyprland supplies the blur).
- Add README.md documenting the actual image, build, and test flow.
ttf-font-awesome resolved to woff2-font-awesome, a web-only format that
desktop apps can't render glyphs from. otf-font-awesome is the installable
desktop OTF.
Add the packages a general desktop is expected to ship, chosen to stay
opinionated but average-user friendly:
- Editors: neovim (+ ripgrep, fd for a usable nvim/fzf experience)
- GUI basics: gnome-text-editor, gnome-calculator, file-roller, loupe
- Media: vlc (BOS had codecs but no player)
- Hardware: cups + cups-pk-helper + system-config-printer (enable
cups.socket in post-install), blueman, seahorse
- Platform: qt5-wayland + qt6-wayland (native Wayland for Qt apps under
the QT_QPA_PLATFORM=wayland we set), xdg-desktop-portal-gtk (file
dialogs/screenshare for Flatpak/Electron/Zen), flatpak
bibata-cursor-theme-bin 2.0.7-1 is now in the [breadway] repo, so add it
back to the package list and re-enable the Bibata-Modern-Ice cursor in the
Hyprland env, GTK settings, and gsettings autostart.
- packages.x86_64: add bread, breadbar, breadbox, breadcrumbs, breadpad,
bos-settings so they ship in the squashfs and reach the target via unpackfs
(no network needed; install works fully offline)
- shellprocess.conf: set timeout 1800 — Calamares' 10s default was killing
post-install.sh partway (the real cause of the empty /boot + ESP); the "-"
prefix had been masking the kill as success
- bos-live-setup: live user now boots the real BOS desktop from /etc/skel
(breadd + breadbar + breadbox) with the installer layered on top
(auto-launch + Super+I), instead of an installer-only kiosk
- post-install.sh: drop the now-redundant networked `bakery install`
unpackfs runs unsquashfs then rsync to copy the rootfs onto the target;
rsync was missing (error code 127), so add it alongside squashfs-tools.
unpackfs also copies the live filesystem verbatim, so the installed
system would inherit the archiso initramfs hooks (booting into the live
path) plus the live autologin/user/sudoers. Rework post-install.sh to run
in the target chroot as a resilient best-effort script that:
- removes the live autologin drop-in, bos-live-setup service/scripts and
the liveuser sudoers file, and locks root (sudo model; the live medium
left root passwordless),
- drops the archiso mkinitcpio config, installs the stock linux.preset and
regenerates the initramfs, then refreshes grub.cfg,
- keeps the snapper/services/dotfiles setup, with the network-dependent
bakery install made non-fatal so offline installs still complete.
Calamares' unpackfs module shells out to unsquashfs to extract
airootfs.sfs onto the target. squashfs-tools wasn't in the live package
list, so installs failed at the Finish step with "Failed to find
unsquashfs ... Bad unpackfs configuration". Add it.
The profile shipped boot configs and the package list but lacked the
mkinitcpio archiso configuration, so mkarchiso built a stock initramfs
with no archiso hook. At boot the kernel honoured archisosearchuuid/
archisobasedir but nothing knew how to find and mount airootfs.sfs, so
switch-root failed and the live medium dropped to emergency mode.
Add the canonical releng pieces:
- airootfs/etc/mkinitcpio.conf.d/archiso.conf (HOOKS incl. archiso)
- airootfs/etc/mkinitcpio.d/linux.preset (builds initramfs-linux.img)
- mkinitcpio{,-archiso,-nfs-utils} in packages.x86_64
Calamares isn't in Arch's official repos, so BOS vendors the PKGBUILD and
publishes a built package to the [breadway] repo. All its deps are official
(kpmcore, qt6-*, yaml-cpp). Also drop the nonexistent calamares-qt6 from the
package list (calamares 3.4.x is already Qt6).
mkarchiso validation: bios.syslinux.mbr/eltorito and uefi-x64.* bootmodes
are deprecated -> use bios.syslinux + uefi.systemd-boot. syslinux must be
in the package list for the BIOS bootmode; add memtest86+/edk2-shell too.
- Fix XDG config dir logic in config/mod.rs (was double-nesting and had /home/user hardcode)
- Replace /home/user hardcodes in breadbar.rs and hyprland.rs with config::config_dir()
- Fix /home/user hardcode in packages.rs (uses /root fallback for .local/state path)
- Remove eprintln! from GTK callback in packages.rs (no stderr at runtime)
- Fix YAML parse error in branding.desc (missing space after sidebarTextHighlight key)
- Add .gitignore (Rust target/, ISO artifacts, editor/OS junk, secrets)
- Delete state.rs (dead code — never mod'd in main.rs)
- Add brightnessctl, grim, slurp to packages.x86_64 (used by keybinds)
- Rename can-you-begin-a-composed-beacon.md → DESIGN.md
ISO structural:
- Move post-install.sh → airootfs/etc/calamares/ (it was never in the squashfs)
- Create airootfs/etc/skel/.config/ with all dotfiles (deploy path now works)
- Add iso/pacman.conf with [breadway] custom repo stub for calamares + bakery
- Add Calamares branding component (bos/branding.desc + show.qml)
- Add missing unpackfs.conf and mount.conf modules
- Add live-session autostart: getty autologin → bash_profile → Hyprland → calamares
- Add polkit rule for wheel-group snapper rollback (pkexec path)
- Remove wlroots from packages (bundled with Hyprland); add bakery to package list
- Fix modules-search path in settings.conf
Dotfiles:
- Rename dotfiles/hyprland/ → dotfiles/hypr/ (Hyprland reads ~/.config/hypr/)
- Fix deprecated shadow options: drop_shadow/shadow_range → shadow { } block
bos-settings Rust:
- Replace glib::MainContext::channel (removed in glib 0.19) with async_channel
- Stream bakery update output line-by-line instead of buffering all at once
- Fix zombie processes: per-package update buttons now wait() in a thread
- Fix sidebar/stack mismatch at startup: select snapshots row to match default view
- Replace deprecated MessageDialog with AlertDialog (GTK 4.10+) throughout
- Use pkexec for snapper rollback so polkit handles privilege escalation
- Add confirmation dialog before delete snapshot (was missing, rollback had one)
- Add refresh button + repopulate after delete in snapshots view
- Add "Saved" / "Error: …" status label to every config view save button
- Add "Remove" buttons to breadbox contexts and breadcrumbs profiles
- Remove hardcoded model string from breadpad defaults
- Drop unused state mod; fix config_dir HOME fallback; fix zombie in editor launches
https://claude.ai/code/session_01WszGHvCmxgcyTwNSkfLF9P