# Panama Formerly Sunhat. A personal config for Fedora, with the intention of helping a user set up their Fedora system with one command. ```sh 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/` → `~/.config/`, 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`](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`](config/dot/quickshell/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`](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; `panama` is the entry point 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/`. Run the lot, or a subset by pattern: ```sh panama test # everything panama test dock # just the ones matching "dock" tests/setup/interview-contract # or one directly; they are plain executables ``` 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 ``` ## The `panama` command ```sh panama update # review, commit and sync this repo panama edit # open it in Neovim panama doctor # what is actually running, not what was installed panama test # every contract, or a subset by pattern panama upgrade # re-run ./install from anywhere ``` None of the scripts in this repository carry a `.sh` extension. A shebang and the executable bit already select the interpreter, and the extension only becomes something to keep in sync — which it did not stay.