Files
Panama/.claude/skills/panama/SKILL.md
T

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, the panama command, how installing and updating work
  • config/dot/hypr/README.md — the compositor config is Lua, not hyprlang; read "The one thing to know first" and "Never use hyprctl keyword" before touching it
  • config/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 here
  • docs/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.

  1. 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.
  2. 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
  3. Every .qml file in config/dot/quickshell/modules/* must be registered in that directory's qmldir in the same save batch. An unregistered component fails the whole configuration and takes down the bar, dock, and settings together. tests/quickshell/qmldir-registration-contract is pure file inspection — run it before the change lands.
  4. Never qs kill from 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 from qs list --all, and kill that PID.
  5. Never hyprctl keyword — Lua-configured Hyprland refuses it, prints to stdout, and exits 0. hyprctl eval also exits 0 on errors. The only proof a write landed is hyprctl getoption reading it back. Batch hyprctl reload to one per verified change-set, and say when you do it.
  6. IPC: annotate every parameter and return type or Quickshell silently skips registration; never duplicate an IpcHandler target — one silently shadows the other.
  7. In config/dot/quickshell/config/PreferenceSchema.qml, readAs describes the compositor's ANSWER shape, not the setting's; a wrong one makes every successful write look rejected.
  8. No continuously repainting animations (pulse, shimmer, spinners) — they peg the GPU on high-refresh displays.
  9. hyprlock.conf, hypridle.conf, hyprpaper.conf, hyprtoolkit.conf never moved to Lua. Do not "fix" them. Do not install a notification daemon — the shell is one.
  10. Scripts carry no .sh extension (shebang + chmod +x), with one deliberate exception: migrations/*.sh, which bin/panama-migrate globs. No secrets under user/ — it is world-readable and tests/setup/user-content-contract greps 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]. --safe selects only contracts classified as hermetic.
  • 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_SECONDS value. 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.qml or services/SettingsRoutes.qml, regenerate: config/dot/quickshell/scripts/panama-settings-docs (writes docs/settings.md) and config/dot/quickshell/scripts/panama-settings-commands (writes the launcher deep links). Both take --check; tests/quickshell/settings-docs-contract fails when stale.
  • README.md pins the contract count and the panama subcommand 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: ConfirmAction with a unique actionId, arbitrated through ShellState.armedConfirm — one armed confirm app-wide. Danger tone marks only the confirming press.
  • Failures render through ErrorRow; honest empty states through NotMeasuredRow with a because:; paragraph-length notes through SettingsNote.
  • 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.json may 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.