Fix all issues from code/UX review

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
This commit is contained in:
Claude 2026-06-12 13:45:00 +00:00
parent 0ff3998c84
commit d5913da277
32 changed files with 720 additions and 288 deletions

View file

@ -0,0 +1,29 @@
---
componentName: bos
strings:
productName: "Bread Operating System"
shortProductName: "BOS"
version: "rolling"
shortVersion: "rolling"
versionedName: "BOS (rolling)"
shortVersionedName: "BOS"
bootloaderEntryName: "BOS"
productUrl: "https://github.com/Breadway/bos"
supportUrl: "https://github.com/Breadway/bos/issues"
knownIssuesUrl: "https://github.com/Breadway/bos/issues"
releaseNotesUrl: "https://github.com/Breadway/bos/releases"
images:
productLogo: "logo.png"
productIcon: "logo.png"
productWelcome: "languages.png"
slideshow: "show.qml"
slideshowAPI: 2
style:
sidebarBackground: "#3b4252"
sidebarText: "#eceff4"
sidebarTextSelect: "#5e81ac"
sidebarTextHighlight:"#eceff4"

View file

@ -0,0 +1,43 @@
/* BOS installer slideshow */
import QtQuick 2.15
import io.calamares.ui 1.0
Presentation {
id: presentation
Slide {
anchors.fill: parent
Rectangle {
anchors.fill: parent
color: "#2e3440"
Column {
anchors.centerIn: parent
spacing: 20
Text {
text: "Bread Operating System"
color: "#eceff4"
font.pointSize: 28
font.bold: true
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
text: "Installing your system…"
color: "#88c0d0"
font.pointSize: 16
anchors.horizontalCenter: parent.horizontalCenter
}
Text {
text: "Hyprland · bread · bakery · snapshots"
color: "#616e88"
font.pointSize: 12
anchors.horizontalCenter: parent.horizontalCenter
}
}
}
}
}

View file

@ -0,0 +1,10 @@
---
# Extra mount options applied by filesystem type.
# Btrfs subvolume mounts are already configured in partition.conf.
mountOptions:
- filesystem: default
options: [noatime]
- filesystem: btrfs
options: [noatime, "compress=zstd", "space_cache=v2"]
- filesystem: vfat
options: [umask=0077]

View file

@ -0,0 +1,7 @@
---
# Unpack the live squashfs onto the target partition.
# "arch" matches profiledef.sh install_dir; adjust if that changes.
unpack:
- source: "/run/archiso/bootmnt/arch/x86_64/airootfs.sfs"
sourcefs: "squashfs"
destination: ""

View file

@ -9,7 +9,7 @@ sed -i 's/NUMBER_MIN_AGE="[^"]*"/NUMBER_MIN_AGE="1800"/' /etc/snapper/configs/ro
sed -i 's/NUMBER_LIMIT="[^"]*"/NUMBER_LIMIT="10"/' /etc/snapper/configs/root
sed -i 's/NUMBER_LIMIT_IMPORTANT="[^"]*"/NUMBER_LIMIT_IMPORTANT="5"/' /etc/snapper/configs/root
# Allow main user to use snapper without sudo
# Allow main user to list/create/delete snapshots without sudo
MAIN_USER=$(getent passwd 1000 | cut -d: -f1)
sed -i "s/ALLOW_USERS=\"\"/ALLOW_USERS=\"$MAIN_USER\"/" /etc/snapper/configs/root
@ -19,18 +19,19 @@ systemctl enable bluetooth
systemctl enable snapper-cleanup.timer
systemctl enable grub-btrfs.path
# --- Bakery install ---
# --- Bakery: install bread ecosystem ---
# Requires [breadway] repo in /etc/pacman.conf — see iso/pacman.conf
if command -v bakery &>/dev/null; then
sudo -u "$MAIN_USER" bakery install bread breadbar breadbox breadcrumbs breadpad bos-settings
fi
# --- Deploy dotfiles (skip existing files) ---
DOTFILES_SRC="/etc/skel/.config"
# --- Deploy dotfiles into user home (skip any file that already exists) ---
SKEL_SRC="/etc/skel/.config"
DOTFILES_DEST="/home/$MAIN_USER/.config"
if [[ -d "$DOTFILES_SRC" ]]; then
if [[ -d "$SKEL_SRC" ]]; then
mkdir -p "$DOTFILES_DEST"
cp -rn "$DOTFILES_SRC/." "$DOTFILES_DEST/"
cp -rn "$SKEL_SRC/." "$DOTFILES_DEST/"
chown -R "$MAIN_USER:$MAIN_USER" "$DOTFILES_DEST"
fi

View file

@ -1,5 +1,5 @@
---
modules-search: [local, /usr/lib/calamares/modules]
modules-search: [/etc/calamares/modules, /usr/lib/calamares/modules]
sequence:
- show:

View file

@ -0,0 +1,11 @@
// Allow members of the wheel group to perform snapper rollback via pkexec
// without a password prompt. Other snapper operations (list/create/delete)
// are controlled by ALLOW_USERS in /etc/snapper/configs/root.
polkit.addRule(function(action, subject) {
if (action.id == "io.opensuse.Snapper.Rollback" &&
subject.local &&
subject.active &&
subject.isInGroup("wheel")) {
return polkit.Result.YES;
}
});

View file

@ -0,0 +1,8 @@
log_level = "info"
[adapters]
keyboard = true
mouse = true
touchpad = true
bluetooth = true
gamepad = true

View file

@ -0,0 +1 @@
bread.activate_profile("default")

View file

@ -0,0 +1,3 @@
[[context]]
name = "default"
apps = ["firefox", "foot", "nautilus", "code"]

View file

@ -0,0 +1,3 @@
[[profile]]
name = "home"
ssids = []

