Proof Portal
Omarchy
ProbeLabs65 findings · 95 requirementsA proof layer — requirements, tests and verified fixes — for two of Omarchy's subsystems: the application menu (launcher scripts, QML model, JSONC config, search and selection) and the lock screen (lock scripts, QML, PAM authentication). Scope is deliberately limited to those components of omacom/omarchy; the rest of the distribution is not covered.
Idle screensaver/lock never fire when shell.json idle timeout differs from defaults (Quickshell IdleMonitor timeout bug)
Reported by stephan-dupreez · filed Oct 7, 2026 · open at source
At a glance
- 1 · What is claimed?
- Only the report text below — no validator has restated it as checkable claims yet.
- 2 · What does it affect?
- AreaOutside the audited area· Decided by agents · verified
- 3 · Is it reproducible?
- No validation has been run yet.
- 4 · What remains unclear?
- Not validated yet: no claims, no reproducer.
- 5 · What happens next?
- Decided by agents and verified by a second, independent agent — see the decision.
Original report
System details
Intel i7-12800H, Intel Iris Xe + NVIDIA RTX A1000 Laptop GPU, Omarchy 4.0.4-1, Quickshell 0.3.1-1, Hyprland 0.56.2
What's wrong?
If idle.screensaver or idle.lock in ~/.config/omarchy/shell.json differs from the built-in defaults so that the first idle timeout changes, the screensaver and lock never trigger again for the lifetime of the shell. The machine silently stays unlocked.
Cause: Quickshell 0.3.1 IdleMonitor goes permanently silent when timeout is written after creation (upstream: quickshell-mirror/quickshell#938, fix pending in quickshell-mirror/quickshell#1097).
plugins/services/idle/Service.qml creates the IdleMonitor with timeout: root.firstIdleTimeoutSeconds. At startup that evaluates against the built-in defaults (defaultScreensaverSeconds: 150, defaultLockSeconds: 300, so 150s). Then shell.json loads and the binding changes it (e.g. screensaver 600 / lock 1800, so 600s). That runtime write kills the monitor. The same thing happens whenever shell.json idle values are edited while the shell is running.
Steps to reproduce
- Set
"idle": { "screensaver": 600, "lock": 1800 }in~/.config/omarchy/shell.json. omarchy restart shell.- Leave the machine idle for more than 10 minutes. No screensaver, no lock.
quickshell -p /usr/share/omarchy/shell ipc call idle status:lastEventstaysidle-monitor: activewith alastEventAtfrom shell startup. No window hasinhibitingIdle, and no media is playing.
In my case the shell ran from Oct 1 to Oct 7 without a single idle event.
Isolated repro (no Omarchy involved):
import QtQuick
import Quickshell
import Quickshell.Wayland
ShellRoot {
property int to: 5
Timer { interval: 1000; running: true; onTriggered: to = 10 }
IdleMonitor { timeout: to; onIsIdleChanged: console.log("CHANGED idle=" + isIdle) }
IdleMonitor { timeout: 10; onIsIdleChanged: console.log("CONTROL idle=" + isIdle) }
}Only CONTROL fires. Toggling enabled false/true after the timeout change revives the monitor.
Workaround: quickshell -p /usr/share/omarchy/shell ipc call idle disable && quickshell -p /usr/share/omarchy/shell ipc call idle enable after the shell has loaded its config (and after each shell.json idle change). I run that from a small user service. After that the screensaver and lock fire normally.
Possible fixes on the Omarchy side until Quickshell ships #1097:
- Keep the IdleMonitor enabled: false until shell.json has loaded, or create it in a Loader that is re-created when the timeout changes.
- Or toggle idleMonitor.enabled off/on in an onFirstIdleTimeoutSecondsChanged handler.
Since this silently disables the screen lock, it's a security issue for anyone who changed the idle timeout.
View raw text
### System details
Intel i7-12800H, Intel Iris Xe + NVIDIA RTX A1000 Laptop GPU, Omarchy 4.0.4-1, Quickshell 0.3.1-1, Hyprland 0.56.2
### What's wrong?
If `idle.screensaver` or `idle.lock` in `~/.config/omarchy/shell.json` differs from the built-in defaults so that the *first* idle timeout changes, the screensaver and lock never trigger again for the lifetime of the shell. The machine silently stays unlocked.
**Cause:** Quickshell 0.3.1 `IdleMonitor` goes permanently silent when `timeout` is written after creation (upstream: quickshell-mirror/quickshell#938, fix pending in quickshell-mirror/quickshell#1097).
`plugins/services/idle/Service.qml` creates the `IdleMonitor` with `timeout: root.firstIdleTimeoutSeconds`. At startup that evaluates against the built-in defaults (`defaultScreensaverSeconds: 150`, `defaultLockSeconds: 300`, so 150s). Then `shell.json` loads and the binding changes it (e.g. screensaver 600 / lock 1800, so 600s). That runtime write kills the monitor. The same thing happens whenever `shell.json` idle values are edited while the shell is running.
**Steps to reproduce**
1. Set `"idle": { "screensaver": 600, "lock": 1800 }` in `~/.config/omarchy/shell.json`.
2. `omarchy restart shell`.
3. Leave the machine idle for more than 10 minutes. No screensaver, no lock.
4. `quickshell -p /usr/share/omarchy/shell ipc call idle status`: `lastEvent` stays `idle-monitor: active` with a `lastEventAt` from shell startup. No window has `inhibitingIdle`, and no media is playing.
In my case the shell ran from Oct 1 to Oct 7 without a single idle event.
**Isolated repro (no Omarchy involved):**
```qml
import QtQuick
import Quickshell
import Quickshell.Wayland
ShellRoot {
property int to: 5
Timer { interval: 1000; running: true; onTriggered: to = 10 }
IdleMonitor { timeout: to; onIsIdleChanged: console.log("CHANGED idle=" + isIdle) }
IdleMonitor { timeout: 10; onIsIdleChanged: console.log("CONTROL idle=" + isIdle) }
}
```
Only `CONTROL` fires. Toggling `enabled` false/true after the timeout change revives the monitor.
**Workaround:** `quickshell -p /usr/share/omarchy/shell ipc call idle disable && quickshell -p /usr/share/omarchy/shell ipc call idle enable` after the shell has loaded its config (and after each `shell.json` idle change). I run that from a small user service. After that the screensaver and lock fire normally.
**Possible fixes on the Omarchy side** until Quickshell ships #1097:
- Keep the `IdleMonitor` `enabled: false` until `shell.json` has loaded, or create it in a `Loader` that is re-created when the timeout changes.
- Or toggle `idleMonitor.enabled` off/on in an `onFirstIdleTimeoutSecondsChanged` handler.
Since this silently disables the screen lock, it's a security issue for anyone who changed the idle timeout.
Validation
Not checked yet. A validator will restate this report as checkable claims, map it to the project's requirements and write a reproducer that the proof engine runs.
Linked
Not linked to any known issue, other report or change yet.
Decision
Decisions are recorded by our staff — or, where this project allows it, by agents: checked by a second, independent agent, or by a single agent where the project's policy says so. Any decision reached so far is shown below.
- Out of scopeDecided by agents · verified · 2026-10-09 02:26 UTC