8.3 KiB
name, description
| name | description |
|---|---|
| panama | Use when working on the Panama repository itself — editing anything under config/, setup/, bin/, tests/, or the Quickshell shell and Hyprland Lua it ships. Covers the live-desktop hot-reload rules, the contract-test discipline, the fixture seams, and where the real documentation lives. |
panama
You are editing a running desktop, not a codebase that gets deployed later. Every dotfile in this
repository is symlinked into ~/.config, so a save is live the moment it lands. That single fact
drives every rule below.
Read before large work, in this order:
README.md— layout, thepanamacommand, how installing and updating workconfig/dot/hypr/README.md— the compositor config is Lua, not hyprlang; read "The one thing to know first" and "Never usehyprctl keyword" before touching itconfig/dot/quickshell/modules/settings/README.md— adding a setting, setting ownership, "Things that will bite you", and where state lives; the most load-bearing document heredocs/settings.md— generated reference for every settings key (never edit by hand)
The live-desktop covenant
Editing config/dot/quickshell/** hot-reloads the live shell on every save.
- Every save must leave valid QML. An intermediate broken save is a broken desktop, not a broken build. Convert a component and its body in ONE edit, never two.
- After each batch of saves, check the journal for errors AND "Unable to assign" warnings:
journalctl --user -u panama-quickshell.service --since '-2 minutes' --no-pager - Every
.qmlfile inconfig/dot/quickshell/modules/*must be registered in that directory'sqmldirin the same save batch. An unregistered component fails the whole configuration and takes down the bar, dock, and settings together.tests/quickshell/qmldir-registration-contractis pure file inspection — run it before the change lands. - Never
qs killfrom a copied configuration: Quickshell derives the shell ID from config content, so a content-identical harness can share the live shell's ID and kill the desktop. Harnesses use a distinct entry file,qs -p, the PID fromqs list --all, andkillthat PID. - Never
hyprctl keyword— Lua-configured Hyprland refuses it, prints to stdout, and exits 0.hyprctl evalalso exits 0 on errors. The only proof a write landed ishyprctl getoptionreading it back. Batchhyprctl reloadto one per verified change-set, and say when you do it. - IPC: annotate every parameter and return type or Quickshell silently skips registration; never
duplicate an
IpcHandlertarget — one silently shadows the other. - In
config/dot/quickshell/config/PreferenceSchema.qml,readAsdescribes the compositor's ANSWER shape, not the setting's; a wrong one makes every successful write look rejected. - No continuously repainting animations (pulse, shimmer, spinners) — they peg the GPU on high-refresh displays.
hyprlock.conf,hypridle.conf,hyprpaper.conf,hyprtoolkit.confnever moved to Lua. Do not "fix" them. Do not install a notification daemon — the shell is one.- Scripts carry no
.shextension (shebang +chmod +x), with one deliberate exception:migrations/*.sh, whichbin/panama-migrateglobs. No secrets underuser/— it is world-readable andtests/setup/user-content-contractgreps for key material.
The contract discipline
Every executable contract under tests/ is classified in tests/contracts.manifest. The rules:
panama contracts <file>names the contracts that mention a file; run those after touching it.- During a desktop session, run
panama test --safe [pattern].--safeselects only contracts classified ashermetic. - A plain full run prompts in a terminal before any selected non-hermetic contract starts. In
automation, grant every required capability with repeatable flags, for example
panama test --allow live-compositor --allow live-desktop keybinds. - Each contract has a 180-second outer timeout by default. Override it with a positive
PANAMA_TEST_TIMEOUT_SECONDSvalue. Failures print the contract's captured stdout and stderr. Successful stdout stays quiet. Successful stderr is surfaced as a warning. - Contracts run directly too:
tests/setup/interview-contract. - After changing
PreferenceSchema.qmlorservices/SettingsRoutes.qml, regenerate:config/dot/quickshell/scripts/panama-settings-docs(writesdocs/settings.md) andconfig/dot/quickshell/scripts/panama-settings-commands(writes the launcher deep links). Both take--check;tests/quickshell/settings-docs-contractfails when stale. README.mdpins the contract count and thepanamasubcommand list (tests/setup/readme-contract); adding a contract or subcommand means updating it.
Seams for testing
Helpers are built hermetic: validated inputs, JSON out, secrets on stdin only (never argv).
Contracts reach them through env seams — PANAMA_NETWORK_HELPER, PANAMA_FINGERPRINT_FIXTURE,
PANAMA_EXTRAS_DIR, and the PANAMA_*_STATIC_ONLY family that cuts a contract to its
file-inspection half. Prefer exercising a helper through its contract's stubbed PATH over running
it against the real system.
Safety idioms (contract-enforced)
- Destructive actions are two-stage:
ConfirmActionwith a uniqueactionId, arbitrated throughShellState.armedConfirm— one armed confirm app-wide. Danger tone marks only the confirming press. - Failures render through
ErrorRow; honest empty states throughNotMeasuredRowwith abecause:; paragraph-length notes throughSettingsNote. - Stored user actions (custom shortcuts, gestures, window rules) are DATA — an enum kind and a
validated target resolved through whitelist tables in
config/dot/hypr/actions.lua. Nothing in~/.config/panama/settings.jsonmay ever be an executable command; the contracts (tests/quickshell/settings-idiom-contract,tests/quickshell/keybind-rebind-contract) pin all of this.
Root work
Never bare sudo. Load the panama-sudo skill first. Migrations already follow the rule.
Initial bootstrap trust
Use the complete command in README.md for a new machine. It downloads boot
from the documented commit URL into a private temporary directory, enforces the
documented curl time and byte limits, verifies the committed blob with
sha256sum -c, and passes both pins to the verified script. Desktop and server
bootstrap use the same commit and digest. Never substitute a branch URL, pipe a
response into Bash, or invent a newer pin from an uncommitted file.
boot validates the full lowercase commit and SHA-256 before Git or install. A
fresh destination fetches only that revision and creates a tracked local main
after HEAD matches. An existing checkout must be clean and an ancestor of the
requested revision; it advances with fast-forward only. Dirty, divergent,
fetch-failed, or mismatched checkouts stop without reset or install. Once Panama
exists, use panama update for normal updates.
boot --server is the one exception where a new Fedora VPS may begin as root.
Before it offers SSH hardening, it copies a safe root key when possible or
verifies the target key. The target user's .ssh must be owned by that user at
0700, and authorized_keys must be owned by that user at 0600. Without a
verified target key, SSH hardening is unavailable and the bootstrap continues.
Every non-comment key line must parse with ssh-keygen. Root-key destination
creation and writing run as the target UID, followed by the same owner, mode,
and key checks. Do not replace that with root writes or assume the user's
primary group matches the username.
Accepted hardening uses atomic same-directory 00-panama.conf with exactly
PermitRootLogin no, PasswordAuthentication no, and
KbdInteractiveAuthentication no. A pre-existing symlink or non-regular
object makes hardening unavailable, as does a missing SSH unit. Panama runs
sshd -t, then checks effective root and target-user policy with sshd -T -C
before reloading the detected unit. Validation or reload failure restores a
prior regular file with its metadata before it retries validation and reload.
Failed recovery stops the handoff with instructions that distinguish a prior
file from no prior file. The fixture contracts also cover declined hardening
and interrupted preparation. panama test --safe never reloads a live daemon,
so it is not live-host proof.