# AGENTS.md Arch Linux ISO profile (archiso). Builds a live ISO with Hyprland desktop, end-4 dots-hyprland, and curated packages. Hosted on Gitea. ## Build & Test Commands ```bash # Build the ISO (repo root IS the profile directory) sudo mkarchiso -v -w work -o out/ . # Build AUR deps for end-4 (run locally before ISO build if localrepo/ is stale) ./localrepo/build-end4-deps.sh # build all ./localrepo/build-end4-deps.sh --quick # skip large AUR pkgs # Refresh localrepo DB after adding/moving .pkg.tar.zst files ./localrepo/update.sh # re-indexes existing packages ./localrepo/update.sh pkg1.pkg.tar.zst # add files, then re-index ``` `update.sh` also refreshes `airootfs/opt/localrepo/` (the copy that ships on the ISO), so run it after touching `localrepo/` before building. ## CI Checks (must pass before merge) - **ShellCheck**: all `.sh` files checked with `shellcheck -x -s bash` - **yamllint**: all `.yml`/`.yaml` files (relaxed config) - **packages.x86_64 syntax**: one package per line, no trailing whitespace, `[a-zA-Z0-9._@+\-]+` only - **Package repo check**: every package in `packages.x86_64` must be resolvable via `pacman -Si` in allowed repos (`cachyos`, `extra`, `multilib`, `chaotic-aur`), OR have a pre-built `.pkg.tar.zst` in `localrepo/`, OR appear in `localrepo/build-end4-deps.sh` ## Package Management **Three sources** contribute packages to the ISO: 1. **`packages.x86_64`** — main list, installed by mkarchiso. Must be in an allowed repo. 2. **`localrepo/*.pkg.tar.zst`** — pre-built AUR packages. The `local-aur` repo is configured in `pacman.conf` and picked up by mkarchiso automatically. 3. **`build-end4-deps.sh`** — builds end-4 AUR deps at build time. There is a **fourth source**: `customize_airootfs.sh` runs end-4's own `./setup install-deps` inside the image (as a throwaway `ii-builder` account), which resolves and compiles everything the dotfiles need (quickshell, MicroTeX, theming, fonts, ...). Those packages are installed in the live system, land in `pkglist.x86_64.txt`, and are harvested into `/opt/localrepo` so pacstrap can install them into the target without the network. **Important**: `localrepo/update.sh` auto-appends new package names to `packages.x86_64`. If you remove a package from `packages.x86_64` that exists in `localrepo/`, it will be re-added on the next `update.sh` run. ## Key Files | File | Purpose | |------|---------| | `packages.x86_64` | Live ISO package list (~402 packages) | | `profiledef.sh` | ISO metadata, compression, boot modes, build-stamp staging | | `pacman.conf` | Repos: cachyos → core → extra → multilib → chaotic-aur → local-aur | | `bootstrap_packages` | Minimal build-time packages (`base`, `arch-install-scripts`) | | `airootfs/root/customize_airootfs.sh` | Runs inside chroot during build: keyrings, skel dotfiles (incl. end4-pC), qsConfig patch, end-4 `install-deps`, package harvest, uv/font pre-warm | | `airootfs/root/.live-pacman.conf` | `/etc/pacman.conf` of the built image (adds `[local-aur]` = `file:///opt/localrepo`) | | `airootfs/usr/local/bin/alvin-install` | Installer: partitions, pacstrap, LUKS (systemd initramfs **or** experimental unl0kr + optional TPM2 unlock), user, git identity + GitHub SSH keys, login manager (none/greetd/sddm/gdm) + autologin, end-4 dotfiles (`--skip-alldeps`), build-stamp motd, boot | | `localrepo/build-end4-deps.sh` | Non-interactive AUR builds for end-4 dependencies | | `localrepo/update.sh` | Regenerates localrepo DB, syncs names to packages.x86_64, syncs `airootfs/opt/localrepo/` | ## Gotchas - The profile root is the **repo root** (not a `releng/` subdirectory). The CI build-iso workflow uses `mkarchiso -v -w work -o out/ releng` but this is a naming convention — the actual profile files live at the repo root. - `customize_airootfs.sh` clones git repos (oh-my-zsh, lazy.nvim, plugins, end-4 dots) into `/etc/skel` and `/opt` during the ISO build. These require network access at build time but make the live ISO work offline. - `customize_airootfs.sh` runs `./setup install-deps -f -s --skip-plasmaintg` as the throwaway user `ii-builder` (end-4's scripts refuse to run as root) and aborts the build if it fails. `--skip-plasmaintg` is deliberate: that optional Firefox widget pulls 410 packages / 526 MiB of KDE. - The `[local-aur]` repo path in `pacman.conf` (`file:///home/alvin/alvinarch/localrepo`) is for local builds only. The CI does not use this path. - The **image** ships its own `[local-aur]` at `file:///opt/localrepo` (see `.live-pacman.conf`). It holds `localrepo/` (copied by CI/`update.sh`) plus everything `install-deps` built. pacstrap runs without `-P`, so the target keeps the stock `/etc/pacman.conf`; `alvin-install` strips `[local-aur]` from it anyway as a safety net, because `/opt/localrepo` exists only on the medium. - `alvin-install` runs end-4 with `--skip-alldeps` — dependencies must come from the ISO. It feeds `yes i` to end-4's failure prompt: inside the installer chroot the medium's `/run` is bind-mounted in, so end-4's `systemctl --machine=…@.host --user enable … --now` lines can never work (and `--now` would start services on the live medium). `install_end4_dots` re-applies the enable-only part (bluetooth, ydotool, i2c module) outside the chroot and reports every step end-4 had to skip. If the end-4 step reports "incomplete", check that `hyprctl`/`quickshell`/the venv were resolvable (harvest) before re-running anything. - `/etc/skel/.cache/uv` + `/etc/skel/.local/share/uv/python` are pre-warmed by the build (~460 MB: CPython 3.12 and the pinned wheel cache) so end-4's `uv venv`/`uv pip install` at install time needs no network. - **end4-pC** (`pctrade/end4-pC`) is the default quickshell config: cloned into `/etc/skel/.config/quickshell/end4-pC` at build time, selected by patching `hl.env("qsConfig", "ii")` → `"end4-pC"` in the **staged** `/opt/dots-hyprland/dots/.config/hypr/hyprland/variables.lua` (there is no `hypr/hyprland/` in this repo — `./setup install` copies it to the installed system). `alvin-install` re-copies end4-pC into the user's home *after* `./setup install`, because end-4's installer `rsync --delete`s all of `~/.config/quickshell`. - `airootfs/etc/skel/.config/illogical-impulse/presets/` carries the user's presets (`Laptop.json`, `Personal-Performance.json`, `Personal-Performance.zip`). They embed `/home/alvin/...` paths, so wallpapers/screenshots need fixing up after install. - End-4 metapackages are built from `localrepo/end4-pkgbuilds/` (quickshell-git, bibata-modern-classic-bin, microtex-git). - `packages.x86_64` is sorted alphabetically. Keep it sorted when adding/removing entries. - `airootfs/opt/localrepo/` is a build artifact (gitignored) — never commit it. - **Build stamp flow**: `profiledef.sh` (sourced by mkarchiso) stages the gitignored `airootfs/root/.iso-build-stamp` when a `.git` dir exists **or** `CI`/`GITEA_ACTIONS` is set — line reads `AlvinArch build | commit | <4-char hash>` (falls back to `commit unknown` if `git -c safe.directory` can't read the repo; without `.git`/CI no file is staged). `customize_airootfs.sh` installs it as `/etc/alvin-build-stamp` on the live medium, and `alvin-install`'s `install_motd` copies the live `/etc/motd` banner to the target and appends the stamp. If the medium has no stamp, the installed system gets no motd from us.