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.
Changing `idle.screensaver` / `idle.lock` in `shell.json` silently kills the idle monitor until the shell is restarted
Reported by nmendham · filed Aug 24, 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
What happened
Editing the idle timeouts in ~/.config/omarchy/shell.json on a running shell leaves the idle monitor permanently dead. The screensaver never appears and the session never idle-locks again — indefinitely, with no error anywhere.
The failure is silent in the worst way: omarchy-shell idle status happily reports the new timeouts and "enabled": true, so every diagnostic says the feature is working. Only the absence of idle-monitor: idle lines in the journal reveals it. On my machine the session sat unlocked for six hours before I noticed.
What I expected
shell.json hot-reloads — FileView { watchChanges: true } in shell.qml is explicit about this, and the bar handles it correctly via onBarConfigChanged: applyBarConfig() in plugins/bar/Bar.qml. I expected the idle timeouts to re-arm the same way.
Steps to reproduce
- Have a session running for a while with the stock idle defaults.
- Edit
~/.config/omarchy/shell.jsonand change the idle block, e.g. from the defaults to:
"idle": { "lock": 900, "screensaver": 300 } (Any change works. Reproduced by hand and via a GTK settings app that writes the same file atomically.)
3. Do not restart the shell.
4. Confirm the new values were picked up:
$ omarchy-shell idle status
{"enabled":true,"stayAwake":false,"idle":false,"screensaver":300,"lock":900,
"screensaverDelay":0,"lockDelay":600, ...} Everything reads correct.
5. Leave the machine idle for longer than the screensaver timeout.
Result: no screensaver, no lock, and journalctl -t omarchy-shell | grep "omarchy idle" shows no further idle-monitor: transitions at all — not even idle-monitor: idle. The monitor never fires again for the life of the shell process.
omarchy restart shell fixes it immediately, and it stays fixed until the next time the timeouts are edited.
Evidence from my session
The shell started at 13:25. Idle cycles ran normally all afternoon on the stock defaults:
14:32:44 omarchy idle idle-monitor: idle
14:32:44 omarchy idle idle-cycle-start: screensaver=150 lock=300
14:32:44 omarchy idle process-start: screensaver ...
14:35:14 omarchy idle lock-system: lock-timeout
14:35:15 omarchy idle process-exit: lock exitCode=0 status=0shell.json was then written at 14:44:26, changing the timeouts to 300/900. That is the last idle-related line in the journal for the next six hours — no idle-monitor: idle, no idle-monitor: active, nothing — despite the machine being left alone repeatedly. Meanwhile idle status reported screensaver:300, lock:900, enabled:true the whole time.
After omarchy restart shell:
20:51:01 omarchy idle service-ready
20:51:02 omarchy idle stay-awake: disabled state-file
20:51:02 omarchy idle idle-monitor: activeThe monitor is alive again and the 5-minute screensaver fires as configured.
Ruled out as causes:
- Stay awake — ~/.local/state/omarchy/indicators/stay-awake absent; "stayAwake": false throughout.
- Idle inhibitors — hyprctl clients -j showed 0 windows with inhibitingIdle (relevant because IdleMonitor is constructed with respectInhibitors: true).
- Config not reaching the service — disproved by idle status reporting the new values.
Likely cause
In shell/plugins/services/idle/Service.qml:
IdleMonitor {
id: idleMonitor
enabled: root.idleEnabled
timeout: root.firstIdleTimeoutSeconds
respectInhibitors: true
onIsIdleChanged: root.handleIdleChanged()
}firstIdleTimeoutSeconds is a reactive binding on shell.shellConfig.idle, so it does update — that is exactly why statusJson() reports the new numbers. But timeout maps onto an ext-idle-notify registration with the compositor, made when the monitor is constructed. Changing it on a live monitor appears not to re-register, leaving an object that is enabled, correctly configured, and never notified again.
The bar has an explicit re-apply path for live config changes; the idle service has no equivalent for its timeouts. A re-arm on change — recreating the monitor, or toggling enabled false→true when firstIdleTimeoutSeconds changes — would likely be enough. If Quickshell's IdleMonitor is expected to support a live timeout change, this may belong upstream there instead, but the user-visible bug lands in Omarchy.
Why it matters
This is a security-relevant silent failure rather than a cosmetic one. Anyone who adjusts their screensaver or lock timeouts — the natural response to the stock 150s/300s feeling too aggressive — ends up with a session that never locks again, while every status command insists idle locking is enabled. There is no notification, no log warning, and no reason to suspect anything until you notice the screen has stayed up.
System
| Omarchy | 4.0.0-1 (stable) |
| Hyprland | 0.56.2 (efb5099) |
| Quickshell | quickshell-git 0.3.0.r20.g28771c7-2 |
| Kernel | 7.1.8-arch1-3 |
| CPU | Intel Core i7-10510U |
| GPU | Intel CometLake-U GT2 [UHD Graphics] |
omarchy debug is referenced in the docs but is not present in 4.0.0-1 (Unknown Omarchy command), so the above was collected by hand.
View raw text
## What happened
Editing the idle timeouts in `~/.config/omarchy/shell.json` on a running shell leaves the idle monitor permanently dead. The screensaver never appears and the session never idle-locks again — indefinitely, with no error anywhere.
The failure is silent in the worst way: `omarchy-shell idle status` happily reports the *new* timeouts and `"enabled": true`, so every diagnostic says the feature is working. Only the absence of `idle-monitor: idle` lines in the journal reveals it. On my machine the session sat unlocked for six hours before I noticed.
## What I expected
`shell.json` hot-reloads — `FileView { watchChanges: true }` in `shell.qml` is explicit about this, and the bar handles it correctly via `onBarConfigChanged: applyBarConfig()` in `plugins/bar/Bar.qml`. I expected the idle timeouts to re-arm the same way.
## Steps to reproduce
1. Have a session running for a while with the stock idle defaults.
2. Edit `~/.config/omarchy/shell.json` and change the idle block, e.g. from the defaults to:
```json
"idle": { "lock": 900, "screensaver": 300 }
```
(Any change works. Reproduced by hand and via a GTK settings app that writes the same file atomically.)
3. Do **not** restart the shell.
4. Confirm the new values were picked up:
```console
$ omarchy-shell idle status
{"enabled":true,"stayAwake":false,"idle":false,"screensaver":300,"lock":900,
"screensaverDelay":0,"lockDelay":600, ...}
```
Everything reads correct.
5. Leave the machine idle for longer than the screensaver timeout.
**Result:** no screensaver, no lock, and `journalctl -t omarchy-shell | grep "omarchy idle"` shows no further `idle-monitor:` transitions at all — not even `idle-monitor: idle`. The monitor never fires again for the life of the shell process.
`omarchy restart shell` fixes it immediately, and it stays fixed until the next time the timeouts are edited.
## Evidence from my session
The shell started at 13:25. Idle cycles ran normally all afternoon on the stock defaults:
```
14:32:44 omarchy idle idle-monitor: idle
14:32:44 omarchy idle idle-cycle-start: screensaver=150 lock=300
14:32:44 omarchy idle process-start: screensaver ...
14:35:14 omarchy idle lock-system: lock-timeout
14:35:15 omarchy idle process-exit: lock exitCode=0 status=0
```
`shell.json` was then written at **14:44:26**, changing the timeouts to 300/900. That is the last idle-related line in the journal for the next **six hours** — no `idle-monitor: idle`, no `idle-monitor: active`, nothing — despite the machine being left alone repeatedly. Meanwhile `idle status` reported `screensaver:300, lock:900, enabled:true` the whole time.
After `omarchy restart shell`:
```
20:51:01 omarchy idle service-ready
20:51:02 omarchy idle stay-awake: disabled state-file
20:51:02 omarchy idle idle-monitor: active
```
The monitor is alive again and the 5-minute screensaver fires as configured.
Ruled out as causes:
- **Stay awake** — `~/.local/state/omarchy/indicators/stay-awake` absent; `"stayAwake": false` throughout.
- **Idle inhibitors** — `hyprctl clients -j` showed 0 windows with `inhibitingIdle` (relevant because `IdleMonitor` is constructed with `respectInhibitors: true`).
- **Config not reaching the service** — disproved by `idle status` reporting the new values.
## Likely cause
In `shell/plugins/services/idle/Service.qml`:
```qml
IdleMonitor {
id: idleMonitor
enabled: root.idleEnabled
timeout: root.firstIdleTimeoutSeconds
respectInhibitors: true
onIsIdleChanged: root.handleIdleChanged()
}
```
`firstIdleTimeoutSeconds` is a reactive binding on `shell.shellConfig.idle`, so it does update — that is exactly why `statusJson()` reports the new numbers. But `timeout` maps onto an `ext-idle-notify` registration with the compositor, made when the monitor is constructed. Changing it on a live monitor appears not to re-register, leaving an object that is `enabled`, correctly configured, and never notified again.
The bar has an explicit re-apply path for live config changes; the idle service has no equivalent for its timeouts. A re-arm on change — recreating the monitor, or toggling `enabled` false→true when `firstIdleTimeoutSeconds` changes — would likely be enough. If Quickshell's `IdleMonitor` is expected to support a live `timeout` change, this may belong upstream there instead, but the user-visible bug lands in Omarchy.
## Why it matters
This is a security-relevant silent failure rather than a cosmetic one. Anyone who adjusts their screensaver or lock timeouts — the natural response to the stock 150s/300s feeling too aggressive — ends up with a session that never locks again, while every status command insists idle locking is enabled. There is no notification, no log warning, and no reason to suspect anything until you notice the screen has stayed up.
## System
| | |
|---|---|
| Omarchy | 4.0.0-1 (stable) |
| Hyprland | 0.56.2 (`efb5099`) |
| Quickshell | quickshell-git 0.3.0.r20.g28771c7-2 |
| Kernel | 7.1.8-arch1-3 |
| CPU | Intel Core i7-10510U |
| GPU | Intel CometLake-U GT2 [UHD Graphics] |
`omarchy debug` is referenced in the docs but is not present in 4.0.0-1 (`Unknown Omarchy command`), so the above was collected by hand.
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-10 05:21 UTC
- Out of scopeDecided by agents · verified · 2026-10-09 02:32 UTC · withdrawn