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

6.8 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.

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.

Accepted hardening uses an atomic same-directory sshd_config.d drop-in, runs sshd -t, then reloads the detected SSH unit. Validation or reload failure restores the previous drop-in before it retries validation and reload; failed recovery stops the handoff with manual recovery instructions. The fixture contracts exercise those branches. panama test --safe never reloads a live daemon, so it is not live-host proof.