Phase 5. The README advertised two desktops that coexist -- GNOME with Forge, Dash-to-Dock, Openbar and Vitals, alongside Hyprland -- and nothing in setup/ installed or configured any of the first one. Panama configures one desktop, and now says so. config/dot/forge is deleted along with its entry in link-dotfiles. It was the hedge from when the GNOME session was still the fallback and Hyprland was being built beside it; the hedge has been paid off. Nine files, six of which were Forge's own editor backups that should never have been committed. Searching for the rest of GNOME found nothing else to cut, which is recorded in the spec so nobody goes looking again. change-settings never enabled an extension. The mentions of Dash-to-Dock, Openbar and Vitals through the shell are comments saying what a component was modelled on -- which intellihide behaviour the dock reproduces, where a colour came from -- and DESKTOP-PARITY.md is the table of what replaced what. That is provenance, and it is the reason those components behave the way they do. Vitals in services/ is Panama's own bar service and merely shares a name with the extension it replaced. The handoff panel list was wrong in two places. It named Wacom, which nothing hands off to, and Region, which is a subpage of System rather than a panel. The nine real ones are read off the call sites and the allow-list that gates them. The spec said it, the comment on gnome-control-center repeated it, and the README would have made it three. One test gap turned up and is closed. The assets contract caught a directory under config/dot/ that nothing links, but not the inverse: a name left in the dirs array with nothing behind it, which makes link-dotfiles point ~/.config/<name> at a path that does not exist. Deleting Forge is the exact move that introduces that, and nothing would have failed if the array entry had been left. A dangling symlink is worse than a missing one, because everything that looks there finds something. Verified by putting the entry back and watching it fail. The audit of docs/settings.md this phase asked for needed nothing: it is generated from PreferenceSchema.qml, a contract already fails when it goes stale, and it carries no claim about GNOME or Forge. The README gained the section it was missing instead -- the 121 contracts under tests/ were the main safety net in this repository and went entirely unmentioned in it. Claude-Session: https://claude.ai/code/session_01NvgBuSWB5sE43yWmg21ozj
5.6 KiB
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), the package lists in setup/packages/, then whichever optional categories were chosen |
link-dotfiles |
Symlinks config/dot/<name> → ~/.config/<name>, and seeds the wallpaper, cursor theme and Firefox chrome |
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 enrollment, Fedora's extras, firmware — each only if it was asked for. Last, because enrollment 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.
Optional applications
Every machine gets the lists in setup/packages/. The interview also offers the
categories in setup/packages/extras/ as a checklist, so a work laptop need not
acquire emulators and a desktop need not skip Steam. Nothing is preselected.
A category is one file. A bare line is a dnf package and a flatpak: line is a
Flathub ID, because the applications in a category do not all come from one
place. Adding a category is adding a file — the menu is read from the directory,
not written down anywhere.
Existing configs are moved to config/old/ rather than overwritten.
The desktop
Hyprland, with a shell written from scratch. It began as a replacement for a GNOME session — Forge for tiling, Dash-to-Dock, Openbar, Vitals — and was built to reproduce it closely enough that muscle memory transferred: same keybinds, same panel contents, same dock, same Tokyo Night Moon palette.
That is history now rather than a second option. Panama installs and configures
one desktop, and the GNOME session it grew out of is neither installed nor
configured here. What each piece replaced is recorded in
config/dot/hypr/DESKTOP-PARITY.md and in
the comments of the components themselves, because knowing what a thing was
modelled on explains why it behaves the way it does.
GNOME is not gone from the machine: gnome-control-center is a declared
dependency, and Panama's own Settings hands off to it for the panels it
deliberately does not own — Online Accounts, Color, Sound, Network, Keyboard,
Privacy, Wellbeing, Accessibility, and System for users, date and time, region
and remote desktop. The allow-list in
services/SystemSettings.qml
is what decides; anything not on it is a panel Panama owns itself.
| 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
firefox/ Vendored Firefox chrome, linked into the browser profile
local/ Icons and the cursor theme, linked into ~/.local/share
old/ Backups of whatever was replaced (gitignored)
wallpapers/ Copied into ~/Pictures/Wallpapers when absent
setup/
packages/ One package per line; extras/ holds the optional categories
scripts/ Run in order by ./install
tests/ Contracts. See below
docs/ Settings reference, and the design specs behind the work
Tests
121 of them, under tests/, and each is a plain executable you can run on its
own:
bash tests/setup/interview-contract
They are called contracts rather than unit tests because that is what they are:
each one pins a decision that was expensive to get right and is cheap to undo by
accident. Most read or measure the real thing — launching a shell to measure a
surface's geometry, standing stub commands on PATH to see what a stage would
have installed, running a script against a throwaway HOME — rather than
asserting things about source text, because the bugs worth catching here have all
been ones that source text looked fine for.
tests/setup/ The installer: the interview, package lists, hardware, extras
tests/quickshell/ The shell and its settings pages
tests/hypr/ The compositor config