Compare commits
41 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f53377914 | ||
|
|
c46e348d6a | ||
|
|
31d0875791 | ||
|
|
3dd53f3fe6 | ||
|
|
4a16e18cf3 | ||
|
|
d484c8e933 | ||
|
|
a4af3aa938 | ||
|
|
9ea57d87c0 | ||
|
|
2a866144f4 | ||
|
|
122cd39cb1 | ||
|
|
356cc08dfe | ||
|
|
3a30cd004f | ||
|
|
23e60dffe0 | ||
|
|
b9544d517b | ||
|
|
12dbec5f32 | ||
|
|
de4e3b09ba | ||
|
|
2cbf46a836 | ||
|
|
6c3c33e4ae | ||
|
|
a7b3f70930 | ||
|
|
cbdeccd03e | ||
|
|
337d280f2b | ||
|
|
6135b2215d | ||
|
|
5a14288025 | ||
|
|
82c63bc4c4 | ||
|
|
0d550a1bda | ||
|
|
ed0eea3cb1 | ||
|
|
8e41d9fc2b | ||
|
|
30d94aa286 | ||
|
|
1bcd9588de | ||
|
|
12a8fa00bb | ||
|
|
0ee174e16e | ||
|
|
eda2c44c48 | ||
|
|
f98f21bbdd | ||
|
|
7ef51e8722 | ||
|
|
c259aa9e93 | ||
|
|
a2973b91eb | ||
|
|
769b6283e0 | ||
|
|
2c6feb4ea0 | ||
|
|
6f148e9a06 | ||
|
|
8682698402 | ||
|
|
c744e45c90 |
|
|
@ -1,35 +0,0 @@
|
|||
name: Build and publish powerlevel10k
|
||||
|
||||
# Powerlevel10k (the BOS default zsh prompt) is AUR-only, so BOS maintains an
|
||||
# in-house PKGBUILD and publishes the built package to the [breadway] repo.
|
||||
# Builds gitstatus + libgit2 from source, so it needs cmake + zsh beyond base-devel.
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'packaging/powerlevel10k/**'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
powerlevel10k:
|
||||
runs-on: [self-hosted, hestia]
|
||||
container:
|
||||
image: archlinux:latest
|
||||
steps:
|
||||
- name: Build and publish
|
||||
env:
|
||||
PUBLISH_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
pacman -Syu --noconfirm base-devel git cmake zsh
|
||||
useradd -m builder
|
||||
git config --global --add safe.directory '*'
|
||||
git clone --depth 1 --branch "${GITHUB_REF_NAME}" \
|
||||
"https://git.breadway.dev/${GITHUB_REPOSITORY}.git" /home/builder/src
|
||||
chown -R builder:builder /home/builder/src
|
||||
su builder -c "cd /home/builder/src/packaging/powerlevel10k && makepkg -f --noconfirm --nocheck"
|
||||
PKG=$(find /home/builder/src/packaging/powerlevel10k -name '*.pkg.tar.zst' | head -1)
|
||||
curl -fsS -X PUT \
|
||||
-H "Authorization: token ${PUBLISH_TOKEN}" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary "@${PKG}" \
|
||||
"https://git.breadway.dev/api/packages/Breadway/arch/os"
|
||||
|
|
@ -1,207 +0,0 @@
|
|||
name: Build and release ISO
|
||||
|
||||
# Builds the BOS ISO on the hestia self-hosted runner (native Arch container),
|
||||
# downloads all bakery ecosystem binaries from their GitHub releases, compiles
|
||||
# bread-theme from source, and uploads the resulting ISO to a Forgejo pre-release.
|
||||
# A matching GitHub release is created that points to Forgejo for the download
|
||||
# (GitHub releases cannot host files larger than 2 GB).
|
||||
#
|
||||
# Required secrets:
|
||||
# RELEASE_TOKEN — Forgejo API token with write:repository scope
|
||||
# MIRROR_TOKEN — GitHub personal access token with repo scope (already used by mirror.yml)
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: ['v*']
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Git tag to build (e.g. v0.4.0)'
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
release-iso:
|
||||
runs-on: [self-hosted, hestia]
|
||||
container:
|
||||
image: archlinux:latest
|
||||
# --privileged: mkarchiso needs CAP_SYS_ADMIN for loop mounts + mknod
|
||||
# --network=host: gives localhost:3002 access to Forgejo (avoids the
|
||||
# public git.breadway.dev → Aegis → Tailscale round-trip for pacman)
|
||||
options: --privileged --network=host
|
||||
|
||||
steps:
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
pacman -Syu --noconfirm archiso curl python git rust
|
||||
|
||||
- name: Determine tag and version
|
||||
id: vars
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
TAG="${{ github.event.inputs.tag }}"
|
||||
else
|
||||
TAG="${{ github.ref_name }}"
|
||||
fi
|
||||
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
||||
echo "version=${TAG#v}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Clone repository at tag
|
||||
run: |
|
||||
git clone --branch "${{ steps.vars.outputs.tag }}" --depth 1 \
|
||||
"https://git.breadway.dev/${GITHUB_REPOSITORY}.git" /bos
|
||||
|
||||
- name: Download bakery ecosystem binaries
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p /build-home/.local/bin \
|
||||
/build-home/.local/state/bakery \
|
||||
/build-home/.cache/bakery
|
||||
|
||||
# Fetch the canonical bakery index
|
||||
curl -fsSL "https://dl.breadway.dev/index.json" \
|
||||
-o /build-home/.cache/bakery/index.json
|
||||
|
||||
# Download each binary from dl.breadway.dev (canonical source; github_url
|
||||
# is not always published for dev/patch releases) and generate the
|
||||
# installed.json that bakery expects in ~/.local/state.
|
||||
python3 << 'PYEOF'
|
||||
import json, urllib.request, os
|
||||
|
||||
with open('/build-home/.cache/bakery/index.json') as f:
|
||||
idx = json.load(f)
|
||||
|
||||
BIN_DIR = '/build-home/.local/bin'
|
||||
installed = {}
|
||||
|
||||
for pkg_name, pkg in idx['packages'].items():
|
||||
bins = []
|
||||
for b in pkg['binaries']:
|
||||
dest_name = b['name'].removesuffix('-x86_64')
|
||||
dest = os.path.join(BIN_DIR, dest_name)
|
||||
url = b['dl_url']
|
||||
print(f' {dest_name} <- {url}', flush=True)
|
||||
urllib.request.urlretrieve(url, dest)
|
||||
os.chmod(dest, 0o755)
|
||||
bins.append(dest_name)
|
||||
|
||||
# installed.json services field is a flat list of unit-name strings
|
||||
services = [
|
||||
(s['unit'] if isinstance(s, dict) else s)
|
||||
for s in pkg.get('services', [])
|
||||
]
|
||||
installed[pkg_name] = {
|
||||
'name': pkg_name,
|
||||
'version': pkg['version'],
|
||||
'binaries': bins,
|
||||
'services': services,
|
||||
'installed_at': '2024-01-01T00:00:00+00:00',
|
||||
}
|
||||
|
||||
with open('/build-home/.local/state/bakery/installed.json', 'w') as f:
|
||||
json.dump({'packages': installed}, f, indent=2)
|
||||
print('installed.json written', flush=True)
|
||||
PYEOF
|
||||
|
||||
- name: Build bread-theme from source
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# bread-theme is not in the bakery index; build it at the tag pinned
|
||||
# in bos-settings/Cargo.toml so the CLI matches the library version.
|
||||
THEME_TAG=$(grep 'bread-theme.*tag' /bos/bos-settings/Cargo.toml \
|
||||
| grep -oP '"v[^"]+"' | tr -d '"')
|
||||
echo "Building bread-theme @ $THEME_TAG"
|
||||
git clone --branch "$THEME_TAG" --depth 1 \
|
||||
https://github.com/Breadway/bread-ecosystem /bread-ecosystem
|
||||
cd /bread-ecosystem
|
||||
cargo build --release -p bread-theme
|
||||
install -m 755 target/release/bread-theme /build-home/.local/bin/bread-theme
|
||||
echo "bread-theme built OK"
|
||||
|
||||
- name: Build ISO
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir -p /bos-work /bos-out
|
||||
cd /bos
|
||||
LAPTOP_HOME=/build-home \
|
||||
WORK=/bos-work \
|
||||
OUT=/bos-out \
|
||||
CI_BUILD=1 \
|
||||
bash build-local.sh
|
||||
ls -lh /bos-out/*.iso
|
||||
|
||||
- name: Create Forgejo release and upload ISO
|
||||
env:
|
||||
FORGEJO_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TAG="${{ steps.vars.outputs.tag }}"
|
||||
VERSION="${{ steps.vars.outputs.version }}"
|
||||
ISO=$(ls /bos-out/*.iso | head -1)
|
||||
ISO_NAME="bos-${VERSION}-x86_64.iso"
|
||||
|
||||
# Use an existing release for this tag if one exists (e.g. created
|
||||
# manually or by a prior re-run), otherwise create a fresh one.
|
||||
EXISTING=$(curl -sf \
|
||||
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
||||
"http://localhost:3002/api/v1/repos/${GITHUB_REPOSITORY}/releases/tags/${TAG}" \
|
||||
2>/dev/null || true)
|
||||
RELEASE_ID=$(echo "${EXISTING}" | python3 -c \
|
||||
"import json,sys; d=json.load(sys.stdin); print(d.get('id',''))" 2>/dev/null || true)
|
||||
|
||||
if [ -z "${RELEASE_ID}" ]; then
|
||||
RELEASE=$(curl -fsS -X POST \
|
||||
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
||||
-H "Content-Type: application/json" \
|
||||
"http://localhost:3002/api/v1/repos/${GITHUB_REPOSITORY}/releases" \
|
||||
-d "{
|
||||
\"tag_name\": \"${TAG}\",
|
||||
\"name\": \"BOS ${TAG}\",
|
||||
\"prerelease\": false,
|
||||
\"body\": \"ISO image attached below.\\n\\nSee the [README](https://github.com/Breadway/bos#testing-in-a-vm) for VM testing instructions.\"
|
||||
}")
|
||||
RELEASE_ID=$(echo "${RELEASE}" | python3 -c "import json,sys; print(json.load(sys.stdin)['id'])")
|
||||
fi
|
||||
echo "Using release ID: ${RELEASE_ID}"
|
||||
|
||||
# Remove any existing asset with the same name before uploading
|
||||
ASSET_ID=$(curl -sf \
|
||||
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
||||
"http://localhost:3002/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets" \
|
||||
| python3 -c "
|
||||
import json,sys
|
||||
assets=json.load(sys.stdin)
|
||||
match=[a['id'] for a in assets if a['name']=='${ISO_NAME}']
|
||||
print(match[0] if match else '')
|
||||
" 2>/dev/null || true)
|
||||
|
||||
if [ -n "${ASSET_ID}" ]; then
|
||||
curl -fsS -X DELETE \
|
||||
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
||||
"http://localhost:3002/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets/${ASSET_ID}"
|
||||
echo "Removed existing ${ISO_NAME} asset"
|
||||
fi
|
||||
|
||||
curl -fsS -X POST \
|
||||
-H "Authorization: token ${FORGEJO_TOKEN}" \
|
||||
-F "attachment=@${ISO};filename=${ISO_NAME}" \
|
||||
"http://localhost:3002/api/v1/repos/${GITHUB_REPOSITORY}/releases/${RELEASE_ID}/assets"
|
||||
echo "Uploaded: ${ISO_NAME}"
|
||||
|
||||
- name: Create GitHub release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.MIRROR_TOKEN }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TAG="${{ steps.vars.outputs.tag }}"
|
||||
VERSION="${{ steps.vars.outputs.version }}"
|
||||
FORGEJO_URL="https://git.breadway.dev/${GITHUB_REPOSITORY}/releases/tag/${TAG}"
|
||||
|
||||
printf '**Download ISO:** %s\n\nGitHub releases cannot host files >2 GB; the `bos-%s-x86_64.iso` (~2.5 GB) is on Forgejo.\n\nSee the [README](https://github.com/Breadway/bos#testing-in-a-vm) for VM testing instructions.' \
|
||||
"${FORGEJO_URL}" "${VERSION}" > /tmp/gh-release-notes.md
|
||||
|
||||
gh release create "${TAG}" \
|
||||
--repo "Breadway/bos" \
|
||||
--title "BOS ${TAG}" \
|
||||
\
|
||||
--notes-file /tmp/gh-release-notes.md \
|
||||
2>/dev/null || echo "GitHub release already exists — skipping"
|
||||
1
.gitignore
vendored
|
|
@ -27,7 +27,6 @@ secrets/
|
|||
# archiso build artifacts (these are large and reproducible)
|
||||
/iso-build/
|
||||
/iso-out/
|
||||
/out/
|
||||
*.iso
|
||||
*.img
|
||||
|
||||
|
|
|
|||
273
Cargo.lock
generated
|
|
@ -28,10 +28,9 @@ checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
|||
|
||||
[[package]]
|
||||
name = "bos-settings"
|
||||
version = "0.4.0"
|
||||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"bread-theme",
|
||||
"glib",
|
||||
"gtk4",
|
||||
"serde",
|
||||
|
|
@ -40,22 +39,11 @@ dependencies = [
|
|||
"toml_edit 0.22.27",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bread-theme"
|
||||
version = "0.2.3"
|
||||
source = "git+https://github.com/Breadway/bread-ecosystem?tag=v0.2.8#77417d552130281ff787e07d52541eb25e9d533b"
|
||||
dependencies = [
|
||||
"dirs",
|
||||
"gtk4",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cairo-rs"
|
||||
version = "0.22.0"
|
||||
version = "0.20.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cc8d9aa793480744cd9a0524fef1a2e197d9eaa0f739cde19d16aba530dcb95"
|
||||
checksum = "91e3bd0f4e25afa9cabc157908d14eeef9067d6448c49414d17b3fb55f0eadd0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cairo-sys-rs",
|
||||
|
|
@ -65,9 +53,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cairo-sys-rs"
|
||||
version = "0.22.0"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8b4985713047f5faee02b8db6a6ef32bbb50269ff53c1aee716d1d195b76d54"
|
||||
checksum = "059cc746549898cbfd9a47754288e5a958756650ef4652bbb6c5f71a6bda4f8b"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"libc",
|
||||
|
|
@ -84,12 +72,6 @@ dependencies = [
|
|||
"target-lexicon",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "2.5.0"
|
||||
|
|
@ -105,27 +87,6 @@ version = "0.8.21"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "5.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"option-ext",
|
||||
"redox_users",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "equivalent"
|
||||
version = "1.0.2"
|
||||
|
|
@ -227,9 +188,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gdk-pixbuf"
|
||||
version = "0.22.0"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25f420376dbee041b2db374ce4573892a36222bb3f6c0c43e24f0d67eae9b646"
|
||||
checksum = "2fd242894c084f4beed508a56952750bce3e96e85eb68fdc153637daa163e10c"
|
||||
dependencies = [
|
||||
"gdk-pixbuf-sys",
|
||||
"gio",
|
||||
|
|
@ -239,9 +200,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gdk-pixbuf-sys"
|
||||
version = "0.22.0"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48f31b37b1fc4b48b54f6b91b7ef04c18e00b4585d98359dd7b998774bbd91fb"
|
||||
checksum = "5b34f3b580c988bd217e9543a2de59823fafae369d1a055555e5f95a8b130b96"
|
||||
dependencies = [
|
||||
"gio-sys",
|
||||
"glib-sys",
|
||||
|
|
@ -252,9 +213,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gdk4"
|
||||
version = "0.11.2"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd42fdbbf48612c6e8f47c65fb92d2e8f39c25aecd6af047e83897c1a22d2a4e"
|
||||
checksum = "4850c9d9c1aecd1a3eb14fadc1cdb0ac0a2298037e116264c7473e1740a32d60"
|
||||
dependencies = [
|
||||
"cairo-rs",
|
||||
"gdk-pixbuf",
|
||||
|
|
@ -267,9 +228,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gdk4-sys"
|
||||
version = "0.11.2"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d974ac4f15e67472c3a9728daf612590b4a5762a4b33f0edd298df0b80d043c"
|
||||
checksum = "6f6eb95798e2b46f279cf59005daf297d5b69555428f185650d71974a910473a"
|
||||
dependencies = [
|
||||
"cairo-sys-rs",
|
||||
"gdk-pixbuf-sys",
|
||||
|
|
@ -282,22 +243,11 @@ dependencies = [
|
|||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gio"
|
||||
version = "0.22.6"
|
||||
version = "0.20.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3848bcba3a35cc0a71df8ba8ecfd799d6bfb862342a53a4a915fb62213aa4e6"
|
||||
checksum = "8e27e276e7b6b8d50f6376ee7769a71133e80d093bdc363bd0af71664228b831"
|
||||
dependencies = [
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
|
|
@ -312,22 +262,22 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gio-sys"
|
||||
version = "0.22.0"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64729ba2772c080448f9f966dba8f4456beeb100d8c28a865ef8a0f2ef4987e1"
|
||||
checksum = "521e93a7e56fc89e84aea9a52cfc9436816a4b363b030260b699950ff1336c83"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
"libc",
|
||||
"system-deps",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glib"
|
||||
version = "0.22.7"
|
||||
version = "0.20.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c207e04e51605dcf7b2924c41591b3a10e1438eaac5bcf448fb91f325381104a"
|
||||
checksum = "ffc4b6e352d4716d84d7dde562dd9aee2a7d48beb872dd9ece7f2d1515b2d683"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"futures-channel",
|
||||
|
|
@ -346,11 +296,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "glib-macros"
|
||||
version = "0.22.6"
|
||||
version = "0.20.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "506d23499707c7142898429757e8d9a3871d965239a2cb66dfa05052be6d6f19"
|
||||
checksum = "e8084af62f09475a3f529b1629c10c429d7600ee1398ae12dd3bf175d74e7145"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
|
|
@ -358,9 +309,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "glib-sys"
|
||||
version = "0.22.6"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f7fbac234ed5bc2a28359b7bde8e1b9cdf1441cc2d7f068e4824672d7db9445"
|
||||
checksum = "8ab79e1ed126803a8fb827e3de0e2ff95191912b8db65cee467edb56fc4cc215"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"system-deps",
|
||||
|
|
@ -368,9 +319,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gobject-sys"
|
||||
version = "0.22.6"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22a861859b887a79cf461359c192c97a57d8fb0229dd291232e57aa11f6fa72c"
|
||||
checksum = "ec9aca94bb73989e3cfdbf8f2e0f1f6da04db4d291c431f444838925c4c63eda"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"libc",
|
||||
|
|
@ -379,9 +330,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "graphene-rs"
|
||||
version = "0.22.0"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7d1b7881f96869f49808b6adfe906a93a57a34204952253444d68c3208d71f1"
|
||||
checksum = "6b86dfad7d14251c9acaf1de63bc8754b7e3b4e5b16777b6f5a748208fe9519b"
|
||||
dependencies = [
|
||||
"glib",
|
||||
"graphene-sys",
|
||||
|
|
@ -390,9 +341,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "graphene-sys"
|
||||
version = "0.22.0"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "517f062f3fd6b7fd3e57a3f038a74b3c23ca32f51199ff028aa704609943f79c"
|
||||
checksum = "df583a85ba2d5e15e1797e40d666057b28bc2f60a67c9c24145e6db2cc3861ea"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"libc",
|
||||
|
|
@ -402,9 +353,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gsk4"
|
||||
version = "0.11.1"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53c912dfcbd28acace5fc99c40bb9f25e1dcb73efb1f2608327f66a99acdcb62"
|
||||
checksum = "61f5e72f931c8c9f65fbfc89fe0ddc7746f147f822f127a53a9854666ac1f855"
|
||||
dependencies = [
|
||||
"cairo-rs",
|
||||
"gdk4",
|
||||
|
|
@ -417,9 +368,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gsk4-sys"
|
||||
version = "0.11.1"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7d54bbc7a9d8b6ffe4f0c95eede15ccfb365c8bf521275abe6bcfb57b18fb8a"
|
||||
checksum = "755059de55fa6f85a46bde8caf03e2184c96bfda1f6206163c72fb0ea12436dc"
|
||||
dependencies = [
|
||||
"cairo-sys-rs",
|
||||
"gdk4-sys",
|
||||
|
|
@ -433,9 +384,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gtk4"
|
||||
version = "0.11.3"
|
||||
version = "0.9.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7181b837f04cbe93f79441475f7a00560a92cba7a72e38cc1a68b6f8b78eaae2"
|
||||
checksum = "f274dd0102c21c47bbfa8ebcb92d0464fab794a22fad6c3f3d5f165139a326d6"
|
||||
dependencies = [
|
||||
"cairo-rs",
|
||||
"field-offset",
|
||||
|
|
@ -454,9 +405,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gtk4-macros"
|
||||
version = "0.11.0"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3581b242ba62fdff122ebb626ea641582ec326031622bd19d60f85029c804a87"
|
||||
checksum = "0ed1786c4703dd196baf7e103525ce0cf579b3a63a0570fe653b7ee6bac33999"
|
||||
dependencies = [
|
||||
"proc-macro-crate",
|
||||
"proc-macro2",
|
||||
|
|
@ -466,9 +417,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gtk4-sys"
|
||||
version = "0.11.3"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20ba8e695e2640455561274e65e45f0a151619e450746007667f4b23ceae4e1b"
|
||||
checksum = "41e03b01e54d77c310e1d98647d73f996d04b2f29b9121fe493ea525a7ec03d6"
|
||||
dependencies = [
|
||||
"cairo-sys-rs",
|
||||
"gdk-pixbuf-sys",
|
||||
|
|
@ -517,15 +468,6 @@ version = "0.2.186"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.2"
|
||||
|
|
@ -541,17 +483,11 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "option-ext"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "pango"
|
||||
version = "0.22.6"
|
||||
version = "0.20.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "251bdc6e6487b811be0e406a21e301e07e45c0aa8fa39e00c0c8e12a91752438"
|
||||
checksum = "6576b311f6df659397043a5fa8a021da8f72e34af180b44f7d57348de691ab5c"
|
||||
dependencies = [
|
||||
"gio",
|
||||
"glib",
|
||||
|
|
@ -561,9 +497,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pango-sys"
|
||||
version = "0.22.0"
|
||||
version = "0.20.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd111a20ca90fedf03e09c59783c679c00900f1d8491cca5399f5e33609d5d6"
|
||||
checksum = "186909673fc09be354555c302c0b3dcf753cd9fa08dcb8077fa663c80fb243fa"
|
||||
dependencies = [
|
||||
"glib-sys",
|
||||
"gobject-sys",
|
||||
|
|
@ -616,17 +552,6 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_users"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"libredox",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.1"
|
||||
|
|
@ -745,26 +670,6 @@ version = "0.13.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.23"
|
||||
|
|
@ -869,43 +774,13 @@ version = "0.2.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
||||
dependencies = [
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -914,46 +789,28 @@ version = "0.52.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.6",
|
||||
"windows_aarch64_msvc 0.52.6",
|
||||
"windows_i686_gnu 0.52.6",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc 0.52.6",
|
||||
"windows_x86_64_gnu 0.52.6",
|
||||
"windows_x86_64_gnullvm 0.52.6",
|
||||
"windows_x86_64_msvc 0.52.6",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
|
|
@ -966,48 +823,24 @@ version = "0.52.6"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
|
|
|
|||
209
README.md
|
|
@ -1,209 +0,0 @@
|
|||
# BOS — Bread Operating System
|
||||
|
||||
An Arch-based, Hyprland desktop distribution that ships the [bread
|
||||
ecosystem](https://github.com/Breadway) 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](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/skel` from 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 the `bakery` package manager.
|
||||
- **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 + tuigreet → Hyprland session.
|
||||
- **Boot splash**: Plymouth `bos` theme (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`.
|
||||
- **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).
|
||||
|
||||
## 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`:
|
||||
|
||||
```sh
|
||||
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`, and `bibata-cursor-theme` 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.
|
||||
|
||||
## Testing in a VM
|
||||
|
||||
A reusable, GPU-accelerated launcher lives at `~/bos-vm/run.sh`:
|
||||
|
||||
```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
|
||||
|
||||
`bos-settings` edits each bread\* app's TOML **non-destructively**: it parses
|
||||
the file with `toml_edit`, 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). Views:
|
||||
|
||||
| View | Config |
|
||||
|------|--------|
|
||||
| bread | `bread/breadd.toml` — daemon, lua, modules, all adapters, events, notifications |
|
||||
| breadbar | `breadbar/style.css` override |
|
||||
| breadbox | `breadbox/config.toml` — launcher contexts |
|
||||
| breadcrumbs | `breadcrumbs/breadcrumbs.toml` — settings, saved networks, profiles |
|
||||
| breadpad | `breadpad/breadpad.toml` — settings, model + ollama, reminders, calendar |
|
||||
| Snapshots | `snapper` list / rollback / delete |
|
||||
| Packages | `bakery` installed list + updates |
|
||||
| Hyprland | open config in editor + monitor list |
|
||||
|
||||
Build standalone:
|
||||
|
||||
```sh
|
||||
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-utils` and 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**: not configured. Boot with Secure Boot disabled, or enroll
|
||||
your own keys. The installer writes both an NVRAM entry and the removable
|
||||
`EFI/BOOT/BOOTX64.EFI` fallback.
|
||||
- **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):**
|
||||
|
||||
1. Boot the BOS ISO and open a terminal (`SUPER+Return`).
|
||||
2. Mount the installed root and EFI, then chroot:
|
||||
```sh
|
||||
mount -o subvol=@ /dev/sdXN /mnt
|
||||
mount /dev/sdXP /mnt/boot/efi # the EFI partition
|
||||
arch-chroot /mnt
|
||||
```
|
||||
3. Reinstall the bootloader (the same sequence the installer uses):
|
||||
```sh
|
||||
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.
|
||||
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
|
@ -1,14 +1,11 @@
|
|||
[package]
|
||||
name = "bos-settings"
|
||||
version = "0.4.0"
|
||||
version = "0.2.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
gtk4 = { version = "0.11", features = ["v4_12"] }
|
||||
glib = "0.22"
|
||||
# Shared ecosystem theming — bos-settings loads the same generated stylesheet as
|
||||
# breadbar/breadbox/breadpad so the whole desktop looks consistent.
|
||||
bread-theme = { git = "https://github.com/Breadway/bread-ecosystem", tag = "v0.2.8", features = ["gtk"] }
|
||||
gtk4 = { version = "0.9", features = ["v4_12"] }
|
||||
glib = "0.20"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
toml = "0.8"
|
||||
|
|
|
|||
|
|
@ -1,30 +1,87 @@
|
|||
//! Theming for bos-settings.
|
||||
//!
|
||||
//! bos-settings deliberately owns almost no styling: it loads the ecosystem's
|
||||
//! shared stylesheet (the same one breadbar/breadbox/breadpad use, generated by
|
||||
//! `bread-theme` from the pywal palette) and adds only the few layout rules
|
||||
//! specific to this app's sidebar + content shell. This keeps it visually
|
||||
//! identical to the rest of the bread desktop and live-recolouring for free.
|
||||
|
||||
use gtk4::CssProvider;
|
||||
use std::cell::RefCell;
|
||||
|
||||
// App-specific layout only — everything visual (colours, buttons, entries,
|
||||
// switches, sidebar/row styling, cards, scrollbars) comes from the shared sheet.
|
||||
const APP_CSS: &str = "\
|
||||
.view-content { padding: 24px; }\n\
|
||||
.view-content > label.title { margin-bottom: 16px; }\n\
|
||||
";
|
||||
|
||||
thread_local! {
|
||||
static APP_PROVIDER: RefCell<Option<CssProvider>> = const { RefCell::new(None) };
|
||||
const CSS: &str = r#"
|
||||
window {
|
||||
background-color: #2e3440;
|
||||
color: #eceff4;
|
||||
}
|
||||
|
||||
pub fn load(_display: >k4::gdk::Display) {
|
||||
// Shared ecosystem stylesheet (loads the generated file or a rendered
|
||||
// fallback, and live-reloads when the palette changes).
|
||||
bread_theme::gtk::apply_shared();
|
||||
|
||||
// bos-settings layout, layered on top at APPLICATION priority.
|
||||
APP_PROVIDER.with(|cell| bread_theme::gtk::apply_css(APP_CSS, cell));
|
||||
.sidebar {
|
||||
background-color: #3b4252;
|
||||
border-right: 1px solid #434c5e;
|
||||
}
|
||||
|
||||
.sidebar row {
|
||||
padding: 8px 12px;
|
||||
color: #d8dee9;
|
||||
}
|
||||
|
||||
.sidebar row:selected {
|
||||
background-color: #5e81ac;
|
||||
color: #eceff4;
|
||||
}
|
||||
|
||||
.sidebar .section-header {
|
||||
padding: 12px 12px 4px 12px;
|
||||
font-size: 0.75em;
|
||||
font-weight: bold;
|
||||
color: #616e88;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.view-content {
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
.view-content label.title {
|
||||
font-size: 1.4em;
|
||||
font-weight: bold;
|
||||
color: #eceff4;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
button {
|
||||
background-color: #5e81ac;
|
||||
color: #eceff4;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
padding: 6px 16px;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-color: #81a1c1;
|
||||
}
|
||||
|
||||
button.destructive-action {
|
||||
background-color: #bf616a;
|
||||
}
|
||||
|
||||
button.destructive-action:hover {
|
||||
background-color: #d08770;
|
||||
}
|
||||
|
||||
entry {
|
||||
background-color: #434c5e;
|
||||
color: #eceff4;
|
||||
border: 1px solid #4c566a;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
textview {
|
||||
background-color: #272c36;
|
||||
color: #a3be8c;
|
||||
font-family: monospace;
|
||||
padding: 8px;
|
||||
}
|
||||
"#;
|
||||
|
||||
pub fn load(display: >k4::gdk::Display) {
|
||||
let provider = CssProvider::new();
|
||||
provider.load_from_string(CSS);
|
||||
gtk4::style_context_add_provider_for_display(
|
||||
display,
|
||||
&provider,
|
||||
gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ fn css_path() -> PathBuf {
|
|||
crate::config::config_dir().join("breadbar/style.css")
|
||||
}
|
||||
|
||||
|
||||
pub fn build() -> GBox {
|
||||
let path = css_path();
|
||||
let existing_css = std::fs::read_to_string(&path).unwrap_or_default();
|
||||
|
|
|
|||
|
|
@ -50,10 +50,9 @@ fn stream_command(args: &[&str], log_buf: gtk4::TextBuffer) {
|
|||
}
|
||||
};
|
||||
|
||||
// Merge stderr into the channel too.
|
||||
// Both are Some because we spawned with Stdio::piped() above.
|
||||
let stdout = child.stdout.take().expect("stdout piped");
|
||||
let stderr = child.stderr.take().expect("stderr piped");
|
||||
// Merge stderr into the channel too
|
||||
let stdout = child.stdout.take().unwrap();
|
||||
let stderr = child.stderr.take().unwrap();
|
||||
|
||||
let tx2 = sender.clone();
|
||||
std::thread::spawn(move || {
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 4 KiB After Width: | Height: | Size: 4 KiB |
|
|
@ -14,10 +14,7 @@
|
|||
set -euo pipefail
|
||||
|
||||
REPO="$(cd "$(dirname "$0")" && pwd)"
|
||||
# WORK defaults to /tmp, but on hermes /tmp is a 16 GB tmpfs — a full xz build
|
||||
# (uncompressed rootfs + squashfs + work copies) can exhaust it mid-build. Allow
|
||||
# pointing it at the NVMe instead: WORK=/home/.../bos-work sudo ./build-local.sh
|
||||
WORK="${WORK:-/tmp/bos-work}"
|
||||
WORK=/tmp/bos-work
|
||||
OUT="${OUT:-$REPO/out}"
|
||||
|
||||
# Build against a throwaway copy of the profile so the working tree stays clean
|
||||
|
|
@ -25,15 +22,10 @@ OUT="${OUT:-$REPO/out}"
|
|||
STAGE=/tmp/bos-iso-stage
|
||||
rm -rf "$STAGE" && cp -a "$REPO/iso" "$STAGE"
|
||||
|
||||
# Rewrite the [breadway] pacman repo URL to the fastest reachable address.
|
||||
# CI_BUILD=1 — container runs on hestia with --network=host; localhost:3002 is direct
|
||||
# default — building on hermes; git.breadway.dev is flaky from there, use Tailscale
|
||||
# Only ever rewrites the staged copy, never the committed pacman.conf.
|
||||
if [ "${CI_BUILD:-0}" = "1" ]; then
|
||||
sed -i 's#https://git.breadway.dev/api/packages/Breadway/arch/os#http://localhost:3002/api/packages/Breadway/arch/os#' "$STAGE/pacman.conf"
|
||||
else
|
||||
# The public git.breadway.dev URL is flaky/unreachable from hermes; Forgejo is
|
||||
# directly reachable over Tailscale (hestia 100.66.238.26:3002). Only rewrites
|
||||
# the staged copy, never the committed pacman.conf.
|
||||
sed -i 's#https://git.breadway.dev/api/packages/Breadway/arch/os#http://100.66.238.26:3002/api/packages/Breadway/arch/os#' "$STAGE/pacman.conf"
|
||||
fi
|
||||
|
||||
if [ "${FAST_BUILD:-0}" = "1" ]; then
|
||||
echo "=== FAST_BUILD: squashfs -> zstd level 6 ==="
|
||||
|
|
@ -49,7 +41,7 @@ grep airootfs_image_tool_options "$STAGE/profiledef.sh"
|
|||
# created from skel (the live user and the installed user) then gets the same
|
||||
# versions `bakery list` reports here, fully offline. Copied at build time so the
|
||||
# binaries never bloat the git repo and always track the current bakery state.
|
||||
BREAD_BINS=(bakery bread breadd breadman breadbar breadbox breadbox-sync breadcrumbs breadpad breadpaper bread-theme)
|
||||
BREAD_BINS=(bakery bread breadd breadman breadbar breadbox breadbox-sync breadcrumbs breadpad)
|
||||
LAPTOP_HOME="${LAPTOP_HOME:-$(getent passwd "${SUDO_USER:-$USER}" | cut -d: -f6)}"
|
||||
BAKERY_BIN="$LAPTOP_HOME/.local/bin"
|
||||
BAKERY_STATE="$LAPTOP_HOME/.local/state/bakery"
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 9 KiB |
|
|
@ -24,46 +24,23 @@ userdel -r liveuser 2>/dev/null || true
|
|||
passwd -l root || true
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Pacman keyring. The live medium's /etc/pacman.d/gnupg doesn't reliably carry
|
||||
# over to the target (unpackfs may skip it / perms differ), leaving the installed
|
||||
# system unable to verify package signatures — the first `pacman -Syu` then dies
|
||||
# with "keyring is not writable / required key missing". Initialise it here so a
|
||||
# fresh install can update out of the box. archlinux-keyring is already present;
|
||||
# [breadway] is SigLevel=Never so it needs no key.
|
||||
# Boot splash (Plymouth) — BOS logo + spinner instead of kernel text. Done
|
||||
# BEFORE grub so grub.cfg picks up the new cmdline and the rebuilt initramfs.
|
||||
# All best-effort: if anything here fails the system still boots (just without
|
||||
# the splash) — the initramfs the initcpio module already built stays valid.
|
||||
# ---------------------------------------------------------------------------
|
||||
if command -v pacman-key &>/dev/null; then
|
||||
pacman-key --init || echo "WARN: pacman-key --init failed"
|
||||
pacman-key --populate archlinux || echo "WARN: pacman-key --populate failed"
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Initramfs HOOKS: microcode + plymouth. Edit HOOKS first, rebuild once below.
|
||||
# microcode — embeds the (autodetect-pruned) CPU microcode into the initramfs
|
||||
# so it loads at early boot. The live ISO embeds ucode the same way, so the
|
||||
# ISO /boot carries no separate ucode image and bos-copy-kernel stages none
|
||||
# onto the target — the installed initramfs must therefore carry it itself.
|
||||
# Must sit AFTER `autodetect` so it's pruned to the running CPU's microcode.
|
||||
# plymouth — the BOS boot splash. Only the udev `plymouth` hook exists (there
|
||||
# is NO `sd-plymouth`), so always insert it after `udev`.
|
||||
# All best-effort: a failure here still leaves a bootable initramfs.
|
||||
# ---------------------------------------------------------------------------
|
||||
if [[ -f /etc/mkinitcpio.conf ]]; then
|
||||
if ! grep -qE '^HOOKS=.*\bmicrocode\b' /etc/mkinitcpio.conf; then
|
||||
sed -i 's/^\(HOOKS=.*\bautodetect\b\)/\1 microcode/' /etc/mkinitcpio.conf \
|
||||
|| echo "WARN: adding microcode hook failed"
|
||||
fi
|
||||
if command -v plymouth-set-default-theme &>/dev/null \
|
||||
&& ! grep -qE '^HOOKS=.*\bplymouth\b' /etc/mkinitcpio.conf; then
|
||||
if command -v plymouth-set-default-theme &>/dev/null; then
|
||||
# Ensure the plymouth hook is in HOOKS (plymouthcfg/initcpiocfg usually add it;
|
||||
# this is the belt). Handle both the udev and systemd initramfs styles.
|
||||
if ! grep -q 'plymouth' /etc/mkinitcpio.conf 2>/dev/null; then
|
||||
if grep -qE '^HOOKS=.*\bsystemd\b' /etc/mkinitcpio.conf; then
|
||||
sed -i 's/^\(HOOKS=.*\bsystemd\b\)/\1 sd-plymouth/' /etc/mkinitcpio.conf \
|
||||
|| echo "WARN: adding sd-plymouth hook failed"
|
||||
else
|
||||
sed -i 's/^\(HOOKS=.*\budev\b\)/\1 plymouth/' /etc/mkinitcpio.conf \
|
||||
|| echo "WARN: adding plymouth hook failed"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Boot splash (Plymouth) — BOS logo + spinner instead of kernel text. Set the
|
||||
# theme + cmdline BEFORE grub so grub.cfg picks up the new cmdline.
|
||||
# ---------------------------------------------------------------------------
|
||||
if command -v plymouth-set-default-theme &>/dev/null; then
|
||||
# Clean boot: splash activates plymouth; hiding systemd status removes the
|
||||
# "[ OK ] Started ..." text (what looked like kernel output) even if the
|
||||
# splash itself doesn't grab the display (e.g. in some VMs).
|
||||
|
|
@ -71,13 +48,10 @@ if command -v plymouth-set-default-theme &>/dev/null; then
|
|||
sed -i 's/^\(GRUB_CMDLINE_LINUX_DEFAULT="\)/\1splash quiet vt.global_cursor_default=0 systemd.show_status=false rd.systemd.show_status=false rd.udev.log_level=3 /' \
|
||||
/etc/default/grub || echo "WARN: adding splash cmdline failed"
|
||||
fi
|
||||
plymouth-set-default-theme bos || echo "WARN: plymouth-set-default-theme failed"
|
||||
# Set the BOS theme and rebuild the initramfs (-R) with the plymouth hook.
|
||||
plymouth-set-default-theme -R bos || echo "WARN: plymouth-set-default-theme failed"
|
||||
fi
|
||||
|
||||
# Rebuild every preset (default + fallback that bos-copy-kernel wrote) so the
|
||||
# microcode + plymouth HOOKS above are actually baked into the initramfs.
|
||||
mkinitcpio -P || echo "WARN: mkinitcpio -P failed"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Install GRUB (UEFI). /boot now has the kernel + initramfs, and the mount
|
||||
# module has bind-mounted /proc /sys /dev /run + efivars into this chroot, so
|
||||
|
|
@ -126,33 +100,11 @@ fi
|
|||
# ---------------------------------------------------------------------------
|
||||
for unit in NetworkManager.service bluetooth.service systemd-timesyncd.service \
|
||||
tlp.service greetd.service snapper-cleanup.timer grub-btrfsd.service \
|
||||
fstrim.timer cups.socket avahi-daemon.service ufw.service \
|
||||
fwupd-refresh.timer reflector.timer; do
|
||||
fstrim.timer cups.socket; do
|
||||
systemctl enable "$unit" || echo "WARN: failed to enable $unit"
|
||||
done
|
||||
systemctl set-default graphical.target || echo "WARN: set-default graphical failed"
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# mDNS resolution (nss-mdns): insert mdns_minimal into the hosts: line so the
|
||||
# resolver answers *.local (network printers, other hosts) via avahi. Idempotent.
|
||||
# ---------------------------------------------------------------------------
|
||||
if [[ -f /etc/nsswitch.conf ]] && ! grep -q 'mdns_minimal' /etc/nsswitch.conf; then
|
||||
sed -i 's/^\(hosts:[[:space:]]*\)/\1mdns_minimal [NOTFOUND=return] /' \
|
||||
/etc/nsswitch.conf || echo "WARN: wiring nss-mdns failed"
|
||||
fi
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Firewall: deny inbound by default, allow outbound, and permit inbound mDNS so
|
||||
# avahi printer/service discovery keeps working. Best-effort — rule application
|
||||
# happens at boot; here we only persist the policy + enable the unit.
|
||||
# ---------------------------------------------------------------------------
|
||||
if command -v ufw &>/dev/null; then
|
||||
ufw default deny incoming || echo "WARN: ufw default deny incoming failed"
|
||||
ufw default allow outgoing || echo "WARN: ufw default allow outgoing failed"
|
||||
ufw allow 5353/udp || echo "WARN: ufw allow mDNS failed"
|
||||
ufw --force enable || echo "WARN: ufw enable failed"
|
||||
fi
|
||||
|
||||
# The bread ecosystem (bakery + bread, breadbar, breadbox, breadcrumbs, breadpad)
|
||||
# is bakery-managed, not pacman: the binaries and bakery manifest live in
|
||||
# /etc/skel/.local (baked in at ISO build time) and are copied into the user's
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
SHELL=/usr/bin/zsh
|
||||
GROUP=users
|
||||
HOME=/home
|
||||
INACTIVE=-1
|
||||
EXPIRE=
|
||||
SKEL=/etc/skel
|
||||
CREATE_MAIL_SPOOL=no
|
||||
|
|
@ -35,8 +35,7 @@ Include = /etc/pacman.d/mirrorlist
|
|||
#
|
||||
# Forgejo signs the repo db with a key pacman can't look up, so TrustAll
|
||||
# fails. SigLevel = Never skips verification (acceptable for this private
|
||||
# repo over TLS). Future improvement: import Forgejo's signing key and
|
||||
# switch to SigLevel = Required for full package verification.
|
||||
# repo over TLS). TODO: import Forgejo's signing key + SigLevel = Required.
|
||||
# -----------------------------------------------------------------------
|
||||
# The section name must match Forgejo's served db filename
|
||||
# ({owner}.{group}.{domain}.db) — pacman fetches "<section>.db" from Server.
|
||||
|
|
|
|||
|
|
@ -1,26 +0,0 @@
|
|||
-- low-battery-warning — notify once when the battery runs low (zero-config).
|
||||
-- Shipped active in BOS; auto-discovered by breadd. Safe on desktops too
|
||||
-- (simply never fires without a battery).
|
||||
|
||||
local M = bread.module({ name = "low-battery-warning", version = "1.0.0" })
|
||||
|
||||
local warned = false
|
||||
|
||||
function M.on_load()
|
||||
bread.on("bread.power.battery.low", function(event)
|
||||
if warned then return end
|
||||
warned = true
|
||||
local pct = event.data.battery_percent or "?"
|
||||
bread.notify("Battery low (" .. pct .. "%). Plug in soon.", {
|
||||
urgency = "critical",
|
||||
title = "Battery",
|
||||
timeout = 10000,
|
||||
})
|
||||
end)
|
||||
|
||||
bread.on("bread.power.ac.connected", function()
|
||||
warned = false
|
||||
end)
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
@ -57,41 +57,6 @@ hl.config({
|
|||
},
|
||||
})
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Animations — snappy curves + per-leaf speeds (matches the reference laptop;
|
||||
-- the hl.config default above is much slower).
|
||||
-- ---------------------------------------------------------------------------
|
||||
local curves = {
|
||||
easeOutQuint = { type = "bezier", points = { { 0.23, 1 }, { 0.32, 1 } } },
|
||||
easeInOutCubic = { type = "bezier", points = { { 0.65, 0.05 }, { 0.36, 1 } } },
|
||||
almostLinear = { type = "bezier", points = { { 0.5, 0.5 }, { 0.75, 1 } } },
|
||||
quick = { type = "bezier", points = { { 0.15, 0 }, { 0.1, 1 } } },
|
||||
}
|
||||
for name, curve in pairs(curves) do
|
||||
hl.curve(name, curve)
|
||||
end
|
||||
|
||||
local animations = {
|
||||
{ leaf = "global", enabled = true, speed = 10, bezier = "default" },
|
||||
{ leaf = "border", enabled = true, speed = 5.39, bezier = "easeOutQuint" },
|
||||
{ leaf = "windows", enabled = true, speed = 4.79, bezier = "easeOutQuint" },
|
||||
{ leaf = "windowsIn", enabled = true, speed = 4.1, bezier = "easeOutQuint", style = "popin 87%" },
|
||||
{ leaf = "windowsOut", enabled = true, speed = 1.49, bezier = "linear", style = "popin 87%" },
|
||||
{ leaf = "fade", enabled = true, speed = 3.03, bezier = "quick" },
|
||||
{ leaf = "layers", enabled = true, speed = 3.81, bezier = "easeOutQuint" },
|
||||
{ leaf = "workspaces", enabled = true, speed = 1.94, bezier = "almostLinear", style = "fade" },
|
||||
}
|
||||
for _, animation in ipairs(animations) do
|
||||
hl.animation(animation)
|
||||
end
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Window rules — float + centre the onboarding popups (kitty --class …).
|
||||
-- ---------------------------------------------------------------------------
|
||||
hl.window_rule({ name = "bos-keybinds", match = { class = "^(bos-keybinds)$" }, float = true, size = { 760, 720 } })
|
||||
hl.window_rule({ name = "bos-welcome", match = { class = "^(bos-welcome)$" }, float = true, size = { 700, 560 } })
|
||||
hl.window_rule({ name = "bos-netsetup", match = { class = "^(bos-netsetup)$" }, float = true, size = { 700, 560 } })
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Environment (vendor-neutral; no GPU-specific vars so it works on Intel/AMD).
|
||||
-- ---------------------------------------------------------------------------
|
||||
|
|
@ -120,8 +85,6 @@ hl.bind(mod .. " + E", hl.dsp.exec_cmd("nautilus"))
|
|||
hl.bind(mod .. " + B", hl.dsp.exec_cmd("zen-browser"))
|
||||
hl.bind(mod .. " + U", hl.dsp.exec_cmd("breadpad"))
|
||||
hl.bind(mod .. " + M", hl.dsp.exec_cmd("breadman"))
|
||||
hl.bind(mod .. " + comma", hl.dsp.exec_cmd("bos-settings"))
|
||||
hl.bind(mod .. " + slash", hl.dsp.exec_cmd("bos-keybinds"))
|
||||
hl.bind(mod .. " + L", hl.dsp.exec_cmd("loginctl lock-session"))
|
||||
hl.bind(mod .. " + F", hl.dsp.window.fullscreen({ action = "toggle" }))
|
||||
hl.bind(mod .. " + V", hl.dsp.window.float({ action = "toggle" }))
|
||||
|
|
@ -189,9 +152,6 @@ hl.bind("XF86AudioPlay", hl.dsp.exec_cmd("playerctl play-pause"),
|
|||
-- ---------------------------------------------------------------------------
|
||||
hl.on("hyprland.start", function()
|
||||
local startup = {
|
||||
-- Generate the shared bread GUI stylesheet first, so breadbar/breadbox/
|
||||
-- bos-settings load it on start (they also live-reload if it changes).
|
||||
"bread-theme generate",
|
||||
-- Global dark theme: GTK4/libadwaita + GTK3 theme + icon + cursor.
|
||||
"gsettings set org.gnome.desktop.interface color-scheme prefer-dark",
|
||||
"gsettings set org.gnome.desktop.interface gtk-theme Adwaita-dark",
|
||||
|
|
@ -204,17 +164,10 @@ hl.on("hyprland.start", function()
|
|||
"awww-daemon",
|
||||
-- set the default wallpaper once the daemon is up (retry until ready)
|
||||
[[bash -c 'until awww img /usr/share/backgrounds/bos/bread-background.png 2>/dev/null; do sleep 0.3; done']],
|
||||
-- breadd runs as a systemd user service (~/.config/systemd/user/breadd.service,
|
||||
-- enabled in skel). It autostarts at login but before Hyprland exists, so
|
||||
-- push the compositor's Wayland env into the user manager and restart breadd
|
||||
-- to pick it up — that's how it gets HYPRLAND_INSTANCE_SIGNATURE to talk to Hyprland.
|
||||
"dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP HYPRLAND_INSTANCE_SIGNATURE",
|
||||
"systemctl --user restart breadd",
|
||||
"breadd",
|
||||
"breadbar",
|
||||
"breadbox-sync",
|
||||
"hypridle",
|
||||
-- first-boot onboarding (self-gates after the first run)
|
||||
"bos-welcome",
|
||||
}
|
||||
for _, cmd in ipairs(startup) do
|
||||
hl.dispatch(hl.dsp.exec_cmd(cmd))
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
# BOS kitty config.
|
||||
# Translucent background so Hyprland's blur shows through behind the terminal,
|
||||
# while text stays fully opaque. Colours are left to kitty's default / pywal.
|
||||
# 0.6 matches the reference laptop; the actual blur is supplied by Hyprland's
|
||||
# decoration:blur (kitty's own background_blur is macOS-only).
|
||||
background_opacity 0.6
|
||||
background_opacity 0.88
|
||||
background_blur 1
|
||||
|
||||
font_family JetBrains Mono
|
||||
font_size 11.0
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
# Default applications for common file types. Without this, freshly installed
|
||||
# BOS has no handler registered for images/video/text/etc., so opening a file
|
||||
# from nautilus does nothing. Maps to the apps shipped in packages.x86_64.
|
||||
[Default Applications]
|
||||
# Images -> Loupe
|
||||
image/png=org.gnome.Loupe.desktop
|
||||
image/jpeg=org.gnome.Loupe.desktop
|
||||
image/gif=org.gnome.Loupe.desktop
|
||||
image/webp=org.gnome.Loupe.desktop
|
||||
image/bmp=org.gnome.Loupe.desktop
|
||||
image/tiff=org.gnome.Loupe.desktop
|
||||
image/svg+xml=org.gnome.Loupe.desktop
|
||||
|
||||
# Audio/Video -> VLC
|
||||
audio/mpeg=vlc.desktop
|
||||
audio/flac=vlc.desktop
|
||||
audio/ogg=vlc.desktop
|
||||
audio/x-wav=vlc.desktop
|
||||
audio/aac=vlc.desktop
|
||||
video/mp4=vlc.desktop
|
||||
video/x-matroska=vlc.desktop
|
||||
video/webm=vlc.desktop
|
||||
video/quicktime=vlc.desktop
|
||||
video/x-msvideo=vlc.desktop
|
||||
|
||||
# Plain text / source -> GNOME Text Editor
|
||||
text/plain=org.gnome.TextEditor.desktop
|
||||
text/markdown=org.gnome.TextEditor.desktop
|
||||
application/x-shellscript=org.gnome.TextEditor.desktop
|
||||
application/json=org.gnome.TextEditor.desktop
|
||||
application/toml=org.gnome.TextEditor.desktop
|
||||
text/x-readme=org.gnome.TextEditor.desktop
|
||||
|
||||
# Documents / web -> Zen (PDF + HTML)
|
||||
application/pdf=zen.desktop
|
||||
text/html=zen.desktop
|
||||
x-scheme-handler/http=zen.desktop
|
||||
x-scheme-handler/https=zen.desktop
|
||||
|
||||
# Archives -> File Roller
|
||||
application/zip=org.gnome.FileRoller.desktop
|
||||
application/x-tar=org.gnome.FileRoller.desktop
|
||||
application/gzip=org.gnome.FileRoller.desktop
|
||||
application/x-7z-compressed=org.gnome.FileRoller.desktop
|
||||
application/x-rar=org.gnome.FileRoller.desktop
|
||||
application/vnd.rar=org.gnome.FileRoller.desktop
|
||||
application/x-xz=org.gnome.FileRoller.desktop
|
||||
application/x-bzip2=org.gnome.FileRoller.desktop
|
||||
|
||||
# Directories -> Nautilus
|
||||
inode/directory=org.gnome.Nautilus.desktop
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
[Unit]
|
||||
Description=Bread Runtime Daemon
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
# %h = the user's home — works for any account created from this skel.
|
||||
ExecStart=%h/.local/bin/breadd
|
||||
Restart=on-failure
|
||||
RestartSec=2
|
||||
UMask=0077
|
||||
RuntimeDirectory=bread
|
||||
RuntimeDirectoryMode=0700
|
||||
# Keep /run/user/<uid>/bread across restarts so the shared theme.css that
|
||||
# bread-theme writes there (and the daemon socket) survive a `restart breadd`.
|
||||
RuntimeDirectoryPreserve=yes
|
||||
KillSignal=SIGTERM
|
||||
TimeoutStopSec=5
|
||||
Environment=RUST_LOG=info
|
||||
|
||||
[Install]
|
||||
WantedBy=default.target
|
||||
|
|
@ -1 +0,0 @@
|
|||
../breadd.service
|
||||
|
|
@ -1,15 +1,4 @@
|
|||
# BOS default zsh config — Powerlevel10k prompt + plugins + pywal palette.
|
||||
#
|
||||
# Mirrors the BOS dev shell, but sources plugins from the distro packages
|
||||
# (/usr/share/zsh/...) instead of oh-my-zsh, so there's no framework to manage.
|
||||
# Customise the prompt with `p10k configure` (rewrites ~/.p10k.zsh).
|
||||
|
||||
# Enable Powerlevel10k instant prompt. Should stay close to the top of ~/.zshrc.
|
||||
# Initialization code that may require console input (password prompts, [y/n]
|
||||
# confirmations, etc.) must go above this block; everything else may go below.
|
||||
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
|
||||
source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
|
||||
fi
|
||||
# BOS default zsh config — quality-of-life defaults, easy to extend.
|
||||
|
||||
# History
|
||||
HISTFILE=~/.zsh_history
|
||||
|
|
@ -22,21 +11,10 @@ autoload -Uz compinit && compinit
|
|||
zstyle ':completion:*' menu select
|
||||
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'
|
||||
|
||||
# Emacs-style key bindings
|
||||
# Key bindings (emacs style + common extras)
|
||||
bindkey -e
|
||||
|
||||
# Prompt — Powerlevel10k (republished to [breadway] as zsh-theme-powerlevel10k).
|
||||
source /usr/share/zsh-theme-powerlevel10k/powerlevel10k.zsh-theme
|
||||
|
||||
# Plugins (order matters: syntax-highlighting must be sourced LAST).
|
||||
ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE='fg=60'
|
||||
source /usr/share/zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh 2>/dev/null
|
||||
source /usr/share/zsh/plugins/zsh-history-substring-search/zsh-history-substring-search.zsh 2>/dev/null
|
||||
source /usr/share/zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh 2>/dev/null
|
||||
|
||||
# history-substring-search: ↑/↓ search history by the typed prefix.
|
||||
bindkey '^[[A' history-substring-search-up
|
||||
bindkey '^[[B' history-substring-search-down
|
||||
bindkey '^[[A' history-search-backward
|
||||
bindkey '^[[B' history-search-forward
|
||||
|
||||
# fzf — fuzzy history search on Ctrl+R, fuzzy file find on Ctrl+T
|
||||
if command -v fzf &>/dev/null; then
|
||||
|
|
@ -76,18 +54,12 @@ alias free='free -h'
|
|||
alias grep='grep --color=auto'
|
||||
alias ip='ip --color=auto'
|
||||
|
||||
# Updates — bos-update runs both channels (pacman + bakery). pacman aliased to
|
||||
# sudo so `pacman -Syu` etc. just work.
|
||||
alias update='bos-update'
|
||||
alias pacman='sudo pacman'
|
||||
# bakery / bread
|
||||
alias update='bakery update'
|
||||
|
||||
# ~/.local/bin holds the bread* binaries baked in at build time.
|
||||
export PATH="$HOME/.local/bin:$PATH"
|
||||
|
||||
# Powerlevel10k prompt configuration.
|
||||
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh
|
||||
|
||||
# Import pywal colour palette (drives the terminal colours from the wallpaper).
|
||||
if [ -f "$HOME/.cache/wal/sequences" ]; then
|
||||
cat "$HOME/.cache/wal/sequences"
|
||||
fi
|
||||
# Prompt — simple and fast (no starship dep)
|
||||
autoload -Uz vcs_info
|
||||
precmd() { vcs_info }
|
||||
zstyle ':vcs_info:git:*' formats ' (%b)'
|
||||
setopt PROMPT_SUBST
|
||||
PROMPT='%F{cyan}%~%f%F{yellow}${vcs_info_msg_0_}%f %(?.%F{green}.%F{red})❯%f '
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
# Compressed RAM swap. systemd-zram-generator reads this and creates a zram
|
||||
# device + swap at boot — no on-disk swap partition needed. Sized at half RAM
|
||||
# capped to 4 GiB, zstd-compressed (typically ~3:1, so cheap headroom).
|
||||
[zram0]
|
||||
zram-size = min(ram / 2, 4096)
|
||||
compression-algorithm = zstd
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
#!/bin/bash
|
||||
# Show the BOS keybind cheatsheet in a floating terminal (bound to SUPER+/).
|
||||
# The bos-keybinds window class is floated/centred by a Hyprland window rule.
|
||||
exec kitty --class bos-keybinds --title "BOS Keybinds" -- less -R /usr/share/bos/keybinds.txt
|
||||
|
|
@ -11,7 +11,7 @@ set -e
|
|||
# (breadd + breadbar + breadbox + keybinds) — proper live-media functionality,
|
||||
# not an installer kiosk.
|
||||
if ! id liveuser &>/dev/null; then
|
||||
useradd -m -s /usr/bin/zsh liveuser
|
||||
useradd -m -s /bin/bash liveuser
|
||||
for g in wheel video input audio storage power; do
|
||||
getent group "$g" >/dev/null 2>&1 && gpasswd -a liveuser "$g" >/dev/null || true
|
||||
done
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
#!/bin/bash
|
||||
# bos-update — update all of BOS in one go.
|
||||
#
|
||||
# BOS packages come from two channels, so a full update touches both:
|
||||
# 1. pacman — Arch base/desktop + the [breadway] repo (bos-settings, etc.).
|
||||
# Every transaction is snapshotted by snap-pac, so you can roll
|
||||
# back from the GRUB "snapshots" submenu or BOS Settings.
|
||||
# 2. bakery — the bread ecosystem apps in ~/.local/bin (bread, breadbar,
|
||||
# breadbox, breadcrumbs, breadpad, breadman, bread-theme).
|
||||
#
|
||||
# Best-effort: a failure in one channel doesn't abort the other.
|
||||
set -uo pipefail
|
||||
|
||||
bold() { printf '\033[1m%s\033[0m\n' "$1"; }
|
||||
|
||||
bold "==> System packages (pacman -Syu)"
|
||||
if command -v pacman >/dev/null; then
|
||||
sudo pacman -Syu || echo "WARN: pacman update failed"
|
||||
else
|
||||
echo "pacman not found; skipping"
|
||||
fi
|
||||
|
||||
echo
|
||||
bold "==> Bread ecosystem (bakery update --all)"
|
||||
if command -v bakery >/dev/null; then
|
||||
bakery update --all || echo "WARN: bakery update failed"
|
||||
else
|
||||
echo "bakery not found; skipping"
|
||||
fi
|
||||
|
||||
echo
|
||||
bold "==> BOS is up to date."
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
#!/bin/bash
|
||||
# First-run welcome. Shows a short getting-started message once, then drops a
|
||||
# marker so it never shows again. Launched from the Hyprland autostart; the
|
||||
# bos-welcome window class is floated/centred by a Hyprland window rule.
|
||||
set -u
|
||||
|
||||
# Never run in the live/installer session — only on an installed system.
|
||||
[[ "$(id -un)" == "liveuser" ]] && exit 0
|
||||
|
||||
marker="${XDG_CONFIG_HOME:-$HOME/.config}/bos/.welcomed"
|
||||
[[ -f "$marker" ]] && exit 0
|
||||
mkdir -p "$(dirname "$marker")"
|
||||
|
||||
# First-run network check. A fresh install usually boots with no connection
|
||||
# (Wi-Fi isn't configured during install), and the first `bos-update`/pacman run
|
||||
# then fails with confusing DNS/"could not resolve host" errors. If
|
||||
# NetworkManager reports we're not fully online, open nmtui so the user can join
|
||||
# a network before anything else. Best-effort: missing nmcli/nmtui/kitty, or the
|
||||
# user quitting nmtui, must never block the welcome below.
|
||||
if command -v nmcli &>/dev/null; then
|
||||
conn="$(nmcli networking connectivity check 2>/dev/null)"
|
||||
if [[ "$conn" != "full" ]]; then
|
||||
notify-send -u normal "BOS" "No internet yet — opening network setup so updates work." 2>/dev/null || true
|
||||
if command -v nmtui &>/dev/null; then
|
||||
kitty --class bos-netsetup --title "Connect to a network" -- nmtui connect 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# Mark welcomed only now, so an interrupted/aborted network step still re-prompts
|
||||
# next login rather than being suppressed forever.
|
||||
touch "$marker"
|
||||
|
||||
exec kitty --class bos-welcome --title "Welcome to BOS" -- less -R /usr/share/bos/welcome.txt
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
|
||||
██████ ██████ ███████ keyboard shortcuts
|
||||
██ ██ ██ ██ ██ SUPER is the Windows/Cmd key
|
||||
██████ ██ ██ ███████
|
||||
══════════════════════════════════════════════════════════
|
||||
|
||||
APPS & WINDOWS
|
||||
SUPER + Return terminal (kitty)
|
||||
SUPER + Space app launcher (breadbox)
|
||||
SUPER + E files (nautilus)
|
||||
SUPER + B browser (zen)
|
||||
SUPER + U notes / reminders (breadpad)
|
||||
SUPER + M package manager (breadman)
|
||||
SUPER + , BOS Settings
|
||||
SUPER + / this keybind cheatsheet
|
||||
SUPER + L lock screen
|
||||
SUPER + Backspace close window
|
||||
SUPER + F fullscreen
|
||||
SUPER + V toggle floating
|
||||
SUPER + Shift + V clipboard history
|
||||
SUPER + T toggle split direction
|
||||
SUPER + Tab last window
|
||||
SUPER + N exit Hyprland (log out)
|
||||
|
||||
SCREENSHOTS
|
||||
SUPER + Shift + S select region -> file
|
||||
SUPER + Shift + C select region -> clipboard
|
||||
SUPER + Shift + P whole screen -> file
|
||||
|
||||
FOCUS & MOVE
|
||||
SUPER + arrows move focus
|
||||
SUPER + Shift + h/j/k/l move window
|
||||
SUPER + Shift + arrows resize window
|
||||
|
||||
WORKSPACES
|
||||
SUPER + 1..0 switch to workspace 1..10
|
||||
SUPER + Shift + 1..0 move window to workspace
|
||||
SUPER + [ / ] previous / next workspace
|
||||
SUPER + Shift + [ / ] move window prev / next workspace
|
||||
SUPER + scroll cycle workspaces
|
||||
|
||||
MOUSE
|
||||
SUPER + left-drag move window
|
||||
SUPER + right-drag resize window
|
||||
|
||||
MEDIA & HARDWARE KEYS
|
||||
volume / brightness / play-pause / next / prev (work on lock screen)
|
||||
|
||||
──────────────────────────────────────────────────────────
|
||||
Press q to close. Configure everything in BOS Settings (SUPER + ,).
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
|
||||
Welcome to BOS — the Bread Operating System
|
||||
══════════════════════════════════════════════════════════
|
||||
|
||||
You're running a complete Hyprland desktop with the bread
|
||||
ecosystem preinstalled. A few things to get you started:
|
||||
|
||||
• SUPER + / show the keybind cheatsheet (any time)
|
||||
• SUPER + , open BOS Settings — configure bread, the
|
||||
bar, launcher, Wi-Fi profiles, notes,
|
||||
snapshots and package updates, all in one
|
||||
place (no config files needed)
|
||||
• SUPER + Space the app launcher (breadbox)
|
||||
• SUPER + Return a terminal
|
||||
|
||||
The bar at the top (breadbar) shows workspaces, the clock,
|
||||
system stats, and your tray. Notifications appear top-right.
|
||||
|
||||
Your system is snapshotted on every package change — if an
|
||||
update breaks something, roll back from BOS Settings or pick
|
||||
a snapshot from the GRUB menu at boot.
|
||||
|
||||
──────────────────────────────────────────────────────────
|
||||
Press q to close. This message won't show again.
|
||||
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 6.2 KiB |
|
|
@ -1,5 +0,0 @@
|
|||
title Bread OS install medium (copy to RAM, UEFI)
|
||||
sort-key 015
|
||||
linux /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
|
||||
initrd /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
|
||||
options archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% copytoram=y
|
||||
|
|
@ -75,11 +75,6 @@ pipewire-jack
|
|||
networkmanager
|
||||
network-manager-applet
|
||||
iw
|
||||
# mDNS service/name resolution — lets CUPS auto-discover network printers and
|
||||
# resolves .local hostnames (avahi-daemon enabled + nss-mdns wired in
|
||||
# post-install.sh).
|
||||
avahi
|
||||
nss-mdns
|
||||
# Wi-Fi backend for NetworkManager (its default; no extra config needed).
|
||||
wpa_supplicant
|
||||
bluez
|
||||
|
|
@ -95,12 +90,6 @@ libpulse
|
|||
# GTK3 dark theme (Adwaita-dark); without this package the gtk-theme-name in
|
||||
# skel settings.ini silently falls back to the light theme for GTK3 apps.
|
||||
gnome-themes-extra
|
||||
# Schema + backend behind `gsettings set org.gnome.desktop.interface
|
||||
# color-scheme prefer-dark` (set in hyprland.lua autostart). Without these the
|
||||
# gsettings call fails silently and libadwaita apps (nautilus, gnome-text-editor)
|
||||
# render in LIGHT mode regardless of the GTK theme.
|
||||
gsettings-desktop-schemas
|
||||
dconf
|
||||
# Credential/keyring storage — browsers, SSH agents, and most apps persist
|
||||
# passwords here; without it every session loses saved logins. seahorse is the
|
||||
# GUI to view/manage the stored secrets and keys.
|
||||
|
|
@ -118,12 +107,6 @@ noto-fonts-emoji
|
|||
ttf-jetbrains-mono
|
||||
# Nerd font variant — icons in terminal tools (eza --icons, fastfetch, yazi)
|
||||
ttf-jetbrains-mono-nerd
|
||||
# Metric-compatible (Arial/Times/Courier) so Office/web docs lay out correctly,
|
||||
# broad Unicode fallback, and the Font Awesome icon glyph set (otf-, the desktop
|
||||
# variant — ttf-font-awesome resolves to the web-only woff2 build).
|
||||
ttf-liberation
|
||||
ttf-dejavu
|
||||
otf-font-awesome
|
||||
|
||||
# Terminal
|
||||
kitty
|
||||
|
|
@ -139,13 +122,10 @@ file-roller
|
|||
|
||||
# GUI applications a general desktop is expected to have out of the box.
|
||||
# gnome-text-editor: graphical editor (terminal editors aside); gnome-calculator:
|
||||
# calculator; loupe: Wayland-native image viewer (default for image files);
|
||||
# zathura(+pdf-mupdf): lightweight Wayland PDF viewer (BOS had no PDF reader).
|
||||
# calculator; loupe: Wayland-native image viewer (default for image files).
|
||||
gnome-text-editor
|
||||
gnome-calculator
|
||||
loupe
|
||||
zathura
|
||||
zathura-pdf-mupdf
|
||||
# Media player — BOS ships gstreamer codecs but otherwise has no player app.
|
||||
vlc
|
||||
# Web browser (served from the [Breadway] repo; AUR zen-browser-bin republished
|
||||
|
|
@ -193,12 +173,6 @@ plymouth
|
|||
gst-plugins-good
|
||||
gst-plugins-bad
|
||||
gst-plugins-ugly
|
||||
# Hardware video acceleration (VA-API) — lets the AMD/Intel GPU decode H.264/HEVC/
|
||||
# VP9 in mpv, VLC, and browsers instead of the CPU (cooler, longer battery on
|
||||
# video). The open Mesa VA-API backend (radeonsi_drv_video.so etc.) now ships in
|
||||
# the `mesa` package itself (pulled in already), so only libva (deps) + the
|
||||
# `vainfo` verification tool need listing here.
|
||||
libva-utils
|
||||
# GUI audio mixer — useful when output device needs manual switching.
|
||||
pavucontrol
|
||||
|
||||
|
|
@ -216,15 +190,8 @@ man-pages
|
|||
less
|
||||
|
||||
# Base CLI tools every install should have.
|
||||
# Shell — zsh with the same prompt + plugins as the dev laptop. Powerlevel10k is
|
||||
# AUR-only, so it's republished to [breadway] (see packaging/powerlevel10k). The
|
||||
# three plugins come from the official repos; skel/.zshrc sources them in order
|
||||
# (autosuggestions → history-substring-search → syntax-highlighting LAST).
|
||||
# Shell
|
||||
zsh
|
||||
zsh-theme-powerlevel10k
|
||||
zsh-autosuggestions
|
||||
zsh-history-substring-search
|
||||
zsh-syntax-highlighting
|
||||
# Editors
|
||||
nano
|
||||
micro
|
||||
|
|
@ -269,14 +236,6 @@ system-config-printer
|
|||
# remote post-install (needs network); the runtime is shipped ready.
|
||||
flatpak
|
||||
|
||||
# Firewall — ufw, enabled deny-incoming in post-install.sh (mDNS allowed so
|
||||
# printer discovery still works).
|
||||
ufw
|
||||
# Firmware updates via LVFS (works with gnome-software / fwupdmgr).
|
||||
fwupd
|
||||
# Compressed RAM swap — see /etc/systemd/zram-generator.conf.
|
||||
zram-generator
|
||||
|
||||
# Icon and cursor themes
|
||||
# Papirus-Dark: cohesive icon set used as the BOS default (set via gsettings in
|
||||
# hyprland.lua autostart and in skel gtk-3.0/settings.ini).
|
||||
|
|
|
|||
|
|
@ -35,8 +35,7 @@ Include = /etc/pacman.d/mirrorlist
|
|||
#
|
||||
# Forgejo signs the repo db with a key pacman can't look up, so TrustAll
|
||||
# fails. SigLevel = Never skips verification (acceptable for this private
|
||||
# repo over TLS). Future improvement: import Forgejo's signing key and
|
||||
# switch to SigLevel = Required for full package verification.
|
||||
# repo over TLS). TODO: import Forgejo's signing key + SigLevel = Required.
|
||||
# -----------------------------------------------------------------------
|
||||
# The section name must match Forgejo's served db filename
|
||||
# ({owner}.{group}.{domain}.db) — pacman fetches "<section>.db" from Server.
|
||||
|
|
|
|||
|
|
@ -21,7 +21,4 @@ file_permissions=(
|
|||
["/usr/local/bin/bos-launch-calamares"]="0:0:755"
|
||||
["/usr/local/bin/bos-copy-kernel"]="0:0:755"
|
||||
["/usr/local/bin/bos-session"]="0:0:755"
|
||||
["/usr/local/bin/bos-keybinds"]="0:0:755"
|
||||
["/usr/local/bin/bos-welcome"]="0:0:755"
|
||||
["/usr/local/bin/bos-update"]="0:0:755"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -8,19 +8,6 @@ LINUX /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
|
|||
INITRD /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
|
||||
APPEND archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID%
|
||||
|
||||
# Copy-to-RAM boot option — loads airootfs.sfs entirely into RAM, so the
|
||||
# installer reads from memory rather than a possibly-flaky USB (avoids SquashFS
|
||||
# read errors during unpackfs). Needs enough RAM for the image (~3 GB).
|
||||
LABEL archtoram
|
||||
TEXT HELP
|
||||
Boot Bread OS, copying the image into RAM first.
|
||||
More reliable installs from USB; needs a few GB of RAM.
|
||||
ENDTEXT
|
||||
MENU LABEL Bread OS install medium (%ARCH%, BIOS) ^copy to RAM
|
||||
LINUX /%INSTALL_DIR%/boot/%ARCH%/vmlinuz-linux
|
||||
INITRD /%INSTALL_DIR%/boot/%ARCH%/initramfs-linux.img
|
||||
APPEND archisobasedir=%INSTALL_DIR% archisosearchuuid=%ARCHISO_UUID% copytoram=y
|
||||
|
||||
# Accessibility boot option
|
||||
LABEL archspeech
|
||||
TEXT HELP
|
||||
|
|
|
|||
|
|
@ -1,105 +0,0 @@
|
|||
# BOS in-house rebuild of zsh-theme-powerlevel10k (AUR-only upstream).
|
||||
# Republished to [breadway] so the ISO can pull the BOS default prompt via pacman
|
||||
# (same pattern as bibata / zen-browser-bin). Upstream maintainer header kept below.
|
||||
# Maintainer: Mark Wagie <mark dot wagie at proton dot me>
|
||||
# Contributor: Christian Rebischke <chris.rebischke@archlinux.org>
|
||||
# Contributor: Jeff Henson <jeff@henson.io>
|
||||
# Contributor: Ron Asimi <ron dot asimi at gmail dot com>
|
||||
# Contributor: Roman Perepelitsa <roman.perepelitsa@gmail.com>
|
||||
pkgname=zsh-theme-powerlevel10k
|
||||
# Whenever pkgver is updated, _libgit2ver below must also be updated.
|
||||
pkgver=1.20.17 ## see P9K_VERSION in internal/p10k.zsh
|
||||
_libgit2ver="tag-2ecf33948a4df9ef45a66c68b8ef24a5e60eaac6"
|
||||
pkgrel=1
|
||||
epoch=1
|
||||
pkgdesc="Powerlevel10k is a theme for Zsh. It emphasizes speed, flexibility and out-of-the-box experience."
|
||||
arch=('x86_64' 'aarch64')
|
||||
url='https://github.com/romkatv/powerlevel10k'
|
||||
license=('MIT')
|
||||
depends=(
|
||||
'glibc'
|
||||
'zsh'
|
||||
)
|
||||
makedepends=(
|
||||
'git'
|
||||
'cmake'
|
||||
)
|
||||
optdepends=(
|
||||
# It works well with Nerd Fonts, Source Code Pro, Font Awesome, Powerline,
|
||||
# and even the default system fonts. The full choice of style options is
|
||||
# available only when using Nerd Fonts.
|
||||
'ttf-meslo-nerd-font-powerlevel10k: recommended font'
|
||||
'powerline-fonts: patched fonts for powerline'
|
||||
'ttf-font-nerd: full choice of style options'
|
||||
)
|
||||
replaces=('zsh-theme-powerlevel9k')
|
||||
_commit=9253fb1c5034410c43a0c681ff8294181c54016c
|
||||
|
||||
# _libgit2ver depends on pkgver. They must be updated together. See libgit2_version in:
|
||||
# https://raw.githubusercontent.com/romkatv/powerlevel10k/v${pkgver}/gitstatus/build.info
|
||||
source=(
|
||||
"git+https://github.com/romkatv/powerlevel10k.git#commit=${_commit}"
|
||||
# "powerlevel10k-${pkgver}.tar.gz::https://github.com/romkatv/powerlevel10k/archive/v${pkgver}.tar.gz"
|
||||
# "https://github.com/romkatv/powerlevel10k/releases/download/v$pkgver/powerlevel10k-$pkgver.tar.gz.asc"
|
||||
"libgit2-${_libgit2ver}.tar.gz::https://github.com/romkatv/libgit2/archive/${_libgit2ver}.tar.gz")
|
||||
sha256sums=('f0edc2cc5bfcdfcf3b94f10597c252873567a990e651d04059c887046fba6701'
|
||||
'4ce11d71ee576dbbc410b9fa33a9642809cc1fa687b315f7c23eeb825b251e93')
|
||||
#validpgpkeys=('8B060F8B9EB395614A669F2A90ACE942EB90C3DD') # Roman Perepelitsa <roman.perepelitsa@gmail.com>
|
||||
|
||||
build() {
|
||||
cd "libgit2-${_libgit2ver}"
|
||||
local cmake_options=(
|
||||
-W no-dev
|
||||
-D CMAKE_BUILD_TYPE='None'
|
||||
-D ZERO_NSEC='ON'
|
||||
-D THREADSAFE='ON'
|
||||
-D USE_BUNDLED_ZLIB='ON'
|
||||
-D REGEX_BACKEND='builtin'
|
||||
-D USE_HTTP_PARSER='builtin'
|
||||
-D USE_SSH='OFF'
|
||||
-D USE_HTTPS='OFF'
|
||||
-D BUILD_CLAR='OFF'
|
||||
-D USE_GSSAPI='OFF'
|
||||
-D USE_NTLMCLIENT='OFF'
|
||||
-D BUILD_SHARED_LIBS='OFF'
|
||||
-D ENABLE_REPRODUCIBLE_BUILDS='ON'
|
||||
)
|
||||
cmake "${cmake_options[@]}" .
|
||||
make
|
||||
|
||||
# build gitstatus
|
||||
cd "$srcdir/powerlevel10k/gitstatus"
|
||||
export CXXFLAGS+=" -I${srcdir}/libgit2-${_libgit2ver}/include -DGITSTATUS_ZERO_NSEC -D_GNU_SOURCE"
|
||||
export LDFLAGS+=" -L${srcdir}/libgit2-${_libgit2ver}"
|
||||
make
|
||||
}
|
||||
|
||||
package() {
|
||||
cd powerlevel10k
|
||||
find . -type f -exec install -D '{}' "$pkgdir/usr/share/${pkgname}/{}" ';'
|
||||
|
||||
install -d "${pkgdir}/usr/share/licenses/${pkgname}"
|
||||
ln -s "/usr/share/${pkgname}/LICENSE" "${pkgdir}/usr/share/licenses/${pkgname}"
|
||||
|
||||
# delete unnecessary files. See also: https://bugs.archlinux.org/task/66737
|
||||
rm -r "${pkgdir}/usr/share/${pkgname}/.git"
|
||||
rm -r "${pkgdir}/usr/share/${pkgname}/gitstatus/deps/"
|
||||
rm -r "${pkgdir}/usr/share/${pkgname}/gitstatus/obj"
|
||||
rm -r "${pkgdir}/usr/share/${pkgname}/gitstatus/src/"
|
||||
rm -r "${pkgdir}/usr/share/${pkgname}/gitstatus/.vscode/"
|
||||
rm "${pkgdir}/usr/share/${pkgname}/.gitattributes"
|
||||
rm "${pkgdir}/usr/share/${pkgname}/.gitignore"
|
||||
rm "${pkgdir}/usr/share/${pkgname}/Makefile"
|
||||
rm "${pkgdir}/usr/share/${pkgname}/gitstatus/build"
|
||||
rm "${pkgdir}/usr/share/${pkgname}/gitstatus/Makefile"
|
||||
rm "${pkgdir}/usr/share/${pkgname}/gitstatus/mbuild"
|
||||
rm "${pkgdir}/usr/share/${pkgname}/gitstatus/.clang-format"
|
||||
rm "${pkgdir}/usr/share/${pkgname}/gitstatus/.gitignore"
|
||||
rm "${pkgdir}/usr/share/${pkgname}/gitstatus/.gitattributes"
|
||||
rm "${pkgdir}/usr/share/${pkgname}/gitstatus/usrbin/.gitkeep"
|
||||
|
||||
cd "${pkgdir}/usr/share/${pkgname}"
|
||||
for file in *.zsh-theme internal/*.zsh gitstatus/*.zsh gitstatus/install; do
|
||||
zsh -fc "emulate zsh -o no_aliases && zcompile -R -- $file.zwc $file"
|
||||
done
|
||||
}
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
# BOS post-install smoke test.
|
||||
#
|
||||
# Run this INSIDE a freshly installed BOS (as the main user) to assert the
|
||||
# install's core invariants. It is read-only and safe to run any time.
|
||||
#
|
||||
# ./smoke-test.sh
|
||||
#
|
||||
# Exit status is non-zero if any check fails, so it can gate CI / manual QA.
|
||||
set -uo pipefail
|
||||
|
||||
pass=0 fail=0
|
||||
ok() { printf ' \033[32mPASS\033[0m %s\n' "$1"; pass=$((pass+1)); }
|
||||
bad() { printf ' \033[31mFAIL\033[0m %s\n' "$1"; fail=$((fail+1)); }
|
||||
note() { printf ' \033[33m----\033[0m %s\n' "$1"; }
|
||||
|
||||
check() { if eval "$2" >/dev/null 2>&1; then ok "$1"; else bad "$1"; fi; }
|
||||
|
||||
echo "== btrfs subvolume layout =="
|
||||
if command -v btrfs >/dev/null; then
|
||||
# `btrfs subvolume list` needs root; try unprivileged, fall back to non-
|
||||
# interactive sudo (no hang if creds aren't cached).
|
||||
paths="$(btrfs subvolume list / 2>/dev/null || sudo -n btrfs subvolume list / 2>/dev/null)"
|
||||
paths="$(awk '{print $NF}' <<<"$paths")"
|
||||
if [ -z "$paths" ]; then
|
||||
note "couldn't list subvolumes (need root) — skipping"
|
||||
else
|
||||
for sv in @ @home @snapshots @log @cache; do
|
||||
if grep -qx "$sv" <<<"$paths"; then ok "subvolume $sv present"; else bad "subvolume $sv missing"; fi
|
||||
done
|
||||
fi
|
||||
else
|
||||
note "btrfs not installed (not a btrfs root?) — skipping subvolume checks"
|
||||
fi
|
||||
|
||||
echo "== snapshot tooling =="
|
||||
check "snapper root config exists" "[ -f /etc/snapper/configs/root ]"
|
||||
check "snap-pac hook present" "pacman -Qq snap-pac"
|
||||
check "grub-btrfs present" "pacman -Qq grub-btrfs"
|
||||
|
||||
echo "== enabled system services =="
|
||||
for unit in NetworkManager.service greetd.service bluetooth.service tlp.service \
|
||||
cups.socket avahi-daemon.service ufw.service systemd-timesyncd.service; do
|
||||
check "$unit enabled" "systemctl is-enabled $unit"
|
||||
done
|
||||
check "graphical.target is default" "[ \"\$(systemctl get-default)\" = graphical.target ]"
|
||||
|
||||
echo "== bread ecosystem on PATH =="
|
||||
for bin in bakery bread breadd breadbar breadbox breadbox-sync breadcrumbs breadpad breadman; do
|
||||
check "$bin found" "command -v $bin"
|
||||
done
|
||||
|
||||
echo "== bos-settings =="
|
||||
check "bos-settings installed" "command -v bos-settings"
|
||||
|
||||
echo "== default dotfiles =="
|
||||
check "hyprland.lua present" "[ -f \"\$HOME/.config/hypr/hyprland.lua\" ]"
|
||||
check "mimeapps.list present" "[ -f \"\$HOME/.config/mimeapps.list\" ]"
|
||||
check "kitty config present" "[ -f \"\$HOME/.config/kitty/kitty.conf\" ]"
|
||||
|
||||
echo "== bootloader (EFI) =="
|
||||
check "GRUB EFI binary present" \
|
||||
"[ -f /boot/efi/EFI/BOS/grubx64.efi ] || [ -f /boot/efi/EFI/BOOT/BOOTX64.EFI ]"
|
||||
check "grub.cfg present" "[ -f /boot/grub/grub.cfg ]"
|
||||
|
||||
echo
|
||||
printf 'Result: \033[32m%d passed\033[0m, \033[31m%d failed\033[0m\n' "$pass" "$fail"
|
||||
[ "$fail" -eq 0 ]
|
||||