Drop the product branding: this is just Settings

It is the system settings app for this desktop, so it is named the way
one is. The window is "Settings", the titlebar is "Settings", the
wordmark above the search field is gone, the sidebar's last row is
"About", and the status line reads "Desktop is healthy".

Prose followed the same rule. Forty-odd strings explained what "Panama"
does -- "Panama never animates while idle", "Restore Panama defaults",
"Panama looks in ~/Pictures/Wallpapers" -- which is how a product
describes itself, not how a settings panel describes a setting. They now
say what happens. No user-visible "Panama" remains anywhere in the app.

Two consequences worth naming:

The SUPER+I shortcut's description is user-visible, because the
Shortcuts page is generated from it, so that is renamed too. Rebindings
are keyed by shipped chord rather than description, so no existing
override is orphaned by this.

Three contracts matched the window by title and one matched that
shortcut by description; all four are updated. There are no Hyprland
window rules keyed on the title, so nothing about the window's placement
changes.

The desktop entry is now Name=Settings, but the FILE keeps its
panama-settings name, as does the icon: the dock pins applications by
desktop id, and renaming the file would silently unpin it.
dock-pins-contract covers exactly that.

The dated design docs under docs/superpowers keep the old name. They are
a record of what was decided when, and editing them to agree with the
present would make them lie about the past.

Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
This commit is contained in:
Gabriel Brown
2026-08-18 10:08:55 -04:00
parent 816ea68f9a
commit 9b2fa80ab7
29 changed files with 88 additions and 87 deletions
+1 -1
View File
@@ -36,7 +36,7 @@ Last live audit: 2026-08-17, Fedora 44, Hyprland 0.56.2, Quickshell 0.3.0.
| Removable media | udiskie plus udisks notifications | Live |
| Autostart apps | Nextcloud, Bitwarden, and RustDesk system service/tray | Live |
| Printer administration | CUPS with the `system-config-printer` graphical interface | Live |
| System settings | Panama Settings for display policy, appearance, desktop, sound, focus, shortcuts, and services; labelled GNOME hardware/account handoffs | Live |
| System settings | The Settings app for display policy, appearance, desktop, sound, focus, shortcuts, and services; labelled GNOME hardware/account handoffs | Live |
## GNOME extension migration
+8 -8
View File
@@ -27,7 +27,7 @@ Don't "fix" them.
| File | Contents |
|---|---|
| `hyprland.lua` | Entry point. Each `require()` is its own error scope |
| `prefs.lua` | Reads the settings file Panama Settings writes. See below |
| `prefs.lua` | Reads the settings file the Settings app writes. See below |
| `env.lua` | Environment. Note the uwsm caveat below |
| `monitors.lua` | DP-2 geometry, scaling, and the HDR decision |
| `looks.lua` | Colours, blur, glow, shadows, animations, VRR, scanout |
@@ -59,7 +59,7 @@ generated elsewhere:
`quickshell/scripts/panama-idle` regenerates the hypridle config from the
settings store and restarts the daemon. `hypridle.conf` in this directory
remains the shipped default and is what runs when the drop-in is not installed;
Panama Settings shows which of the two states you are in rather than presenting
The Settings app shows which of the two states you are in rather than presenting
controls that quietly do nothing.
Remove the drop-in and go back to the shipped config with:
@@ -77,7 +77,7 @@ relationship is:
`prefs.get("key", <shipped value>)`, so the config still works standalone with
no settings file at all.
- **The JSON is the truth.** Hyprland and Quickshell both read it.
- **Panama Settings is the editor.** It writes the file *and* applies the change
- **The Settings app is the editor.** It writes the file *and* applies the change
live, so nothing needs a reload and the two sides cannot drift apart.
To add an adjustable setting: add an entry to
@@ -95,7 +95,7 @@ accepts the config in each of those states.
Every bind in `keybinds.lua` goes through a local `bind()` wrapper that
substitutes the chord from a stored override, so shortcuts can be moved from
Panama Settings without editing this file.
the Settings app without editing this file.
```lua
bind(mod .. " + Q", hl.dsp.window.close(), { description = "Close window" })
@@ -118,7 +118,7 @@ shipped one, so a hand-edited `settings.json` cannot cost you a keymap.
Every `hl.bind` must pass a `description`. Hyprland reports Lua-defined binds
with dispatcher `__lua` and a bytecode offset as the argument, so a bind without
one has nothing readable beside its chord, and Panama Settings drops it from the
one has nothing readable beside its chord, and the Settings app drops it from the
Input & Shortcuts page rather than showing a mystery row.
`tests/quickshell/keybinds-contract.sh` fails if any bind lacks a description, so
this cannot regress silently.
@@ -275,7 +275,7 @@ The mental model is unchanged from Forge:
| `SUPER + V` | Clipboard history |
| `SUPER + .` | Emoji picker |
| `SUPER + S` | Quick settings |
| `SUPER + I` | Panama Settings |
| `SUPER + I` | Settings |
| `SUPER + SHIFT + F` | Start or reveal focus session |
| `SUPER + B` | Notification centre |
| `SUPER + grave` | Workspace overview |
@@ -288,7 +288,7 @@ The mental model is unchanged from Forge:
### Apps
`SUPER + T` terminal · `N` neovim · `W` browser · `F` files · `C` calculator ·
`E` mail · `I` Panama Settings · `CTRL + SHIFT + Esc` system monitor. GNOME
`E` mail · `I` Settings · `CTRL + SHIFT + Esc` system monitor. GNOME
Settings remains searchable in Vicinae for hardware and account panels.
## Calendar and notifications
@@ -326,7 +326,7 @@ one place. Home and Phone continue the same surface rather than opening extra
dashboard windows.
Home shows the first four selected favourites at rest and every selected light
when expanded. Use **Panama Settings → Home & Phone** to choose favourites,
when expanded. Use **Settings → Home & Phone** to choose favourites,
set Panama-only aliases, and arrange their order. Dragging a brightness control
only previews the value; releasing it sends one brightness request. A normal
power toggle leaves Home Assistant responsible for restoring its previous
+1 -1
View File
@@ -80,7 +80,7 @@ bind(mod .. " + W", hl.dsp.exec_cmd(browser), { description = "Browser" })
bind(mod .. " + F", hl.dsp.exec_cmd(files), { description = "Files" })
bind(mod .. " + C", hl.dsp.exec_cmd(calculator), { description = "Calculator" })
bind(mod .. " + E", hl.dsp.exec_cmd(mail), { description = "Mail" })
bind(mod .. " + I", hl.dsp.exec_cmd(settings), { description = "Panama Settings" })
bind(mod .. " + I", hl.dsp.exec_cmd(settings), { description = "Settings" })
bind("CTRL + SHIFT + Escape", hl.dsp.exec_cmd(sysmonitor), { description = "System monitor" })
-- ── Launcher ────────────────────────────────────────────────────────────────
@@ -6,7 +6,7 @@ import qs.services
SettingsPage {
id: root
title: "About Panama"
title: "About"
lede: "A curated Hyprland desktop built around focus, speed, and good taste."
Component.onCompleted: {
@@ -17,7 +17,7 @@ SettingsPage {
}
SettingsCard {
title: "Panama Desktop"
title: "Desktop"
subtitle: "Tokyo Night Moon · Prism glass · native tiling"
TextRow {
@@ -41,15 +41,37 @@ SettingsPage {
}
// What GNOME's About panel answers and this page did not: what am I running
// on. The rows come from MachineInfo, except graphics, which is joined from
// on. Rows come from MachineInfo, except graphics, which is joined from
// GraphicsDevices rather than read a second time -- two readouts of the same
// hardware are two things that can disagree.
//
// The join splices the GPU rows in directly after Processor rather than
// appending them, so the card reads the way fastfetch does: what the system
// is, then what is installed on it, then the hardware underneath. A GPU
// listed after "Disk" reads as an afterthought.
readonly property var machineRows: {
const rows = (MachineInfo.facts ?? []).slice();
const gpus = GraphicsDevices.devices ?? [];
if (gpus.length === 0)
return rows;
const graphics = gpus.map((device, index) => ({
label: gpus.length > 1 ? "Graphics " + (index + 1) : "Graphics",
value: device.name
}));
const after = rows.findIndex(row => row.label === "Processor");
if (after < 0)
return rows.concat(graphics);
return rows.slice(0, after + 1).concat(graphics, rows.slice(after + 1));
}
SettingsCard {
title: "This machine"
subtitle: "Hardware and system, as the kernel reports it."
Repeater {
model: MachineInfo.facts
model: root.machineRows
TextRow {
id: machineRow
@@ -58,27 +80,12 @@ SettingsPage {
label: machineRow.modelData.label
value: machineRow.modelData.value
}
}
Repeater {
model: GraphicsDevices.devices
TextRow {
id: gpuRow
required property var modelData
required property int index
label: GraphicsDevices.devices.length > 1
? "Graphics " + (gpuRow.index + 1)
: "Graphics"
value: gpuRow.modelData.name
divider: gpuRow.index < GraphicsDevices.devices.length - 1
divider: machineRow.index < root.machineRows.length - 1
}
}
TextRow {
visible: MachineInfo.scanned && MachineInfo.facts.length === 0
visible: MachineInfo.scanned && root.machineRows.length === 0
label: "Hardware"
detail: "The system did not report anything readable"
value: "Unavailable"
@@ -25,14 +25,14 @@ SettingsPage {
SettingsCard {
title: "Text"
subtitle: "Scales text in applications. Panama's own panels are drawn at their design size, so the shell is unaffected."
subtitle: "Scales text in applications. The shell's own panels are drawn at their design size, so they are unaffected."
SliderRow { setting: "textScale"; divider: false }
}
SettingsCard {
title: "Motion"
subtitle: "Panama never animates while idle. This affects motion you asked for — windows opening, workspaces sliding, panels appearing."
subtitle: "Nothing animates while idle. This affects motion you asked for — windows opening, workspaces sliding, panels appearing."
ToggleRow { setting: "animationsEnabled"; divider: false }
}
@@ -46,7 +46,7 @@ SettingsPage {
title: "Background"
subtitle: Wallpaper.lastError !== ""
? Wallpaper.lastError
: "Applied to every display. Panama looks in ~/Pictures/Wallpapers, ~/Pictures/Backgrounds, ~/.local/share/backgrounds, and /usr/share/backgrounds."
: "Applied to every display. Looked for in ~/Pictures/Wallpapers, ~/Pictures/Backgrounds, ~/.local/share/backgrounds, and /usr/share/backgrounds."
WallpaperPicker {
id: wallpapers
@@ -184,7 +184,7 @@ SettingsPage {
SettingsCard {
title: "Theme"
subtitle: "Panama has one curated visual identity rather than a matrix of partially compatible themes. The controls above adjust its parameters — how much space, how soft, how much motion — without replacing it."
subtitle: "This desktop has one curated visual identity rather than a matrix of partially compatible themes. The controls above adjust its parameters — how much space, how soft, how much motion — without replacing it."
TextRow { label: "Color palette"; detail: "Tokyo Night Moon"; value: "Prism" }
TextRow { label: "Interface type"; detail: "Adwaita Sans"; value: "System"; divider: false }
@@ -209,7 +209,7 @@ SettingsPage {
SettingsCard {
title: "Compositor autostart"
subtitle: "Panama starts these from Hyprland configuration. They are read-only here."
subtitle: "These are started from the Hyprland configuration. They are read-only here."
TextRow {
visible: !DefaultApps.busy && DefaultApps.luaAutostartEntries.length === 0
@@ -47,7 +47,7 @@ SettingsPage {
SettingsCard {
title: "Window layout"
subtitle: "Panama follows the Forge mental model with native Hyprland tiling."
subtitle: "Follows the Forge mental model, with native Hyprland tiling."
// These were two read-only rows reporting "Tiling" and "Dynamic", which
// described settings rather than facts -- both are ordinary Hyprland
@@ -121,10 +121,10 @@ SettingsPage {
SettingsCard {
title: "Reset"
subtitle: "Restores Panama's appearance, dock, clock, focus, and display policy, and clears your Home accessory arrangement. Pinned applications, files, and paired devices are not changed."
subtitle: "Restores the appearance, dock, clock, focus, and display policy, and clears your Home accessory arrangement. Pinned applications, files, and paired devices are not changed."
ActionRow {
label: "Restore Panama defaults"
label: "Restore defaults"
detail: "Applies immediately, including to the compositor"
action: "Restore defaults"
divider: false
@@ -89,9 +89,12 @@ Rectangle {
}
}
// The real bar carries a clock here, not a name. Standing in with the
// actual time keeps the preview a picture of this desktop rather than
// a picture of a product.
Text {
anchors.centerIn: parent
text: "Panama"
text: Qt.formatTime(new Date(), "h:mm")
color: Theme.alpha(Theme.fg, 0.45)
font.family: Theme.fontFamily
font.pixelSize: 9
@@ -149,7 +149,7 @@ SettingsPage {
ActionRow {
visible: Displays.isOverridden(root.monitor ? root.monitor.name : "")
label: "Using a custom display setting"
detail: "Forget it to go back to the resolution and scale Panama ships"
detail: "Forget it to go back to the shipped resolution and scale"
action: "Forget"
divider: false
onTriggered: Displays.forget(root.monitor.name)
@@ -248,7 +248,7 @@ SettingsPage {
SettingsCard {
title: "Gaming display policy"
subtitle: "Applied immediately and restored when Panama starts."
subtitle: "Applied immediately and restored when the session starts."
ToggleRow { setting: "autoHdr" }
ChoiceRow { setting: "vrrPolicy" }
@@ -9,7 +9,7 @@ SettingsPage {
readonly property string greeting: openedHour < 12 ? "Good morning" : (openedHour < 18 ? "Good afternoon" : "Good evening")
title: `${root.greeting}, Gabriel`
lede: "Your Panama desktop is configured and ready."
lede: "Your desktop is configured and ready."
SettingsCard {
title: SystemSettings.monitorDescription || "Active display"
@@ -202,7 +202,7 @@ SettingsPage {
SettingRow {
label: "Private configuration"
detail: "Saved with owner-only permissions in Panama's private environment file"
detail: "Saved with owner-only permissions in a private environment file"
controlWidth: 216
Row {
@@ -239,7 +239,7 @@ SettingsPage {
SettingRow {
label: "Light catalog"
detail: "Panama reads light state through the Home Assistant helper."
detail: "Light state is read through the Home Assistant helper."
divider: false
controlWidth: 176
@@ -24,7 +24,7 @@ SettingsPage {
TextRow {
label: "Notification history"
detail: "Live notifications retained by Panama"
detail: "Live notifications retained by the shell"
value: `${Notifs.history.length} items`
}
@@ -20,8 +20,8 @@ SettingsPage {
SettingsCard {
title: "Idle behaviour"
subtitle: IdleLock.managed
? "Panama is managing hypridle. Changes take effect immediately."
: "hypridle is running Panama's shipped configuration. Turn on management below to make these adjustable."
? "Idle timings are managed here. Changes take effect immediately."
: "hypridle is running its shipped configuration. Turn on management below to make these adjustable."
SliderRow { setting: "screenBlankMinutes"; zeroLabel: "Never" }
SliderRow { setting: "lockMinutes"; zeroLabel: "Never" }
@@ -41,10 +41,10 @@ SettingsPage {
SettingsCard {
title: "Management"
subtitle: "Panama generates hypridle's configuration into your state directory and points the service at it with a systemd drop-in. ~/.config/hypr is a symlink into the Panama repository, so the shipped configuration cannot be rewritten in place."
subtitle: "hypridle's configuration is generated into your state directory and the service is pointed at it with a systemd drop-in. ~/.config/hypr is a symlink into the configuration repository, so the shipped file cannot be rewritten in place."
SettingRow {
label: "Let Panama manage idle timings"
label: "Manage idle timings here"
detail: IdleLock.serviceState === "active"
? "hypridle is running"
: "hypridle is " + IdleLock.serviceState
@@ -90,7 +90,7 @@ SettingsPage {
SettingsCard {
title: "Owned by Fedora"
subtitle: "File history and trash retention are GNOME preferences, applied by a housekeeping service that does not run in a Hyprland session. Panama does not offer them as switches, because storing that preference here would change nothing."
subtitle: "File history and trash retention are GNOME preferences, applied by a housekeeping service that does not run in a Hyprland session. They are not offered as switches here, because storing that preference would change nothing."
ActionRow {
label: "File history & trash"
@@ -1,4 +1,4 @@
# Panama Settings
# Settings
The control centre for everything Panama owns. Anything the system owns —
hardware, accounts, printers — is delegated to GNOME Settings and labelled as
@@ -55,11 +55,11 @@ SettingsPage {
SettingsCard {
title: "Formats"
subtitle: "Dates, times, and numbers follow the language above. Panama's own clock formatting is on the Appearance page."
subtitle: "Dates, times, and numbers follow the language above. The desktop's own clock formatting is on the Appearance page."
ActionRow {
label: "Clock and date display"
detail: "How Panama itself shows the time"
detail: "How the desktop itself shows the time"
action: "Open appearance"
onTriggered: ShellState.openSettings("appearance")
}
@@ -18,7 +18,7 @@ SettingsPage {
SettingsCard {
title: "Read anything on screen"
subtitle: "Select a region, window, or display. Panama recognizes it locally and gives you clean follow-up actions."
subtitle: "Select a region, window, or display. It is recognized locally, with clean follow-up actions."
SettingRow {
icon: "󰗊"
@@ -52,7 +52,7 @@ SettingsPage {
SettingsCard {
title: "Local recognition"
subtitle: "The screen image stays in Panama's cache and is deleted when you dismiss the result."
subtitle: "The screen image stays in a local cache and is deleted when you dismiss the result."
TextRow {
label: "Text recognition"
@@ -120,7 +120,7 @@ SettingsPage {
SettingsCard {
title: "Fedora system settings"
subtitle: "Panels Panama does not own, because they configure system services rather than the desktop. Each row opens the panel that actually owns it. Printers and online accounts live with the rest of the network hardware, on Network & Devices."
subtitle: "Panels this app does not own, because they configure system services rather than the desktop. Each row opens the panel that actually owns it. Printers and online accounts live with the rest of the network hardware, on Network & Devices."
// This was one row listing five subjects and opening the network panel
// regardless. Naming a panel and then not opening it is worse than not
@@ -40,7 +40,7 @@ Rectangle {
anchors.left: parent.left
anchors.leftMargin: 18
anchors.verticalCenter: parent.verticalCenter
text: "Panama Settings"
text: "Settings"
color: Theme.fg
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSize
@@ -40,7 +40,7 @@ Rectangle {
{ page: "datetime", label: "Date & Time", icon: "\u{F0954}" },
{ page: "applications", label: "Applications", icon: "\u{F003B}" },
{ page: "services", label: "Startup & Services", icon: "\u{F0493}" },
{ page: "about", label: "About Panama", icon: "\u{F02FD}" }
{ page: "about", label: "About", icon: "\u{F02FD}" }
]
width: 272
@@ -59,15 +59,6 @@ Rectangle {
height: implicitHeight
spacing: 12
Text {
text: "PANAMA"
color: Theme.fg
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeLarge
font.weight: Font.DemiBold
font.letterSpacing: 2.2
}
Rectangle {
width: parent.width
height: 36
@@ -317,7 +308,7 @@ Rectangle {
anchors.left: parent.left
anchors.leftMargin: 36
anchors.verticalCenter: parent.verticalCenter
text: "Panama desktop is healthy"
text: "Desktop is healthy"
color: Theme.fgDim
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall
@@ -8,7 +8,7 @@ FloatingWindow {
readonly property var homePhoneDiagnostics: settingsShell.homePhoneDiagnostics
title: "Panama Settings"
title: "Settings"
visible: ShellState.settingsOpen
implicitWidth: 1120
implicitHeight: 760
@@ -150,7 +150,7 @@ SettingsPage {
SettingsCard {
visible: Object.keys(Keybinds.overrides).length > 0
title: "Changed shortcuts"
subtitle: "Rebinding stores only the new chord; what a shortcut does always comes from Panama's configuration."
subtitle: "Rebinding stores only the new chord; what a shortcut does always comes from the desktop's configuration."
ActionRow {
label: "Restore every shipped shortcut"
@@ -156,7 +156,7 @@ Item {
width: parent.width - 40
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
text: "No images found. Panama looks in ~/Pictures/Wallpapers, ~/Pictures/Backgrounds, ~/.local/share/backgrounds, and /usr/share/backgrounds."
text: "No images found. Looked in ~/Pictures/Wallpapers, ~/Pictures/Backgrounds, ~/.local/share/backgrounds, and /usr/share/backgrounds."
color: Theme.fgMuted
font.family: Theme.fontFamily
font.pixelSize: Theme.fontSizeSmall