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.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
liveuser can't write /var/log, so the .bash_profile redirect
(Hyprland &>/var/log/hyprland-live.log) failed and bash aborted the line
without ever launching the compositor. Log to /tmp/hyprland-live.log,
which the live user can write.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The live medium autologged root on tty1 and exec'd Hyprland, but Hyprland
refuses to start with superuser privileges ("launched with superuser
privileges, but the privileges check is not omitted") and exited before
even creating a log — leaving tty1 at a blank blinking cursor. (Boot,
switch-root, firstboot suppression and the bos login on other ttys were
all already working.)
Adopt the standard live-ISO pattern:
- bos-live-setup.service (oneshot, gated on the archisobasedir cmdline so
it only runs on the live medium) creates an unprivileged `liveuser`,
adds it to the usual hardware groups, clears its password, and drops in
a minimal live Hyprland config that auto-launches the installer.
- tty1 autologin now targets liveuser instead of root.
- Calamares needs root, so bos-launch-calamares runs it via passwordless
sudo (/etc/sudoers.d/99-bos-live) with the Wayland env preserved, so the
root installer renders on the live user's compositor.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Redirect the live autologin compositor's stdout/stderr to
/var/log/hyprland-live.log, and on exit drop to an interactive shell
showing the return code instead of letting the getty autologin
respawn-loop hide any startup failure behind a blank blinking cursor.
Makes a failed live boot diagnosable and leaves the medium usable.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
On GPU-less targets (VMs, headless, exotic hardware) wlroots refuses to
initialise without a hardware renderer, so the autologin session exec'd
Hyprland on tty1 and it died immediately — leaving a blinking cursor and
no desktop, while tty2 still showed the (correct) `bos` login.
Export WLR_RENDERER_ALLOW_SOFTWARE=1 before exec Hyprland in root's
.bash_profile so wlroots may use the llvmpipe software renderer when no
GPU renderer exists. On real hardware the hardware renderer is still
chosen; this is purely a fallback. Also set WLR_NO_HARDWARE_CURSORS=1 so
the pointer isn't invisible in VMs. Both must be real env vars (read at
wlroots init), not Hyprland `env=` lines, which apply too late.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The fixed initramfs boots into userspace, but systemd-firstboot
(ConditionFirstBoot=yes, --prompt-locale --prompt-keymap-auto
--prompt-timezone --prompt-root-password) then blocked the console
waiting for interactive input, and root was locked (no /etc/shadow),
so the live medium never reached the autologin getty + Hyprland.
Ship the same base files releng uses to satisfy firstboot and unlock
root for autologin:
- etc/locale.conf (LANG=C.UTF-8) -> no locale prompt
- etc/localtime (-> UTC) -> no timezone prompt
- etc/vconsole.conf (KEYMAP=us) -> no keymap prompt
- etc/hostname (bos)
- etc/shadow (root unlocked, empty pw, perms 0400 via profiledef)
- etc/passwd (root shell = bash; system users are appended by the
systemd-sysusers pacman hook during pacstrap)
The overlay is applied before pacstrap (mkarchiso _make_custom_airootfs
precedes _make_packages) and these are pacman backup files, so the
static passwd/shadow act as the base and package scriptlets add the
rest — no clobbering of polkitd/pipewire/etc. users.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The profile declared syslinux + systemd-boot bootmodes but lacked the
required config directories, so mkarchiso would fail. Added from the
official releng profile, rebranded to Bread OS; %PLACEHOLDER% tokens are
substituted by mkarchiso at build time.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- logo.png (productLogo/productIcon): rasterised from the bread logo, transparent
- languages.png (productWelcome): logo centred on a light Nord canvas
- logo.svg / bread_white.svg: source vector
Resolves the missing-branding-asset blocker so Calamares can render.
Colour scheme can be refined when final SVGs land.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
calamares and calamares-qt6 are in Arch's extra repo; no custom PKGBUILD
needed. Update packages.x86_64 and the pacman.conf comment accordingly.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Forgejo serves the repo db as {owner}.{group}.{domain}.db, and pacman
fetches "<section>.db" from Server — so the section name must match.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- package.yml: use correct Arch registry upload (octet-stream + binary body
+ PUT /api/packages/Breadway/arch/os), drop --privileged, remove
actions/checkout (archlinux image has no Node) in favour of a manual
shell clone, use the built-in Actions token instead of a stored secret,
and --nocheck (tests belong in CI, not packaging)
- mirror.yml: clone --mirror + explicit refs/heads + refs/tags push with
--prune, instead of pushing refs/remotes pollution from a checkout
- pacman.conf: correct Server URL to the Forgejo Arch registry format
Requires only the GITHUB_MIRROR_TOKEN secret (GitHub PAT, repo scope) for
the mirror job; package publishing uses the automatic per-run token.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- .forgejo/workflows/mirror.yml: mirrors every push/tag to GitHub
- .forgejo/workflows/package.yml: builds PKGBUILD on tag and publishes
bos-settings to the Forgejo Arch package registry (distrib=breadway)
- iso/pacman.conf: replace placeholder repo.breadway.dev with the actual
Forgejo package registry URL
Requires two Forgejo secrets:
GITHUB_MIRROR_TOKEN — GitHub PAT with repo push scope
FORGEJO_TOKEN — Forgejo token with package:write scope
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 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
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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