Take one machine's fingerprints off everyone's desktop

The audit's second tier: values that were measurements of the author's
desktop, shipped to every machine as if they were defaults.

Settings greeted every human as Gabriel; it now greets whoever
accountsservice says is signed in, and nobody when it says nothing. The
weather shipped his home coordinates and confidently reported his forecast
anywhere on earth; it now ships unset, fetches nothing until a location is
chosen, and the location row says so. The GTK bookmarks carried seven
/home/gib paths and his file server into every file dialog; they are now
generated per machine from a template and gitignored -- Nautilus edits the
instance freely, the way settings.ini already worked one file over. Web
search routed through his personal bang redirector; the engine is now the
webSearchUrl preference with a DuckDuckGo default, read by both the script
command and the suggestions extension, which the launcher-search contract
already pins to one another. The GPU vitals path defaulted to his card1 and
lost the readout on any machine enumerated differently; a machine with
exactly one GPU now adopts it. And the Containers and Snapshots pages hide
once a scan proves their backing stack absent, instead of rendering
permanently empty on machines that never had podman or snapper.

Lesser residue swept in the same pass: the DP-2 hyprpaper block one machine
needed, the author's username-typo expansions (moved to his personal seed in
user/, where personal content belongs), a capture fallback into /home/gib,
and a parity table asserting one machine's hardware as fact.

