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. |
||
|---|---|---|
| .forgejo/workflows | ||
| assets | ||
| bos-settings | ||
| dotfiles | ||
| iso | ||
| packaging | ||
| scripts | ||
| .gitignore | ||
| bakery.toml | ||
| build-local.sh | ||
| Cargo.lock | ||
| Cargo.toml | ||
| DESIGN.md | ||
| KEYS.asc | ||
| LICENSE | ||
| README.md | ||
BOS — Bread Operating System
An Arch-based, Hyprland desktop distribution that ships the bread ecosystem preconfigured. One Calamares install produces a themed, bootable Wayland desktop — no manual Arch bootstrap, no wiring up dotfiles, no per-tool bakery installs.
Design rationale and the btrfs/A-B roadmap live in DESIGN.md. This file is the practical overview: what's in the image, how to build it, and how to test it.
What you get
- Compositor: Hyprland with a native-Lua config (
hyprland.lua), curated keybinds, snappy animations, blur, and pywal-driven colours on a black base. - bread ecosystem, baked into
/etc/skelfrom bakery-managed binaries (no network needed at install time):bread/breadd,breadbar(status bar- notification daemon),
breadbox(launcher),breadcrumbs(Wi-Fi profiles),breadpad(notes/reminders),breadman, and thebakerypackage manager.
- notification daemon),
- bos-settings: a GTK4 control panel that configures every bread* app's config from a GUI (non-destructively), plus snapshot rollback and bakery updates. See below.
- Login: greetd + breadgreet (bread-ecosystem's own greeter, under
cage) → Hyprland session. - Boot splash: Plymouth
bostheme (logo + spinner, black background). - Theming: global dark across GTK3 (Adwaita-dark), GTK4/libadwaita
(
color-scheme: prefer-dark), and Qt (qt5ct/qt6ct Fusion dark); Papirus-Dark icons; Bibata cursor. - Apps: kitty, nautilus (+ gvfs), Zen browser, VLC, loupe, gnome-text-editor,
gnome-calculator, file-roller, with file associations wired in
mimeapps.list.yayships for AUR access beyond bakery's bread ecosystem +[breadway]. - Hardware: pipewire audio, NetworkManager, BlueZ + blueman, CUPS printing with avahi mDNS discovery, TLP power management, fwupd firmware updates.
- Resilience: btrfs + snapper + snap-pac + grub-btrfs snapshots on every pacman transaction; zram swap; ufw firewall (deny-incoming, mDNS allowed).
- Security: full-disk encryption (LUKS, via Calamares' built-in support —
cryptsetup + the matching mkinitcpio/GRUB wiring ship so an encrypted
install actually boots) and self-signed Secure Boot (via
sbctl, enrolled automatically at install time when the firmware is in Setup Mode).
Repo layout
bos/
├── Cargo.toml # workspace (members: bos-settings)
├── bos-settings/ # GTK4 unified settings app (Rust)
│ └── src/
│ ├── config/mod.rs # non-destructive toml_edit config layer
│ └── ui/{widgets,window,sidebar}.rs, ui/views/*.rs
├── iso/ # archiso profile
│ ├── profiledef.sh
│ ├── packages.x86_64 # live + installed package set
│ └── airootfs/ # files overlaid onto the image
│ └── etc/
│ ├── skel/ # default user dotfiles (hypr, kitty, gtk, …)
│ └── calamares/ # installer config + post-install.sh
├── packaging/ # in-house PKGBUILDs for AUR-only deps
│ ├── arch/ # bos-settings
│ ├── calamares/
│ └── bibata/
├── .forgejo/workflows/ # CI: build + publish packages to [breadway]
├── build-local.sh # native ISO build for this machine
└── DESIGN.md
Building the ISO
build-local.sh builds the image natively (no container) and bakes this
machine's bakery-installed bread binaries into /etc/skel:
sudo ./build-local.sh # release-quality (xz squashfs)
sudo FAST_BUILD=1 ./build-local.sh # fast dev iteration (zstd squashfs)
The ISO lands in out/bos-<date>-x86_64.iso. The script pins
SOURCE_DATE_EPOCH (reproducible UUIDs) and rewrites the [breadway] repo URL
to the Tailscale-reachable Forgejo registry for the build.
Why some packages are in-house
calamares, zen-browser-bin, bibata-cursor-theme, and yay-bin are
AUR-only. BOS keeps a PKGBUILD for each under packaging/ and republishes the
built package to the [breadway] repo via a Forgejo Actions workflow (built
on the hestia self-hosted runner, published with a scoped registry token).
bos-settings itself publishes the same way on a v* tag.
Verifying a release
Every tagged release ISO on the Forgejo releases
page ships alongside a
SHA256SUMS file and a detached signature SHA256SUMS.asc, signed by a
dedicated release-signing key (not reused from anything else):
5620 3B86 A110 695A E7F3 1093 4AF3 323D 678E B5E2
The public half is committed at KEYS.asc. To verify a download:
gpg --import KEYS.asc
gpg --verify SHA256SUMS.asc SHA256SUMS
sha256sum -c SHA256SUMS
Testing in a VM
A reusable, GPU-accelerated launcher lives at ~/bos-vm/run.sh:
~/bos-vm/run.sh install # boot the ISO installer (target disk attached)
~/bos-vm/run.sh # boot the installed system from the disk
It uses KVM + -cpu host, 8 GiB / 8 vCPU, and virtio-vga-gl with
-display gtk,gl=on (virgl) — 3D acceleration is essential for a smooth
Hyprland session in QEMU. The disk lives on NVMe (not the tmpfs /tmp) to
avoid memory pressure.
bos-settings
A GTK4 settings app aiming for GNOME-Settings-style parity: not just editing config files, but live system state and control, so day-to-day machine administration doesn't require a terminal.
Bread-ecosystem TOML configs are edited non-destructively: toml_edit
parses the file, changes only the keys a view exposes, and writes it back —
preserving comments and any keys the UI doesn't model (calendar passwords,
saved-network passwords, model paths). Panels with a daemon behind them
(bread, breadbox, breadcrumbs, breadsearch, breadclip) also get live
systemd status + Start/Stop/Restart/Logs via a shared service_control
widget, not just the config file.
| Panel | What it does |
|---|---|
| About | System info (OS/kernel/CPU/GPU/memory/disk/uptime) + hostname |
| Network | Wi-Fi scan/connect, Ethernet status, radio toggle |
| Wi-Fi Profiles (breadcrumbs) | breadcrumbs.toml — settings, saved networks, profiles |
| Firewall | ufw rules: enable/disable, add/remove, view active rules |
| Sound | PipeWire output/input device + volume via pactl |
| Power | Battery status/health, brightness, charge limits (hardware-dependent), TLP profile (read-only) |
| Date & Time | Timezone, NTP sync toggle |
| Display (Hyprland) | Connected monitors + open hyprland.lua in editor |
| Users | Add/remove accounts, change passwords |
| Wallpaper (breadpaper) | Set wallpaper, drives the pywal-derived accent palette |
| Bar (breadbar) | breadbar/style.css override, live-reloads on save |
| Launcher (breadbox) | breadbox/config.toml — launcher contexts |
| Clipboard (breadclip) | breadclipd service control + "open history" |
| Notes (breadpad) | breadpad/breadpad.toml — settings, model + ollama, reminders, calendar |
| File Search (breadsearch) | breadsearch/config.toml — index/search/model + breadmill service |
| Daemon (bread) | breadd.toml — daemon, lua, modules, adapters, events, notifications |
| Packages | bakery installed list + updates, pacman system update |
| AUR | Search via yay; installing opens a terminal (AUR build scripts need review) |
| Firmware | fwupd device list + updates |
| Snapshots | snapper list / boot-into (grub-btrfs) / delete |
Build standalone:
cargo build --release -p bos-settings
cargo test -p bos-settings # includes config round-trip tests
The bread ecosystem at a glance
| Tool | Role | Launch |
|---|---|---|
bread / breadd |
Reactive automation daemon — normalises hardware/compositor signals into events dispatched to Lua modules | runs at login |
breadbar |
Top status bar (workspaces, clock, stats, tray) and the notification daemon | runs at login |
breadbox |
Application launcher | SUPER+Space |
breadpad |
Notes & reminders (AI-classified, optional CalDAV sync) | SUPER+U |
breadman |
Package-manager UI | SUPER+M |
breadcrumbs |
Wi-Fi profile state machine (location-aware) | CLI / BOS Settings |
bakery |
CLI package manager for the ecosystem | bakery |
bos-settings |
Unified GTK4 control panel for all of the above + snapshots + updates | SUPER+, |
Keyboard shortcuts
SUPER is the Windows/Cmd key. Press SUPER+/ at any time for this
cheatsheet in-session; first boot shows a short welcome (once).
| Keys | Action |
|---|---|
SUPER+Return |
Terminal (kitty) |
SUPER+Space |
App launcher (breadbox) |
SUPER+E / SUPER+B |
Files (nautilus) / Browser (zen) |
SUPER+U / SUPER+M |
breadpad / breadman |
SUPER+, / SUPER+/ |
BOS Settings / keybind cheatsheet |
SUPER+L / SUPER+N |
Lock / log out |
SUPER+Backspace |
Close window |
SUPER+F / SUPER+V / SUPER+T |
Fullscreen / float / toggle split |
SUPER+Shift+V |
Clipboard history |
SUPER+Tab |
Last window |
SUPER+Shift+S/C/P |
Screenshot region→file / region→clipboard / screen→file |
SUPER+arrows |
Move focus |
SUPER+Shift+h/j/k/l |
Move window |
SUPER+Shift+arrows |
Resize window |
SUPER+1..0 |
Switch to workspace 1–10 |
SUPER+Shift+1..0 |
Move window to workspace |
SUPER+[ / ] |
Previous / next workspace |
SUPER+left/right-drag |
Move / resize window with the mouse |
Known limitations
- GPUs: ships the generic Mesa stack — AMD and Intel work out of the box.
The NVIDIA proprietary driver is not included; NVIDIA users must install
nvidia/nvidia-utilsand set the usual Hyprland env vars after install. - Virtual machines: Hyprland needs GPU acceleration to be smooth. Use
virtio-vga-gl+-display gtk,gl=on(virgl); plain software rendering is noticeably laggy. - Wayland-first: X11-only apps run through XWayland; a few may misbehave.
- Secure Boot: self-signed only, via
sbctl— BOS can't ship a Microsoft-signed shim (that needs going through Microsoft's own paid UEFI CA process). Post-install enrolls BOS's own keys automatically, but only when the firmware is already in Setup Mode (no vendor keys installed yet); otherwise it's skipped and you can runsudo sbctl enroll-keys --microsoft && sudo sbctl sign-all -gyourself later (after clearing your firmware's existing keys, if any). The installer writes both an NVRAM entry and the removableEFI/BOOT/BOOTX64.EFIfallback either way. - Disk encryption: full-disk LUKS is available on the installer's "Erase
disk" page (Calamares' own checkbox) and on manually-created partitions —
BOS ships the matching
cryptsetup/mkinitcpio/GRUB wiring so an encrypted install actually boots (LUKS1, since GRUB doesn't support LUKS2 + Argon2id). - Snapshots assume btrfs: the snapper/grub-btrfs tooling expects the default btrfs subvolume layout the installer creates.
Recovery
An update broke something (system still boots): open BOS Settings →
Snapshots and roll back, or pick a pre-update snapshot from the GRUB
“snapshots” submenu at boot, then run snapper rollback from the booted
snapshot.
The system won't boot (broken GRUB / lost EFI entry):
- Boot the BOS ISO and open a terminal (
SUPER+Return). - Mount the installed root and EFI, then chroot:
mount -o subvol=@ /dev/sdXN /mnt mount /dev/sdXP /mnt/boot/efi # the EFI partition arch-chroot /mnt - Reinstall the bootloader (the same sequence the installer uses):
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=BOS --recheck grub-install --target=x86_64-efi --efi-directory=/boot/efi --removable --recheck grub-mkconfig -o /boot/grub/grub.cfg
Firmware shows “no boot device”: select EFI/BOOT/BOOTX64.EFI from the
firmware boot menu — the installer always writes that removable fallback.
Boot architecture notes
archiso keeps the kernel and initramfs outside the squashfs, so the installer
stages them explicitly: a shellprocess@kernel step copies the kernel + ucode
into the target /boot and writes a stock mkinitcpio preset before the native
initcpio module builds the initramfs. GRUB is not installed by Calamares'
bootloader/grubcfg modules (they leave the ESP empty in this layout) —
post-install.sh runs grub-install (NVRAM and --removable) +
grub-mkconfig instead, which is the sequence verified to boot.