View file

@ -0,0 +1,56 @@
monitor=,preferred,auto,1
exec-once = breadd
exec-once = breadbar
exec-once = breadbox-sync
source = ~/.config/hypr/keybinds.conf
general {
gaps_in = 5
gaps_out = 10
border_size = 2
col.active_border = rgba(88c0d0ff)
col.inactive_border = rgba(4c566aff)
layout = dwindle
}
decoration {
rounding = 8
blur {
enabled = true
size = 6
passes = 2
}
shadow {
enabled = true
range = 12
render_power = 3
}
}
animations {
enabled = true
bezier = ease, 0.25, 0.1, 0.25, 1.0
animation = windows, 1, 4, ease
animation = fade, 1, 4, ease
animation = workspaces, 1, 5, ease
}
input {
kb_layout = us
follow_mouse = 1
touchpad {
natural_scroll = true
}
}
dwindle {
pseudotile = true
preserve_split = true
}
misc {
disable_hyprland_logo = true
disable_splash_rendering = true
}

View file

@ -0,0 +1,58 @@
$mod = SUPER
# App launchers
bind = $mod, Space, exec, breadbox
bind = $mod, N, exec, breadpad
bind = $mod, M, exec, breadman
bind = $mod, S, exec, bos-settings
# Core
bind = $mod, Return, exec, foot
bind = $mod, Q, killactive
bind = $mod SHIFT, E, exit
bind = $mod, F, fullscreen
# Focus
bind = $mod, H, movefocus, l
bind = $mod, L, movefocus, r
bind = $mod, K, movefocus, u
bind = $mod, J, movefocus, d
# Move windows
bind = $mod SHIFT, H, movewindow, l
bind = $mod SHIFT, L, movewindow, r
bind = $mod SHIFT, K, movewindow, u
bind = $mod SHIFT, J, movewindow, d
# Workspaces
bind = $mod, 1, workspace, 1
bind = $mod, 2, workspace, 2
bind = $mod, 3, workspace, 3
bind = $mod, 4, workspace, 4
bind = $mod, 5, workspace, 5
bind = $mod SHIFT, 1, movetoworkspace, 1
bind = $mod SHIFT, 2, movetoworkspace, 2
bind = $mod SHIFT, 3, movetoworkspace, 3
bind = $mod SHIFT, 4, movetoworkspace, 4
bind = $mod SHIFT, 5, movetoworkspace, 5
# Scroll through workspaces
bind = $mod, mouse_down, workspace, e+1
bind = $mod, mouse_up, workspace, e-1
# Mouse binds
bindm = $mod, mouse:272, movewindow
bindm = $mod, mouse:273, resizewindow
# Volume
bind = , XF86AudioRaiseVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
bind = , XF86AudioLowerVolume, exec, wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
bind = , XF86AudioMute, exec, wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
# Brightness
bind = , XF86MonBrightnessUp, exec, brightnessctl set 5%+
bind = , XF86MonBrightnessDown, exec, brightnessctl set 5%-
# Screenshot
bind = , Print, exec, grimblast copy area

View file

@ -0,0 +1,3 @@
[Service]
ExecStart=
ExecStart=-/sbin/agetty -o '-p -f -- \\u' --noclear --autologin root - $TERM

View file

@ -0,0 +1,4 @@
# Auto-start Hyprland on tty1 in the live session
if [[ "$(tty)" == "/dev/tty1" ]] && [[ -z "$WAYLAND_DISPLAY" ]]; then
exec Hyprland
fi

View file

@ -0,0 +1,28 @@
# Live-session Hyprland config — launches Calamares on start.
# This is NOT the installed system config; that lives in dotfiles/hypr/.
monitor=,preferred,auto,1
exec-once = calamares
general {
border_size = 2
col.active_border = rgba(88c0d0ff)
col.inactive_border = rgba(4c566aff)
}
decoration {
rounding = 4
}
input {
kb_layout = us
follow_mouse = 1
}
misc {
disable_hyprland_logo = true
disable_splash_rendering = true
# Keep compositor running if calamares exits (user can relaunch)
exit_window_request_force = false
}

View file

@ -47,10 +47,9 @@ gtk4-layer-shell
librsvg
libpulse
# Display
# Display (wlroots is bundled with Hyprland; don't list separately)
wayland
wayland-protocols
wlroots
# Fonts
noto-fonts
@ -63,10 +62,13 @@ foot
# File manager
nautilus
# Installer
# Installer — sourced from [breadway] repo (see pacman.conf)
calamares
calamares-qt6
# Bread ecosystem — sourced from [breadway] repo
bakery
# Utilities
sudo
git

38
iso/pacman.conf Normal file
View file

@ -0,0 +1,38 @@
#
# BOS pacman.conf — used during ISO build and installed to the target system.
# Based on the standard Arch Linux pacman.conf.
#
[options]
HoldPkg = pacman glibc
Architecture = auto
CheckSpace
ParallelDownloads = 5
Color
VerbosePkgLists
ILoveCandy
SigLevel = Required DatabaseOptional
LocalFileSigLevel = Optional
[core]
Include = /etc/pacman.d/mirrorlist
[extra]
Include = /etc/pacman.d/mirrorlist
[multilib]
Include = /etc/pacman.d/mirrorlist
# -----------------------------------------------------------------------
# Breadway custom repo — provides: bakery, calamares (pre-built), and the
# bread ecosystem packages (bread, breadbar, breadbox, breadcrumbs, breadpad,
# bos-settings).
#
# TODO: Replace this URL with the actual hosted repo before building.
# See: https://github.com/Breadway/repo for setup instructions.
# -----------------------------------------------------------------------
[breadway]
SigLevel = Optional TrustAll
Server = https://repo.breadway.dev/$arch