Watch
1
0
Fork
You've already forked souveraine
0
souveraine/surfaces/quickshell/modules/common/Config.qml
Fimeg 8f42fc953d publish: the public projection begins here
This is a projection, not a development branch. The tree above was constructed
from the internal source named below under a manifest that decides which paths
may leave, then scanned as a whole tree rather than as a series of patches, and
only then published.

Public history starts here because the history before it was not admissible,
and neither was the tree. What used to stand in this repository included a
rescue copy of another machine, a directory of phone handoffs, deployment
wired to one house, and a submodule pointing at a forge no stranger can reach.
None of that was ever the product. It stays in the private forge, which is
allowed to hold the whole working organism, and this is what was deliberately
sent out instead.

Three mechanisms produced this tree, in decreasing order of trust. A top-level
path the manifest does not name never arrives at all, which is the one that
catches directories nobody has thought of yet. Named internal files inside
admitted roots are dropped. A short, reviewed table replaces deployment
defaults that a public build must not carry -- an endpoint aimed at one LAN, a
VPN profile belonging to one phone, packaging built from one checkout path.

Everything after this commit is an ordinary publication with the same three
trailers, so a force push stops being routine and starts meaning that
something deliberate happened. The trailers bind the projection to its source
without pretending the public SHA is the private one: same lineage, different
tree, and the record says so.

Source-Sha: 8f27b1e76a8fef560a336aba18e6990713ff1047
Policy-Sha: 6b261d2f3e6e1fb19874846ba4bb1dfe15565d25b8618c1c1afba0419c101d27
Tree-Digest: 18ec3563c5e5ef9a414993a9f6734b251ff9ed3cd56eebdd6cac01e45c6e3067
2026-09-04 15:55:48 -04:00

933 lines
49 KiB
QML

pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Io
import qs.modules.common.functions
Singleton {
id: root
property string filePath: Directories.shellConfigPath
property alias options: configOptionsJsonAdapter
property bool ready: false
property int readWriteDelay: 50 // milliseconds
property bool blockWrites: false
// Tri-state option: "auto" (or anything unrecognized) defers to the
// caller's default, "on"/"off" force it. Booleans are honored so old
// configs written before the string form keep working.
function tristate(value, fallback) {
if (value === "on" || value === true) return true;
if (value === "off" || value === false) return false;
return fallback;
}
function setNestedValue(nestedKey, value) {
let keys = nestedKey.split(".");
let obj = root.options;
let parents = [obj];
// Traverse and collect parent objects
for (let i = 0; i < keys.length - 1; ++i) {
if (!obj[keys[i]] || typeof obj[keys[i]] !== "object") {
obj[keys[i]] = {};
}
obj = obj[keys[i]];
parents.push(obj);
}
// Convert value to correct type using JSON.parse when safe
let convertedValue = value;
if (typeof value === "string") {
let trimmed = value.trim();
if (trimmed === "true" || trimmed === "false" || !isNaN(Number(trimmed))) {
try {
convertedValue = JSON.parse(trimmed);
} catch (e) {
convertedValue = value;
}
}
}
obj[keys[keys.length - 1]] = convertedValue;
}
Timer {
id: fileReloadTimer
interval: root.readWriteDelay
repeat: false
onTriggered: {
configFileView.reload()
}
}
Timer {
id: fileWriteTimer
interval: root.readWriteDelay
repeat: false
onTriggered: {
configFileView.writeAdapter()
}
}
FileView {
id: configFileView
path: root.filePath
watchChanges: true
blockWrites: root.blockWrites
onFileChanged: fileReloadTimer.restart()
onAdapterUpdated: fileWriteTimer.restart()
onLoaded: root.ready = true
onLoadFailed: error => {
if (error == FileViewError.FileNotFound) {
writeAdapter();
}
}
JsonAdapter {
id: configOptionsJsonAdapter
property string panelFamily: "ii" // "ii", "waffle"
// Souveraine form-factor gate. Flip to true on a phone deploy:
// gates the Phone settings category and (later) the single-column
// layout. Laptop deploys stay false and see the stock page set.
property JsonObject souveraine: JsonObject {
property bool phone: false
}
property JsonObject policies: JsonObject {
property int ai: 1 // 0: No | 1: Yes | 2: Local
property int weeb: 1 // 0: No | 1: Open | 2: Closet
}
property JsonObject ai: JsonObject {
property string systemPrompt: "## Style\n- Use casual tone, don't be formal!\n- Always be brief and to the point, unless asked otherwise\n- Don't repeat the user's question\n- Be approachable: Avoid using overly complicated, domain-specific terms and provide analogies when asked to explain a concept\n\n## Context (ignore when irrelevant)\n- You are a helpful and inspiring sidebar assistant on a {DISTRO} Linux system\n- Desktop environment: {DE}\n- Current date & time: {DATETIME}\n- Focused app: {WINDOWCLASS}\n\n## Presentation\n- Use Markdown features in your response: \n - **Bold** text to **highlight keywords** in your response\n - **Split long information into small sections** with h2 headers and a relevant emoji at the start of it (for example `## 🐧 Linux`). Bullet points are preferred over long paragraphs, unless you're offering writing support or instructed otherwise by the user.\n- Asked to compare different options? You should firstly use a table to compare the main aspects, then elaborate or include relevant comments from online forums *after* the table. Make sure to provide a final recommendation for the user's use case!\n- Use LaTeX formatting for mathematical and scientific notations whenever appropriate. Enclose all LaTeX '$$' delimiters. NEVER generate LaTeX code in a latex block unless the user explicitly asks for it. DO NOT use LaTeX for regular documents (resumes, letters, essays, CVs, etc.).\n\nThanks!\n"
property string tool: "functions" // search, functions, or none
property list<var> extraModels: [
{
"api_format": "openai", // Most of the time you want "openai". Use "gemini" for Google's models
"description": "This is a custom model. Edit the config to add more! | Anyway, this is DeepSeek R1 Distill LLaMA 70B",
"endpoint": "https://openrouter.ai/api/v1/chat/completions",
"homepage": "https://openrouter.ai/deepseek/deepseek-r1-distill-llama-70b:free", // Not mandatory
"icon": "spark-symbolic", // Not mandatory
"key_get_link": "https://openrouter.ai/settings/keys", // Not mandatory
"key_id": "openrouter",
"model": "deepseek/deepseek-r1-distill-llama-70b:free",
"name": "Custom: DS R1 Dstl. LLaMA 70B",
"requires_key": true
}
]
}
property JsonObject appearance: JsonObject {
property bool extraBackgroundTint: true
property int fakeScreenRounding: 2 // 0: None | 1: Always | 2: When not fullscreen
property JsonObject fonts: JsonObject {
property string main: "Google Sans Flex"
property string numbers: "Google Sans Flex"
property string title: "Google Sans Flex"
property string iconNerd: "JetBrains Mono NF"
property string monospace: "JetBrains Mono NF"
property string reading: "Readex Pro"
property string expressive: "Space Grotesk"
}
property JsonObject transparency: JsonObject {
property bool enable: false
property bool automatic: true
property real backgroundTransparency: 0.11
property real contentTransparency: 0.57
}
property JsonObject wallpaperTheming: JsonObject {
property bool enableAppsAndShell: true
property bool enableQtApps: true
property bool enableTerminal: true
property JsonObject terminalGenerationProps: JsonObject {
property real harmony: 0.6
property real harmonizeThreshold: 100
property real termFgBoost: 0.35
property bool forceDarkMode: false
}
}
property JsonObject palette: JsonObject {
property string type: "auto" // Allowed: auto, scheme-content, scheme-expressive, scheme-fidelity, scheme-fruit-salad, scheme-monochrome, scheme-neutral, scheme-rainbow, scheme-tonal-spot
property string accentColor: ""
}
}
property JsonObject audio: JsonObject {
// Values in %
property JsonObject protection: JsonObject {
// Prevent sudden bangs
property bool enable: false
property real maxAllowedIncrease: 10
property real maxAllowed: 99
}
}
property JsonObject apps: JsonObject {
property string bluetooth: "kcmshell6 kcm_bluetooth"
property string changePassword: "kitty -1 --hold=yes fish -i -c 'passwd'"
property string network: "kcmshell6 kcm_networkmanagement"
property string manageUser: "kcmshell6 kcm_users"
property string networkEthernet: "kcmshell6 kcm_networkmanagement"
property string taskManager: "plasma-systemmonitor --page-name Processes"
property string terminal: "kitty -1" // This is only for shell actions
property string update: "kitty -1 --hold=yes fish -i -c 'pkexec pacman -Syu'"
property string volumeMixer: `~/.config/hypr/hyprland/scripts/launch_first_available.sh "pavucontrol-qt" "pavucontrol"`
}
property JsonObject background: JsonObject {
property JsonObject widgets: JsonObject {
property JsonObject clock: JsonObject {
property bool enable: true
property bool showOnlyWhenLocked: false
property string placementStrategy: "leastBusy" // "free", "leastBusy", "mostBusy"
property real x: 100
property real y: 100
property string style: "cookie" // Options: "cookie", "digital"
property string styleLocked: "cookie" // Options: "cookie", "digital"
property JsonObject cookie: JsonObject {
// aiStyling gates the categorize step in
// switchwall.sh (it must be true for wallpapers to
// be AI-categorized on apply). aiPreset is the
// SEPARATE gate for CookieClock applying a
// category preset over the user's configured clock
// style — split 2026-08-05 after turning on
// aiStyling rewrote the phone's clock
// (applyStyle writes these keys). Default off: the
// clock keeps whatever the user set.
property bool aiStyling: false
property bool aiPreset: false
property int sides: 14
property string dialNumberStyle: "full" // Options: "dots" , "numbers", "full" , "none"
property string hourHandStyle: "fill" // Options: "classic", "fill", "hollow", "hide"
property string minuteHandStyle: "medium" // Options "classic", "thin", "medium", "bold", "hide"
property string secondHandStyle: "dot" // Options: "dot", "line", "classic", "hide"
property string dateStyle: "bubble" // Options: "border", "rect", "bubble" , "hide"
property bool timeIndicators: true
property bool hourMarks: false
property bool dateInClock: true
property bool constantlyRotate: false
property bool useSineCookie: false
}
property JsonObject digital: JsonObject {
property bool adaptiveAlignment: true
property bool showDate: true
property bool animateChange: true
property bool vertical: false
property JsonObject font: JsonObject {
property string family: "Google Sans Flex"
property real weight: 350
property real width: 100
property real size: 90
property real roundness: 0
}
}
property JsonObject quote: JsonObject {
property bool enable: false
property string text: ""
}
}
property JsonObject weather: JsonObject {
property bool enable: false
property string placementStrategy: "free" // "free", "leastBusy", "mostBusy"
property real x: 400
property real y: 100
}
// Backported 2026-07-13 from laptop-upstream Config: the
// borrowed Background.qml reads these unconditionally, and
// their absence threw TypeErrors on the laptop. Keys only —
// we are NOT pulling the desktop-widget rendering machinery
// into this phone-first shell; enable defaults to false.
property JsonObject visualizer: JsonObject {
property bool enable: false
property string placementStrategy: "free"
property real x: 500
property real y: 500
property int bars: 30
property string style: "bars"
property bool vertical: false
}
property JsonObject stats: JsonObject {
property bool enable: false
property string placementStrategy: "free"
property real x: 150
property real y: 300
property string githubUsername: ""
property string codeforcesUsername: ""
property bool showGraphs: false
}
property JsonObject systemResources: JsonObject {
property bool enable: false
property string placementStrategy: "free"
property real x: 150
property real y: 600
property bool showGraphs: false
}
}
property string wallpaperPath: ""
property string thumbnailPath: ""
// Optional local derivatives for unlike display shapes. The
// original wallpaper remains canonical; variants are never a
// destructive replacement for it.
property string portraitVariantPath: ""
property string landscapeVariantPath: ""
property real wallpaperFocalX: 0.5
property real wallpaperFocalY: 0.5
property bool hideWhenFullscreen: true
property JsonObject parallax: JsonObject {
property bool vertical: false
property bool autoVertical: false
property bool enableWorkspace: false
property real workspaceZoom: 1.07 // Relative to wallpaper size
property bool enableSidebar: false
property real widgetsFactor: 1.2
}
}
property JsonObject bar: JsonObject {
// TASK-69/70: one collector for every agent session
// (Souveraine, Claude Code, Codex). Replaces per-provider
// fetches; claudeUsage above stays for the subscription
// gauge until stage 3 folds its OAuth poll in here.
property JsonObject agentSessions: JsonObject {
property bool enable: true // Show the agent island in the bar
property int refreshInterval: 60 // seconds
property int windowMinutes: 1440 // How far back counts as "a session"
}
// Bar layout. One BarContent serves every device; which
// widgets appear and in what order is data, not a fork.
// Known names: activeWindow, cellular, resources, media,
// claudeUsage, workspaces, clock, utilButtons, island,
// battery, pomodoro, systray. An unknown name renders
// nothing, so ["none"] deliberately empties a slot; an
// empty list means "unset" and falls back to the profile.
property JsonObject layout: JsonObject {
// "auto" derives from the bar's own cramped-ness test
// (the same one behind useShortenedForm), so a phone
// needs no config. "desktop" | "compact" pin it.
property string profile: "auto"
property list<string> left: []
property list<string> centerLeft: []
property list<string> centerMiddle: []
property list<string> centerRight: []
property list<string> right: []
}
property JsonObject clock: JsonObject {
property string format: "" // Empty: pick by profile
}
property JsonObject autoHide: JsonObject {
property bool enable: false
property int hoverRegionWidth: 2
property bool pushWindows: false
property JsonObject showWhenPressingSuper: JsonObject {
property bool enable: true
property int delay: 140
}
}
property bool bottom: false // Instead of top
property int cornerStyle: 0 // 0: Hug | 1: Float | 2: Plain rectangle
property bool floatStyleShadow: true // Show shadow behind bar when cornerStyle == 1 (Float)
property bool borderless: false // true for no grouping of items
property string topLeftIcon: "spark" // Options: "distro" or any icon name in ~/.config/quickshell/ii/assets/icons
property bool showBackground: true
property bool verbose: true
property bool vertical: false
property JsonObject resources: JsonObject {
// "auto" follows the active bar profile: compact bars
// rotate one stat; desktop bars render the full group.
// "on"/"off" override it. Never null — a null var is
// serialized into config.json and crashes JsonAdapter on
// the next load.
property string rotate: "auto"
property int rotateInterval: 4
property bool alwaysShowSwap: true
property bool alwaysShowCpu: true
property int memoryWarningThreshold: 95
property int swapWarningThreshold: 85
property int cpuWarningThreshold: 90
}
property list<string> screenList: [] // List of names, like "eDP-1", find out with 'hyprctl monitors' command
property JsonObject utilButtons: JsonObject {
property bool showScreenSnip: true
property bool showColorPicker: false
property bool showMicToggle: false
property bool showKeyboardToggle: true
property bool showDarkModeToggle: true
property bool showPerformanceProfileToggle: false
property bool showScreenRecord: false
}
property JsonObject workspaces: JsonObject {
property bool monochromeIcons: true
property int shown: 10
property bool showAppIcons: true
property bool alwaysShowNumbers: false
property int showNumberDelay: 300 // milliseconds
property list<string> numberMap: ["1", "2"] // Characters to show instead of numbers on workspace indicator
property bool useNerdFont: false
}
// Backported 2026-07-13: borrowed ClaudeUsage service + bar
// widget read these unconditionally. Keys only, enable=false.
property JsonObject claudeUsage: JsonObject {
property bool enable: false // Show a Claude (Pro/Max) subscription usage gauge in the bar
property bool defaultWeekly: false // Start on the 7-day window; click to switch session <-> week
property int warningThreshold: 90 // Turn red at/above this utilization (%)
property int fetchInterval: 5 // minutes
}
property JsonObject weather: JsonObject {
property bool enable: false
property bool enableGPS: true // gps based location
property string city: "" // When 'enableGPS' is false
property bool useUSCS: false // Instead of metric (SI) units
property int fetchInterval: 10 // minutes
}
property JsonObject indicators: JsonObject {
property JsonObject notifications: JsonObject {
property bool showUnreadCount: false
}
// Status icons inside the right-hand pill. "auto" follows
// the profile: a compact bar drops xkb and bluetooth.
// "on"/"off" override it. Never null — see bar.resources.
property string showXkb: "auto"
property string showBluetooth: "auto"
}
property JsonObject tooltips: JsonObject {
property bool clickToShow: false
}
}
property JsonObject battery: JsonObject {
property int low: 20
property int critical: 5
property int full: 101
property bool automaticSuspend: true
property int suspend: 3
}
property JsonObject calendar: JsonObject {
property string locale: "en-GB"
}
property JsonObject cheatsheet: JsonObject {
// Use a nerdfont to see the icons
// 0: 󰖳 | 1: 󰌽 | 2: 󰘳 | 3:  | 4: 󰨡
// 5:  | 6:  | 7: 󰣇 | 8:  | 9: 
// 10:  | 11:  | 12:  | 13:  | 14: 󱄛
property string superKey: ""
property bool useMacSymbol: false
property bool splitButtons: false
property bool useMouseSymbol: false
property bool useFnSymbol: false
property JsonObject fontSize: JsonObject {
property int key: Appearance.font.pixelSize.smaller
property int comment: Appearance.font.pixelSize.smaller
}
}
property JsonObject conflictKiller: JsonObject {
property bool autoKillNotificationDaemons: false
// DO NOT auto-kill trays here. On this phone kded6 is not a
// competing Plasma tray — it is the StatusNotifierWatcher that
// ii's OWN tray (Quickshell.Services.SystemTray) registers as a
// host with (IsStatusNotifierHostRegistered=true). Killing it
// just makes D-Bus re-activate it on ii's next tray call — an
// infinite loop. Our services/ConflictKiller.qml override drops
// the kded6 check entirely. Leave this false.
property bool autoKillTrays: false
}
property JsonObject crosshair: JsonObject {
// Valorant crosshair format. Use https://www.vcrdb.net/builder
property string code: "0;P;d;1;0l;10;0o;2;1b;0"
}
property JsonObject dock: JsonObject {
property bool enable: false
property bool monochromeIcons: true
property real height: 60
property real hoverRegionHeight: 2
// Home normally keeps its dock visible. Auto-hide leaves only
// the edge reveal strip mapped, then raises the same dock when
// the pointer dwells there. These delays belong to the dock's
// one visibility state machine; Settings only writes them.
property bool autoHide: false
property int revealDelayMs: 120
property int hideDelayMs: 350
property bool pinnedOnStartup: false
property bool hoverToReveal: true // When false, only reveals on empty workspace
property list<string> pinnedApps: [ // IDs of pinned entries
"org.kde.dolphin", "kitty",]
property list<string> ignoredAppRegexes: []
// Fan-out stacks (macOS "Fan" mode). Each entry is
// "stackId|appId,appId,appId" — phone-local, no Phosh sync.
// stackId is a display label; members render as an arc.
property list<string> stacks: []
// Feel knobs (single source — components read these, never
// hardcode): dragDwellMs = how long a drag hovers an icon
// or stack before it reads as combine-intent (GNOME's
// rule); gestureRailHeight = bottom strip the dock reserves
// for Souveraine's integrated navigation rail, visually and
// in its input mask.
property int dragDwellMs: 500
property real gestureRailHeight: 32
// How big the dock draws. `buttonSize` is the one number the
// row's height follows and every icon is derived from, so the
// dock scales as a piece rather than each part being tuned
// apart. 56/44 replaced a hardcoded 44/35 that read small on a
// 540px panel; it lives here so it is a setting rather than a
// rebuild.
property real buttonSize: 56
property real iconSize: 44
}
property JsonObject interactions: JsonObject {
property JsonObject scrolling: JsonObject {
property bool fasterTouchpadScroll: false // Enable faster scrolling with touchpad
property int mouseScrollDeltaThreshold: 120 // delta >= this then it gets detected as mouse scroll rather than touchpad
property int mouseScrollFactor: 120
property int touchpadScrollFactor: 450
}
property JsonObject deadPixelWorkaround: JsonObject { // Hyprland leaves out 1 pixel on the right for interactions
property bool enable: false
}
}
property JsonObject language: JsonObject {
property string ui: "auto" // UI language. "auto" for system locale, or specific language code like "zh_CN", "en_US"
property JsonObject translator: JsonObject {
property string engine: "auto" // Run `trans -list-engines` for available engines. auto should use google
property string targetLanguage: "auto" // Run `trans -list-all` for available languages
property string sourceLanguage: "auto"
}
}
property JsonObject launcher: JsonObject {
property list<string> pinnedApps: [ "org.kde.dolphin", "kitty", "cmake-gui"]
}
property JsonObject light: JsonObject {
property JsonObject night: JsonObject {
property bool automatic: true
property string from: "19:00" // Format: "HH:mm", 24-hour time
property string to: "06:30" // Format: "HH:mm", 24-hour time
property int colorTemperature: 5000
}
property JsonObject antiFlashbang: JsonObject {
property bool enable: false
}
}
property JsonObject lock: JsonObject {
property bool useHyprlock: false
property bool launchOnStartup: false
property int dpmsTimeout: 3
property string unlockHook: ""
// Souveraine: PIN keypad surface for touch panels (phone).
// The OSK can't rise above a session lock, so the lock
// surface must carry its own input.
property bool touchKeypad: false
property JsonObject blur: JsonObject {
property bool enable: true
property real radius: 100
property real extraZoom: 1.1
}
property bool centerClock: true
// 12-hour glance clock (am/pm). Off = 24-hour.
property bool twelveHourClock: true
// Lock-screen wallpaper. Empty = follow the system wallpaper
// (background.wallpaperPath); a path pins the lock's own.
property string wallpaperPath: ""
property bool showLockedText: true
// A visible wiring exercise for the FPC1020 path. It never
// unlocks the session; the separate Polkit setting below is
// the temporary, post-login-only factor.
property JsonObject fingerprintPreview: JsonObject {
property bool enabled: false
property int holdMs: 3000
}
// The temporary FPC factor belongs only to polkit-1. It cannot
// satisfy first login, disk unlock, sudo, SSH, or lock-screen
// PAM. The real souveraine-fpd match result will replace this
// raw-reader bridge without changing the user-facing surface.
property JsonObject fingerprintPolkit: JsonObject {
property bool enabled: true
}
// Souveraine-owned lock cards. Transport controls are
// ambient; media metadata remains personal by default.
property JsonObject content: JsonObject {
property bool showMediaControls: true
property bool mediaMetadataAmbient: false
property bool showBattery: true
// App identity + count are ambient; the summary line is
// personal until promoted. Bodies never render on lock.
property bool showNotifications: true
property bool notificationContentAmbient: false
}
property JsonObject idle: JsonObject {
// Native idle-notify remains opt-in until verified on the
// Pixel compositor; hypridle is the current adapter.
property bool nativeCoordinatorEnabled: false
// The lock timer is the one the user sets. The dim is
// expressed RELATIVE to it — how long before the lock the
// screen starts fading — so the two can never cross and
// moving one moves the other. They were independent
// absolutes (120 and 300), which meant picking a dim
// longer than the lock silently produced a dim that never
// fired. sessiond's lock-screen dim has always been
// relative (`dim_at = budget - dim_grace`); this is the
// shell saying the same thing the same way.
//
// Default 180 reproduces the old pair exactly: 300 - 180 =
// 120. An existing config.json keeps its lockAfterSeconds
// and picks this default up, so nobody's timing changes.
property int lockAfterSeconds: 300
property int dimBeforeLockSeconds: 180
// Backlight level while Dimmed; Active restores the
// brightnessctl-saved value.
property string dimBrightness: "30%"
}
property JsonObject security: JsonObject {
property bool unlockKeyring: true
property bool requirePasswordToPower: false
// Whether the lock surface may trigger power-off / reboot
// at all. Off by default (fail-closed): a destructive
// action from the locked screen is opt-in. The system
// polkit rule (souveraine-login1.rules) lets the active
// session power off without challenge once unlocked; this
// gate keeps the *locked* surface from reaching it until
// the user enables it. requirePasswordToPower then arms
// the action to be confirmed by the PIN unlock.
property bool allowPowerFromLock: false
}
// Step-up authentication grants for sensitive operations.
// The PAM service (souveraine-stepup) is root-owned system
// config and must be installed separately before enabling.
property JsonObject stepUp: JsonObject {
property int grantTtlMs: 300000 // 5 minutes
property bool enabled: false // requires souveraine-stepup PAM service
}
property bool materialShapeChars: true
}
property JsonObject media: JsonObject {
// Attempt to remove dupes (the aggregator playerctl one and browsers' native ones when there's plasma browser integration)
property bool filterDuplicatePlayers: true
}
property JsonObject networking: JsonObject {
property string userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36"
}
property JsonObject notifications: JsonObject {
property int timeout: 7000
// Upstream modules (NotificationPopup, settings InterfaceConfig)
// read forceMonitor; the old "monitor" name left that undefined
// and threw a TypeError on every popup evaluation.
property JsonObject forceMonitor: JsonObject {
property bool enable: false
property string name: "" // Name of the monitor to show notifications on, like "eDP-1". Find out with 'hyprctl monitors' command
}
}
property JsonObject osd: JsonObject {
property int timeout: 1000
}
property JsonObject osk: JsonObject {
property string layout: "qwerty_full"
property bool pinnedOnStartup: false
}
// Speech services — network STT/TTS on Casey's VPN. The shell
// and the souveraine-stt/tts CLIs read the same config file, so
// the settings page here is the single source of truth for both.
property JsonObject speech: JsonObject {
property JsonObject stt: JsonObject {
property bool enable: true
// faster-whisper REST bridge: POST multipart 'audio'
// (WAV) -> {"text": ...}. /health for the status probe.
property string endpoint: ""
}
property JsonObject tts: JsonObject {
property bool enable: false
// Speech-synthesis endpoint: POST {"text": ...} -> audio
// stream. Empty until a TTS server exists on the VPN.
property string endpoint: ""
}
}
// Text-selection action menu (TASK-18).
//
// OPT-IN ON PURPOSE, and do not flip this default casually. When
// enabled, the shell watches the compositor's primary selection,
// which means it observes EVERY piece of text the user highlights
// anywhere on the device — including a password highlighted inside
// a password manager. No tier in SESSION-AUTHORITY-DOCTRINE §2
// covers an ambient capability of that reach, so the user turns it
// on knowingly or it does not run. Selection.qml additionally kills
// its watcher whenever the session is locked and never persists or
// logs selection content.
property JsonObject selection: JsonObject {
property bool enable: false
// Read Aloud is the one action with a live backend today; it
// routes through Speech.speak() and so also obeys
// speech.tts.enable. The rest are stubs until they earn a
// backend (TASK-18: a stubbed action is fine, a janky menu is not).
property bool readAloud: true
// Agent actions ("Talk about this" / "Add to our conversation")
// reach conversation history, which is `personal` tier — they
// stay dark until the session is genuinely unlocked.
property bool agentActions: true
// Reference lookups stay strictly local/offline by default,
// per TASK-18's stated default stance: never touch the agent.
property bool referenceActions: true
}
property JsonObject overlay: JsonObject {
property bool openingZoomAnimation: true
property bool darkenScreen: true
property real clickthroughOpacity: 0.8
property JsonObject floatingImage: JsonObject {
property string imageSource: "https://media.tenor.com/H5U5bJzj3oAAAAAi/kukuru.gif"
property real scale: 0.5
}
}
property JsonObject overview: JsonObject {
property bool enable: true
property real scale: 0.18 // Relative to screen size
property real rows: 2
property real columns: 5
property bool orderRightLeft: false
property bool orderBottomUp: false
property bool centerIcons: true
// The app drawer's own grid (TASK-14). Kept nested instead of
// overloading rows/columns above — those are the desktop
// overview's workspace-grid knobs, and the drawer is a
// different density. The settings app writes these.
property JsonObject appGrid: JsonObject {
property int columns: 4
property int rows: 5
property int iconSize: 44
}
}
property JsonObject regionSelector: JsonObject {
property JsonObject targetRegions: JsonObject {
property bool windows: true
property bool layers: false
property bool content: true
property bool showLabel: false
property real opacity: 0.3
property real contentRegionOpacity: 0.8
property int selectionPadding: 5
}
property JsonObject rect: JsonObject {
property bool showAimLines: true
}
property JsonObject circle: JsonObject {
property int strokeWidth: 6
property int padding: 10
}
property JsonObject annotation: JsonObject {
property bool useSatty: false
}
}
property JsonObject resources: JsonObject {
property int updateInterval: 3000
property int historyLength: 60
}
property JsonObject tray: JsonObject {
property bool monochromeIcons: true
property bool showItemId: false
property bool invertPinnedItems: true // Makes the below a whitelist for the tray and blacklist for the pinned area
property list<var> pinnedItems: [ "Fcitx" ]
property bool filterPassive: true
}
property JsonObject musicRecognition: JsonObject {
property int timeout: 16
property int interval: 4
}
property bool autoIdleInhibit: false
property JsonObject search: JsonObject {
property int nonAppResultDelay: 30 // This prevents lagging when typing
property string engineBaseUrl: "https://www.google.com/search?q="
property list<string> excludedSites: ["quora.com", "facebook.com"]
property bool sloppy: false // Uses levenshtein distance based scoring instead of fuzzy sort. Very weird.
property JsonObject prefix: JsonObject {
property bool showDefaultActionsWithoutPrefix: true
property string action: "/"
property string app: ">"
property string clipboard: ";"
property string emojis: ":"
property string math: "="
property string shellCommand: "$"
property string webSearch: "?"
}
property JsonObject imageSearch: JsonObject {
property string imageSearchEngineBaseUrl: "https://lens.google.com/uploadbyurl?url="
property bool useCircleSelection: false
}
// Backported 2026-07-13: borrowed LauncherSearch reads this
// unconditionally. Key only, enable=false.
property JsonObject fileSearch: JsonObject {
property bool enable: false
property list<string> paths: [Directories.home]
property list<string> exclude: [".git", "node_modules", "target", "build"]
property bool excludeHiddenDirs: true
property int maxResults: 30
}
}
property JsonObject sidebar: JsonObject {
property bool keepRightSidebarLoaded: true
property int width: 460 // Collapsed sidebar width in px
property int widthExtended: 750 // Extended (Ctrl+O) sidebar width in px
property JsonObject translator: JsonObject {
property bool enable: false
property int delay: 300 // Delay before sending request. Reduces (potential) rate limits and lag.
}
property JsonObject ai: JsonObject {
property bool textFadeIn: false
// Chat message text size. Live binding to the theme value
// (never a literal, and never null — see
// null-in-a-serialized-config, 2026-08-11). ii-base added
// this key after our override was forked, and because this
// file SHADOWS ii-base's Config wholesale, the key simply
// vanished: MessageTextBlock read it as undefined and
// assigned undefined to font.pixelSize on every render.
property int fontSize: Appearance.font.pixelSize.small
}
property JsonObject booru: JsonObject {
property bool allowNsfw: false
property string defaultProvider: "yandere"
property int limit: 20
property JsonObject zerochan: JsonObject {
property string username: "[unset]"
}
}
property JsonObject cornerOpen: JsonObject {
property bool enable: true
property bool bottom: false
property bool valueScroll: true
property bool clickless: false
property int cornerRegionWidth: 250
property int cornerRegionHeight: 5
property bool visualize: false
property bool clicklessCornerEnd: true
property int clicklessCornerVerticalOffset: 1
}
property JsonObject quickToggles: JsonObject {
property string style: "android" // Options: classic, android
property JsonObject android: JsonObject {
property int columns: 5
property list<var> toggles: [
{ "size": 2, "type": "network" },
{ "size": 2, "type": "bluetooth" },
{ "size": 1, "type": "idleInhibitor" },
{ "size": 1, "type": "mic" },
{ "size": 2, "type": "audio" },
{ "size": 2, "type": "nightLight" }
]
}
}
property JsonObject quickSliders: JsonObject {
property bool enable: false
property bool showMic: false
property bool showVolume: true
property bool showBrightness: true
}
}
property JsonObject screenRecord: JsonObject {
property string savePath: Directories.videos.replace("file://","") // strip "file://"
}
property JsonObject screenSnip: JsonObject {
property string savePath: "" // only copy to clipboard when empty
}
property JsonObject sounds: JsonObject {
property bool battery: false
property bool pomodoro: false
property string theme: "freedesktop"
}
property JsonObject time: JsonObject {
// https://doc.qt.io/qt-6/qtime.html#toString
property string format: "hh:mm"
property string shortDateFormat: "dd/MM"
property string dateWithYearFormat: "dd/MM/yyyy"
property string dateFormat: "ddd, dd/MM"
property JsonObject pomodoro: JsonObject {
property int breakTime: 300
property int cyclesBeforeLongBreak: 4
property int focus: 1500
property int longBreak: 900
}
property bool secondPrecision: false
}
property JsonObject updates: JsonObject {
property bool enableCheck: true
property int checkInterval: 120 // minutes
property int adviseUpdateThreshold: 75 // packages
property int stronglyAdviseUpdateThreshold: 200 // packages
}
property JsonObject wallpaperSelector: JsonObject {
property bool useSystemFileDialog: false
}
property JsonObject windows: JsonObject {
property bool showTitlebar: true // Client-side decoration for shell apps
property bool centerTitle: true
}
property JsonObject hacks: JsonObject {
property int arbitraryRaceConditionDelay: 20 // milliseconds
}
property JsonObject workSafety: JsonObject {
property JsonObject enable: JsonObject {
property bool wallpaper: false
property bool clipboard: false
}
property JsonObject triggerCondition: JsonObject {
property list<string> networkNameKeywords: ["airport", "cafe", "college", "company", "eduroam", "free", "guest", "public", "school", "university"]
property list<string> fileKeywords: ["anime", "booru", "ecchi", "hentai", "yande.re", "konachan", "breast", "nipples", "pussy", "nsfw", "spoiler", "girl"]
property list<string> linkKeywords: ["hentai", "porn", "sukebei", "hitomi.la", "rule34", "gelbooru", "fanbox", "dlsite"]
}
}
property JsonObject waffles: JsonObject {
// Some spots are kinda janky/awkward. Setting the following to
// false will make (some) stuff also be like that for accuracy.
// Example: the right-click menu of the Start button
property JsonObject tweaks: JsonObject {
property bool switchHandlePositionFix: true
property bool smootherMenuAnimations: true
property bool smootherSearchBar: true
}
property JsonObject bar: JsonObject {
property bool bottom: true
property bool leftAlignApps: false
}
property JsonObject actionCenter: JsonObject {
property list<string> toggles: [ "network", "vpn", "bluetooth", "easyEffects", "powerProfile", "idleInhibitor", "nightLight", "darkMode", "antiFlashbang", "cloudflareWarp", "mic", "musicRecognition", "notifications", "onScreenKeyboard", "gameMode", "screenSnip", "colorPicker" ]
}
property JsonObject calendar: JsonObject {
property bool force2CharDayOfWeek: true
}
}
}
}
}