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.
ScreenRecording bar indicator stuck 'active' after boot despite no gpu-screen-recorder process running
Reported by AmanKRoy · filed Sep 5, 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
Summary
The ScreenRecording bar indicator (shell/plugins/bar/indicators/ScreenRecording.qml) shows the "Stop recording" (active) state immediately after every shell/session restart or reboot, even though no gpu-screen-recorder process is actually running. This has persisted across multiple real reboots, not just shell restarts, so it isn't a leftover in-memory flag — the false-positive is regenerated fresh every boot.
Environment
- Omarchy 4.0.2-1 (Arch Linux, Hyprland)
- Dual-monitor setup (two bar instances, so two
ScreenRecordingindicator instances load concurrently at startup)
Evidence
- No real process ever exists. Direct
/procscan for any process whoseexesymlink resolves togpu-screen-recorder, run repeatedly across restarts and reboots, finds nothing.pgrep -af "^gpu-screen-recorder"(unanchored, no--quiet) also finds nothing at any point I checked, including a 5-second 100ms-interval poll spanning a full shell restart.
- The widget's own script agrees nothing is recording. Manually running
omarchy-capture-screenrecording --stop-recording(the exact command the indicator'sonPressedhandler runs when it believes recording is active) hits the script's ownscreenrecording_active()check (apgrep -f "^gpu-screen-recorder"call), finds nothing, and exits 1 via theelif [[ $STOP_RECORDING == "true" ]]; exit 1branch — i.e. the production script's own logic confirms no recording is active.
- The indicator's internal `pgrep` call still reports `exitCode: 0` (match found). I temporarily instrumented a local copy of
ScreenRecording.qmlwithconsole.logcalls aroundrefresh()and thestatusProcProcess, reinstalled it, and restarted the shell (omarchy-restart-shell) while tailing the journal. Every time,statusProc'sonExitedhandler fires withexitCode: 0, androot.recordingflips totrue— reproduced on repeated restarts.
[SR-DEBUG] Component.onCompleted
[SR-DEBUG] refresh() called. bar: true statusProc.running: false
[SR-DEBUG] statusProc launched
[SR-DEBUG] statusProc.running changed: true
[SR-DEBUG] statusProc EXITED, exitCode: 0
[SR-DEBUG] recording changed to true
[SR-DEBUG] active changed to true- But the match itself doesn't exist. I then changed the command from
pgrep --quiet -f "^gpu-screen-recorder"topgrep -af "^gpu-screen-recorder"(dropping--quiet, adding-ato print the matched line) and pipedstdoutthrough aSplitParserlogging every line.exitCode: 0still fires on every restart, but zero matched lines are ever printed — i.e.pgrepis reporting a match was found while producing no output describing what matched.
- Ruled out: no systemd user unit is active (
gpu-screen-recorder.serviceisdisabled/inactive (dead)), no Hyprlandexec-onceentry references the recorder, andgrep -r "gpu-screen-recorder"across/usr/share/omarchyonly matches the indicator itself and theomarchy-capture-screenrecordingscript — nothing else in Omarchy ever invokes the binary.
Suspected cause
This system has two monitors, so two ScreenRecording indicator instances mount concurrently at shell startup, each independently constructing an identical Process (pgrep --quiet -f "^gpu-screen-recorder") and setting running = true within the same event loop tick (Component.onCompleted / onBarChanged). Given the exitCode: 0 combined with the total absence of matched output, this looks like a race in Quickshell's Process exit-code delivery when two Process objects with the same command are started back-to-back/concurrently — the exit code from one may be getting cross-delivered, or a stale/default value is being read before the real child has actually reported. I haven't dug into Quickshell's C++ internals to confirm the exact mechanism.
Impact
Purely cosmetic — no real recording ever starts, so there's no risk of an unbounded video file or actual background recording. But the indicator is misleading (looks like an active recording is running for days), and clicking it fires omarchy-capture-screenrecording --stop-recording for no reason.
Suggested fix directions (not attached as a PR — wanted to flag this with full repro evidence first since I haven't been able to confirm the exact mechanism at the Quickshell layer)
- Share a single status check across all
ScreenRecordingindicator instances (e.g. a shared/singleton poll) instead of each monitor's indicator spawning its own concurrent identicalProcess, removing the suspected race by construction. - Add a periodic re-poll (the indicator currently only refreshes on
bar/indicatorHostsignals, so if it does get a false positive once, nothing corrects it afterward).
Happy to help test a fix if useful.
View raw text
## Summary The `ScreenRecording` bar indicator (`shell/plugins/bar/indicators/ScreenRecording.qml`) shows the "Stop recording" (active) state immediately after every shell/session restart or reboot, even though no `gpu-screen-recorder` process is actually running. This has persisted across multiple real reboots, not just shell restarts, so it isn't a leftover in-memory flag — the false-positive is regenerated fresh every boot. ## Environment - Omarchy 4.0.2-1 (Arch Linux, Hyprland) - Dual-monitor setup (two bar instances, so two `ScreenRecording` indicator instances load concurrently at startup) ## Evidence 1. **No real process ever exists.** Direct `/proc` scan for any process whose `exe` symlink resolves to `gpu-screen-recorder`, run repeatedly across restarts and reboots, finds nothing. `pgrep -af "^gpu-screen-recorder"` (unanchored, no `--quiet`) also finds nothing at any point I checked, including a 5-second 100ms-interval poll spanning a full shell restart. 2. **The widget's own script agrees nothing is recording.** Manually running `omarchy-capture-screenrecording --stop-recording` (the exact command the indicator's `onPressed` handler runs when it believes recording is active) hits the script's own `screenrecording_active()` check (a `pgrep -f "^gpu-screen-recorder"` call), finds nothing, and exits 1 via the `elif [[ $STOP_RECORDING == "true" ]]; exit 1` branch — i.e. the production script's own logic confirms no recording is active. 3. **The indicator's internal `pgrep` call still reports `exitCode: 0` (match found).** I temporarily instrumented a local copy of `ScreenRecording.qml` with `console.log` calls around `refresh()` and the `statusProc` `Process`, reinstalled it, and restarted the shell (`omarchy-restart-shell`) while tailing the journal. Every time, `statusProc`'s `onExited` handler fires with `exitCode: 0`, and `root.recording` flips to `true` — reproduced on repeated restarts. ``` [SR-DEBUG] Component.onCompleted [SR-DEBUG] refresh() called. bar: true statusProc.running: false [SR-DEBUG] statusProc launched [SR-DEBUG] statusProc.running changed: true [SR-DEBUG] statusProc EXITED, exitCode: 0 [SR-DEBUG] recording changed to true [SR-DEBUG] active changed to true ``` 4. **But the match itself doesn't exist.** I then changed the command from `pgrep --quiet -f "^gpu-screen-recorder"` to `pgrep -af "^gpu-screen-recorder"` (dropping `--quiet`, adding `-a` to print the matched line) and piped `stdout` through a `SplitParser` logging every line. `exitCode: 0` still fires on every restart, but **zero matched lines are ever printed** — i.e. `pgrep` is reporting a match was found while producing no output describing what matched. 5. Ruled out: no systemd user unit is active (`gpu-screen-recorder.service` is `disabled`/`inactive (dead)`), no Hyprland `exec-once` entry references the recorder, and `grep -r "gpu-screen-recorder"` across `/usr/share/omarchy` only matches the indicator itself and the `omarchy-capture-screenrecording` script — nothing else in Omarchy ever invokes the binary. ## Suspected cause This system has two monitors, so two `ScreenRecording` indicator instances mount concurrently at shell startup, each independently constructing an identical `Process` (`pgrep --quiet -f "^gpu-screen-recorder"`) and setting `running = true` within the same event loop tick (`Component.onCompleted` / `onBarChanged`). Given the `exitCode: 0` combined with the total absence of matched output, this looks like a race in Quickshell's `Process` exit-code delivery when two `Process` objects with the same command are started back-to-back/concurrently — the exit code from one may be getting cross-delivered, or a stale/default value is being read before the real child has actually reported. I haven't dug into Quickshell's C++ internals to confirm the exact mechanism. ## Impact Purely cosmetic — no real recording ever starts, so there's no risk of an unbounded video file or actual background recording. But the indicator is misleading (looks like an active recording is running for days), and clicking it fires `omarchy-capture-screenrecording --stop-recording` for no reason. ## Suggested fix directions (not attached as a PR — wanted to flag this with full repro evidence first since I haven't been able to confirm the exact mechanism at the Quickshell layer) - Share a single status check across all `ScreenRecording` indicator instances (e.g. a shared/singleton poll) instead of each monitor's indicator spawning its own concurrent identical `Process`, removing the suspected race by construction. - Add a periodic re-poll (the indicator currently only refreshes on `bar`/`indicatorHost` signals, so if it does get a false positive once, nothing corrects it afterward). Happy to help test a fix if useful.
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
- Related PRpr/10397· confirmed
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 10:50 UTC