Every list in setup/packages/ is annotated -- which package exists for which settings page, why an exception was made -- and install-packages passed the whole file to dnf, comment lines included. dnf does not ignore an argument it cannot match. It reports "No match for argument: #" and exits 1, and with set -euo pipefail at the top of that script the first annotated list ends the stage. initial-packages carries four comments and is the first list read, so a fresh machine got the repositories, the group updates, and then nothing. Two things hid it. On a machine that already has everything, a re-run matches every real name and fails only on the comments, so the failure looks like noise rather than the stage dying. And every contract that reads these lists strips comments with sed before comparing -- the tests were reading a file the installer was not, which is why a repository with a dependency contract, an assets contract and a doctor still reported PASS across the board. The fix is one filter used at all five call sites. The contract lifts that filter out of the script and runs it, rather than describing what it should do, so deleting or renaming it fails here instead of passing quietly. It also checks the inverse -- that stripping comments does not strip packages -- because trading a loud failure for a silent one would be worse than the bug. Found while adding the extras lists for phase 4, which are annotated the same way and would have hit the same wall. Claude-Session: https://claude.ai/code/session_01NvgBuSWB5sE43yWmg21ozj
Panama
Formerly Sunhat. A personal config for Fedora, with the intention of helping a user set up their Fedora system with one command.
git clone https://git.gbrown.org/gib/Panama.git ~/.local/share/Panama
~/.local/share/Panama/install
install asks its questions first and then runs the stages in setup/scripts/
in order, without stopping again:
| Script | Does |
|---|---|
interview |
Every prompt, before anything is installed. Answers last one run and are never written to a durable path |
install-packages |
Repos (RPM Fusion, Terra, Hyprland COPR), then the package lists in setup/packages/ |
link-dotfiles |
Symlinks config/dot/<name> → ~/.config/<name>, and seeds the wallpaper and cursor theme |
change-settings |
Copies config/copy/ over /, applies gsettings, enables user services |
link-vicinae-scripts |
Publishes the Vicinae script commands |
setup-identity |
git config, gh auth login, an SSH key — whichever were asked for |
install-hardware |
NVIDIA, Secure Boot enrolment, Fedora's extras, firmware — each only if it was asked for. Last, because enrolment and firmware are consumed at the next boot |
The run ends with a health summary from panama-doctor, which reports what is
actually running rather than what was attempted. It never fails the install: on a
fresh machine it legitimately reports things as not yet configured.
Existing configs are moved to config/old/ rather than overwritten.
Desktops
Panama configures two desktops that coexist. Both sessions stay available in GDM, so you can switch back and forth while you settle in.
GNOME
The original setup: Forge for tiling, Dash-to-Dock, Openbar, Vitals,
AppIndicator support. Configured through config/dot/forge/ and gsettings.
Hyprland
A from-scratch replacement built to reproduce the GNOME setup closely enough that muscle memory transfers — same keybinds, same panel contents, same dock, same Tokyo Night Moon palette.
| Piece | What it is |
|---|---|
config/dot/hypr/ |
Compositor config. Lua, not hyprlang — see its README |
config/dot/quickshell/ |
The shell: bar, dock, Continuum overview, Settings, Screen Intelligence, focus sessions, quick settings, notifications, screenshot UI |
config/dot/vicinae/ |
Raycast-style launcher, themed |
config/dot/uwsm/ |
Session environment (see the uwsm caveat in the hypr README) |
config/dot/wofi/ |
Fallback launcher, in case the shell fails to start |
config/dot/xdg-desktop-portal/ |
Portal backend routing |
Start here: config/dot/hypr/README.md — it
covers the Lua migration, the uwsm environment gotcha, the HDR decision, the
full keymap, and troubleshooting.
Log in as "Hyprland (uwsm-managed)", not plain "Hyprland".
Layout
bin/ Small user-facing commands on PATH
config/
bash/ .bashrc, aliases, env (env is gitignored)
copy/ Files copied verbatim over / (needs sudo)
dot/ Symlinked into ~/.config
old/ Backups of whatever was replaced (gitignored)
setup/
packages/ One package per line
scripts/ Run in order by ./install