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.
App library rescans hidden entries on every save of any file in $HOME (no debounce, ~105 processes per scan)
Reported by benedikt-personal · filed Oct 10, 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
Version: omarchy 4.0.4-1, quickshell 0.3.1-1.
Problem
shell/services/AppLibrary.qml starts hiddenEntryScan (shell/services/hidden-entries.sh) on every DesktopEntries.applications onValuesChanged, with no debounce. iconIndexScan already uses a 750 ms Timer (iconIndexDebounce) for the same signal; hiddenEntryScan does not.
Quickshell's desktop-entry watcher holds inotify watches on $HOME, ~/.local, ~/.local/share and the applications folders (verified in /proc/<quickshell pid>/fdinfo). A normal atomic save of any file in $HOME (for example ~/.claude.json written by Claude Code: lock dir, tmp file, rename) therefore fires the signal. In a 90 s trace one save produced 3 scans within 0.4 s. In a later 60 s window with normal use: 1 save, 2 scans.
Cost per scan (99 .desktop files): about 105-135 forks, 0.34 s wall, 0.36 s CPU. The forks come from id=$(desktop_id_for_file ...), one command-substitution subshell per file. On a machine where agents save the file often, reaped quickshell children averaged 19.8 percent of one core over 26.3 h (CORCO-2013 measurement).
Suggested fix (two parts)
1. In AppLibrary.qml add a debounce Timer for hiddenEntryScan, same as iconIndexDebounce (interval 750), and call hiddenEntryDebounce.restart() instead of hiddenEntryScan.running = true in onValuesChanged. Keep the immediate scan in Component.onCompleted.
2. Remove the per-file subshell in hidden-entries.sh. Tested: output identical (29 ids), forks about 125 -> about 25-45, wall 345 ms -> 175 ms.
@@ -30,7 +30,7 @@
local rel=${file#"$dir"/}
rel=${rel%.desktop}
- printf '%s\n' "${rel//\//-}"
+ desktop_id=${rel//\//-}
}
is_hidden_desktop_file() {
@@ -82,7 +82,8 @@
[[ -d $dir ]] || return
while IFS= read -r -d '' file; do
- id=$(desktop_id_for_file "$dir" "$file")
+ desktop_id_for_file "$dir" "$file"
+ id=$desktop_id
[[ -n ${seen_ids[$id]+set} ]] && continue
seen_ids[$id]=1
Optional, quickshell side (https://git.outfoxxed.me/quickshell/quickshell): DesktopEntryMonitor could ignore events on parent directories whose name is not the next path component of a watched applications folder, or only emit when a *.desktop file or an applications folder changed.
Workaround found: none. AppLibrary is instantiated directly in shell.qml (not a plugin), the script path is fixed to $OMARCHY_PATH/shell/services, and no quickshell environment variable controls the DesktopEntries watcher.
View raw text
Version: omarchy 4.0.4-1, quickshell 0.3.1-1.
Problem
shell/services/AppLibrary.qml starts hiddenEntryScan (shell/services/hidden-entries.sh) on every DesktopEntries.applications onValuesChanged, with no debounce. iconIndexScan already uses a 750 ms Timer (iconIndexDebounce) for the same signal; hiddenEntryScan does not.
Quickshell's desktop-entry watcher holds inotify watches on $HOME, ~/.local, ~/.local/share and the applications folders (verified in /proc/<quickshell pid>/fdinfo). A normal atomic save of any file in $HOME (for example ~/.claude.json written by Claude Code: lock dir, tmp file, rename) therefore fires the signal. In a 90 s trace one save produced 3 scans within 0.4 s. In a later 60 s window with normal use: 1 save, 2 scans.
Cost per scan (99 .desktop files): about 105-135 forks, 0.34 s wall, 0.36 s CPU. The forks come from `id=$(desktop_id_for_file ...)`, one command-substitution subshell per file. On a machine where agents save the file often, reaped quickshell children averaged 19.8 percent of one core over 26.3 h (CORCO-2013 measurement).
Suggested fix (two parts)
1. In AppLibrary.qml add a debounce Timer for hiddenEntryScan, same as iconIndexDebounce (interval 750), and call hiddenEntryDebounce.restart() instead of hiddenEntryScan.running = true in onValuesChanged. Keep the immediate scan in Component.onCompleted.
2. Remove the per-file subshell in hidden-entries.sh. Tested: output identical (29 ids), forks about 125 -> about 25-45, wall 345 ms -> 175 ms.
```diff
@@ -30,7 +30,7 @@
local rel=${file#"$dir"/}
rel=${rel%.desktop}
- printf '%s\n' "${rel//\//-}"
+ desktop_id=${rel//\//-}
}
is_hidden_desktop_file() {
@@ -82,7 +82,8 @@
[[ -d $dir ]] || return
while IFS= read -r -d '' file; do
- id=$(desktop_id_for_file "$dir" "$file")
+ desktop_id_for_file "$dir" "$file"
+ id=$desktop_id
[[ -n ${seen_ids[$id]+set} ]] && continue
seen_ids[$id]=1
```
Optional, quickshell side (https://git.outfoxxed.me/quickshell/quickshell): DesktopEntryMonitor could ignore events on parent directories whose name is not the next path component of a watched applications folder, or only emit when a *.desktop file or an applications folder changed.
Workaround found: none. AppLibrary is instantiated directly in shell.qml (not a plugin), the script path is fixed to $OMARCHY_PATH/shell/services, and no quickshell environment variable controls the DesktopEntries watcher.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
- Fixed bypr/14992· 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-10 17:10 UTC