Claude-Session: https://claude.ai/code/session_01Epx9ZC1gwm81K3jm9x9CKh
This commit is contained in:
Gabriel Brown
2026-08-23 11:55:43 -04:00
parent 3d21e20041
commit 44124d72fa
20 changed files with 139 additions and 42 deletions
+1
View File
@@ -21,6 +21,7 @@ __pycache__/
# Generated from the color scheme; machine state, not configuration.
/config/dot/gtk-3.0/settings.ini
/config/dot/gtk-3.0/bookmarks
/config/dot/gtk-4.0/settings.ini
/config/dot/tmux/current-theme.conf
/config/dot/hypr/hyprlock.conf
-12
View File
@@ -139,18 +139,6 @@ matches:
- trigger: "dokcer"
replace: "docker"
- trigger: "gborwn"
replace: "gbrown"
- trigger: "gbrwon"
replace: "gbrown"
- trigger: "gbronw"
replace: "gbrown"
- trigger: "grbown"
replace: "gbrown"
- trigger: "restrat"
replace: "restart"
-8
View File
@@ -1,8 +0,0 @@
file:///home/gib/Documents Documents
file:///home/gib/Documents/Code Code
file:///home/gib/Downloads Downloads
file:///home/gib/Music Music
file:///home/gib/Pictures Pictures
file:///home/gib/Videos Videos
file:///home/gib/.local/share/Panama Panama
smb://server-gib.local/homes/ Gib's Server
+6
View File
@@ -0,0 +1,6 @@
file://$HOME/Documents Documents
file://$HOME/Downloads Downloads
file://$HOME/Music Music
file://$HOME/Pictures Pictures
file://$HOME/Videos Videos
file://$HOME/.local/share/Panama Panama
+1 -1
View File
@@ -25,7 +25,7 @@ Last live audit: 2026-08-17, Fedora 44, Hyprland 0.56.2, Quickshell 0.3.0.
| Calendar agenda | Existing GNOME, Google, iCloud, and Nextcloud sources through Evolution Data Server | Live |
| Control Center | Wi-Fi, Bluetooth, audio input/output, Caffeine, Night Light, Focus, Home Assistant favorites, and KDE Connect phone continuity | Live |
| Focus sessions | Persistent workspace-bound timer, DND/caffeine coordination, Signal Glass controls | Live |
| Brightness | Appears only when a backlight device exists | Live, not applicable on this monitor |
| Brightness | Appears only when a backlight device exists | Live where the hardware exposes it |
| AppIndicator / tray | Native StatusNotifierItem host and themed menus | Live |
| Screenshot and recording | Quickshell picker, grim/slurp/satty/wf-recorder | Live |
| Screen text and code recognition | Local Tesseract/ZBar Read mode, selectable Prism result sheet | Live after package install |
+4 -8
View File
@@ -17,20 +17,16 @@
# frame time for nothing.
# ─────────────────────────────────────────────────────────────────────────────
# One block for every output: per-monitor wallpaper is applied at runtime by
# the shell (services/Wallpaper.qml) over IPC, so a per-connector block here
# would just be one machine's connector name in everyone's config.
wallpaper {
monitor = DP-2
monitor =
path = ~/Pictures/Wallpapers/faroe_islands.jpg
# cover = fill the output, cropping overflow. Matches the "zoom" picture
# option this setup used under GNOME.
fit_mode = cover
}
# Fallback for any output without its own block above.
wallpaper {
monitor =
path = ~/Pictures/Wallpapers/faroe_islands.jpg
fit_mode = cover
}
ipc = on
splash = false
@@ -1297,28 +1297,44 @@ Singleton {
detail: "Which GPU the graphics readout in the bar measures"
},
// ── Search ──────────────────────────────────────────────────────────
// The launcher's web search appends the query to this. It shipped
// pointing at the author's personal bang redirector once; a stranger's
// searches belong to no one's server but the engine they chose.
{
key: "webSearchUrl", type: "string",
def: "https://duckduckgo.com/?q=", group: "search",
pattern: "^https://[^\\s]{1,200}$",
label: "Web search engine",
detail: "Where the launcher's web search sends a query; the search text is appended"
},
// ── Weather location ────────────────────────────────────────────────
// Coordinates rather than a place name, because that is what Open-Meteo
// takes and it needs no API key. weatherLocation is only the label shown
// in the UI; it is never sent anywhere, so it can say whatever makes the
// reading recognizable.
{
key: "weatherLatitude", type: "real", def: 27.7375, min: -90, max: 90, step: 0.0001,
key: "weatherLatitude", type: "real", def: 0, min: -90, max: 90, step: 0.0001,
group: "weather", internal: true,
label: "Latitude",
detail: "Set by choosing a location"
},
{
key: "weatherLongitude", type: "real", def: -82.6861, min: -180, max: 180, step: 0.0001,
key: "weatherLongitude", type: "real", def: 0, min: -180, max: 180, step: 0.0001,
group: "weather", internal: true,
label: "Longitude",
detail: "Set by choosing a location"
},
// Empty until a location is chosen. The shipped value was once the
// author's home town, which confidently reported his weather on every
// machine anywhere; an unset location fetches nothing and says so
// instead.
{
key: "weatherLocation", type: "string", def: "Local weather", group: "weather",
key: "weatherLocation", type: "string", def: "", group: "weather",
internal: true,
// Display only -- never sent to the weather service.
pattern: "^[^\\n]{1,64}$",
pattern: "^[^\\n]{0,64}$",
label: "Weather location",
detail: "The place the weather reading is for"
},
@@ -207,6 +207,8 @@ SettingsPage {
title: "Search"
subtitle: "Applications, files, the calculator, clipboard history, emoji, and open windows are all searched from the launcher."
TextEntryRow { setting: "webSearchUrl"; placeholder: "https://duckduckgo.com/?q=" }
TextRow {
label: "Launcher"
detail: SystemSettings.vicinaeActive
@@ -96,7 +96,17 @@ SettingsPage {
return match[2] ? match[1] + " " + match[2].toUpperCase() : match[1];
}
title: `${root.greeting}, Gabriel`
// Greets whoever is signed in, from the same accountsservice record the
// lock screen shows. This once hardcoded the author's first name, which
// made the first screen of Settings wrong for every other human.
readonly property string greetingName: {
if (!UserAccounts.me)
return "";
const full = UserAccounts.displayName(UserAccounts.me);
return full.split(" ")[0] || "";
}
title: root.greetingName !== "" ? `${root.greeting}, ${root.greetingName}` : root.greeting
lede: Weather.available
? Math.round(Weather.temperature) + Weather.unitSuffix + " and "
+ Weather.description.toLowerCase() + " in " + Settings.weatherLocation
@@ -275,7 +285,7 @@ SettingsPage {
label: "Location"
detail: "Only the search term is sent; the name is a label kept on this machine"
value: Settings.weatherLocation
value: Settings.weatherLocation !== "" ? Settings.weatherLocation : "Not set — choose one to see weather"
LocationPicker {
width: parent.width
@@ -55,6 +55,22 @@ Rectangle {
{ page: "about", label: "About", icon: "\u{F02FD}" }
]
// Pages whose entire backing stack can be absent hide once a scan has
// proven it absent: a Containers page with no podman and a Snapshots page
// with no snapper configuration render permanently empty, which reads as
// broken rather than inapplicable. Until the scan lands they stay
// visible, so machines that have the stack never see a blink -- and both
// scans fire when Settings opens (HomePage.onCompleted).
function pageAvailable(page: string): bool {
switch (page) {
case "containers":
return !Containers.scanned || Containers.available;
case "snapshots":
return !Snapshots.scanned || Snapshots.configs.length > 0;
}
return true;
}
width: 272
color: Theme.alpha(Theme.bgDark, 0.96)
border.width: 0
@@ -236,6 +252,7 @@ Rectangle {
Rectangle {
id: navItem
required property var modelData
visible: root.pageAvailable(modelData.page)
width: parent.width
height: 40
radius: 10
+1 -1
View File
@@ -76,7 +76,7 @@ Singleton {
property real coordinateScale: 1.0
// ── Paths ───────────────────────────────────────────────────────────────
readonly property string _home: Quickshell.env("HOME") || "/home/gib"
readonly property string _home: Quickshell.env("HOME") || ""
// Both folders are settings now rather than a choice of three, so both can
// name somewhere outside home -- a second drive, a network mount. Prefixing
@@ -42,6 +42,13 @@ Singleton {
const parsed = JSON.parse(this.text);
root.devices = Array.isArray(parsed) ? parsed : [];
root.lastError = "";
// The shipped default is one machine's card index, and
// card numbering means nothing across machines. When the
// stored path is not present here and there is exactly
// one real answer, adopt it -- a single-GPU laptop should
// not lose its vitals readout to a desktop's enumeration.
if (root.selectionMissing && root.devices.length === 1)
root.select(root.devices[0].path);
} catch (error) {
root.devices = [];
root.lastError = "The graphics devices could not be read.";
@@ -54,7 +54,8 @@ Singleton {
"weather": "home",
"notifications": "notifications",
"capture": "screen-intelligence",
"gaming": "gaming"
"gaming": "gaming",
"search": "applications"
})
// Settings that are real but have no schema entry, because the system owns
@@ -59,7 +59,15 @@ Singleton {
}
}
// Nothing was chosen yet: fetch nothing, claim nothing. The card offers
// the location picker instead.
readonly property bool configured: Settings.weatherLocation !== ""
function refresh(): void {
if (!root.configured) {
root.available = false;
return;
}
// Skip if the previous fetch is somehow still in flight.
if (!fetch.running)
fetch.running = true;
@@ -6,7 +6,25 @@ import { Action, ActionPanel, Icon, List } from "@vicinae/api";
// search engine to be bounced, and falls through to an ordinary search when
// there is no bang. Bang support is a property of this URL, not of this
// extension, which is why there is no bang parsing below.
const ENGINE = "https://bang.gibbyb.com/?q=";
// The engine is Panama's webSearchUrl preference (Applications page), the
// same key the fallback script command reads -- launcher-search-contract pins
// the two to one default. Read once per command launch; DuckDuckGo when the
// preference is unset or unreadable.
const DEFAULT_ENGINE = "https://duckduckgo.com/?q=";
const ENGINE = (() => {
try {
const configHome =
process.env.XDG_CONFIG_HOME || `${process.env.HOME}/.config`;
const stored = JSON.parse(
require("fs").readFileSync(`${configHome}/panama/settings.json`, "utf8"),
).webSearchUrl;
return typeof stored === "string" && stored.startsWith("https://")
? stored
: DEFAULT_ENGINE;
} catch {
return DEFAULT_ENGINE;
}
})();
// The suggestion endpoint Firefox's address bar uses. Answers with
// [query, [suggestion, ...], ...] and needs no key.
@@ -25,5 +25,8 @@
#
# xdg-open rather than a named browser: the default browser is already a setting
# this desktop owns, on the Applications page, and naming one here would quietly
# outrank it.
exec xdg-open "https://bang.gibbyb.com/?q=$1"
# outrank it. The engine is the webSearchUrl preference (Applications page);
# the shipped default asks DuckDuckGo, not somebody's personal redirector.
search_url="$(jq -r '.webSearchUrl // empty' "${XDG_CONFIG_HOME:-$HOME/.config}/panama/settings.json" 2>/dev/null)"
[ -n "$search_url" ] || search_url="https://duckduckgo.com/?q="
exec xdg-open "${search_url}$1"
@@ -5,6 +5,6 @@
# @vicinae.mode silent
# @vicinae.icon ../../icons/hicolor/scalable/apps/panama-settings.svg
# @vicinae.description Open Applications in Settings.
# @vicinae.keywords ["settings", "default applications"]
# @vicinae.keywords ["settings", "web search engine", "default applications"]
exec "$HOME/.config/quickshell/scripts/panama-action" settings-page applications
+9 -1
View File
@@ -4,7 +4,7 @@
Do not edit this file. Run `quickshell/scripts/panama-settings-docs`
after changing the schema; a contract fails when this copy is stale.
148 settings across 29 groups. 70 of them are applied to the compositor and confirmed by reading the value back.
149 settings across 30 groups. 70 of them are applied to the compositor and confirmed by reading the value back.
## accessibility
@@ -255,6 +255,14 @@ Found on **Mouse & Touchpad**.
| **Left-handed**<br>`leftHanded` `input:left_handed` | false | Swap the primary and secondary buttons |
| **Middle-click paste**<br>`middleClickPaste` `misc:middle_click_paste` | true | Paste the primary selection in GTK and native Wayland applications |
## search
Found on **Applications**.
| Setting | Default | What it does |
|---|---|---|
| **Web search engine**<br>`webSearchUrl` | https://duckduckgo.com/?q= | Where the launcher's web search sends a query; the search text is appended |
## themes
Found on **Appearance**.
+16
View File
@@ -255,6 +255,22 @@ for icon_file in "$PANAMA_ICON_DIR"/*.svg; do
done
gtk-update-icon-cache -f -t "$HOME/.local/share/icons/hicolor" 2>/dev/null || true
# File-manager sidebar bookmarks, generated per machine from the template.
# The tracked file used to carry absolute /home/<author> paths -- seven dead
# sidebar entries in every file dialog for anyone else. Nautilus edits the
# generated instance in place (Ctrl+D writes this file through the symlink),
# which is exactly why it is gitignored: bookmarks are user data, not config.
BOOKMARKS_TEMPLATE="$PANAMA_DOT/gtk-3.0/bookmarks.template"
BOOKMARKS_FILE="$PANAMA_DOT/gtk-3.0/bookmarks"
if [ -r "$BOOKMARKS_TEMPLATE" ]; then
if [ -e "$BOOKMARKS_FILE" ]; then
log "Keeping existing GTK bookmarks at $BOOKMARKS_FILE"
else
sed "s|\$HOME|$HOME|g" "$BOOKMARKS_TEMPLATE" > "$BOOKMARKS_FILE"
log "Generated GTK bookmarks for $HOME"
fi
fi
# The pointer theme. oreo_blue_cursors is packaged by no Fedora repository -- it
# is a GitHub project -- so rather than download it at install time and depend on
# a URL that can rot, the theme is vendored into this repository and exposed the
+8
View File
@@ -9,3 +9,11 @@ matches:
replace: "[email protected]"
- trigger: ":empro"
replace: "[email protected]"
- trigger: "gborwn"
replace: "gbrown"
- trigger: "gbrwon"
replace: "gbrown"
- trigger: "gbronw"
replace: "gbrown"
- trigger: "grbown"
replace: "gbrown"