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.
Orphan inotifywait processes accumulate watching ~/.config/omarchy/plugins
Reported by zhainan99 · filed Sep 7, 2026Closed upstream on 2026-09-21 by bjarneo via an automated message, as a duplicate of #7150 (R-1759). GitHub close reason: completed.
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?
- Not yet mapped to any requirement or component.
- 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?
- Our staff decide whether the report is valid. Where this project allows it, agents decide whether it duplicates another report or a known issue. No decision has been recorded yet.
Original report
Orphan inotifywait processes accumulate watching ~/.config/omarchy/plugins
Summary
Quickshell's PluginRegistry.qml spawns an inotifywait -m -r watcher on~/.config/omarchy/plugins to hot-reload local plugins. Over time the number
of such watcher processes grows unbounded, and stale ones become orphans
reparented to systemd --user, never terminating.
Steps to reproduce
On an installed Omarchy system, over a session (especially afteromarchy restart shell / re-login, or plugin file changes that trigger the
watcher restart path), count the watchers:
ps -eo pid,ppid,cmd | grep "inotifywait.*omarchy/plugins"Observed: 19-20 concurrent `inotifywait -m -r -q -e close_write,create,delete,move
--format %w%f /home/zhainan/.config/omarchy/plugins` processes, all but one with
PPID = systemd --user (orphaned, original parent gone).
Expected behavior
Exactly one live watcher per running Quickshell instance; it should be
terminated together with the shell, and never accumulate across restarts.
Evidence / Root cause
/usr/share/omarchy/shell/services/PluginRegistry.qml
property Process localPluginWatcher: Process {
command: ["inotifywait", "-m", "-r", "-q", "-e",
"close_write,create,delete,move", "--format", "%w%f",
registry.pluginsDir]
onExited: localPluginWatcherRestart.restart()
}
property Timer localPluginWatcherRestart: Timer {
interval: 1000
onTriggered: localPluginWatcher.running = true
}The running = true re-assert path (and shell restart) starts a newinotifywait without stopping the previous one. On Quickshell exit the childinotifywait is not reaped (it becomes a systemd --user orphan), so each
shell lifecycle leaks one watcher. With restarts triggered by file events, the
leak is much faster (observed ~1/minute while plugin dir was being touched).
Impact
- 20 resident processes, each holding an inotify watch on the whole
~/.config/omarchy/plugins tree (recursive), consuming inotify watch slots
and file descriptors.
- With fs.inotify.max_user_watches tuning, exhaustion of watch slots can
break other inotify-dependent tools (editors, file watchers, vim, tmux).
- Terminating the orphan watchers does NOT stop the leak; the underlying
process lifecycle is the bug.
Workaround
# kill only orphans (parent = systemd --user)
pkill -P $(pgrep -f "systemd --user" | head -1) -f "inotifywait.*omarchy/plugins"Note: pkill -P <systemd-user-pid> is fragile; safer is to match PPID.
System
- Omarchy: 4.0.2-1 (pacman
omarchy) - Kernel: Linux 7.1.9-arch1-2
- CPU: Intel(R) N100 (4 cores)
- GPU: Intel Alder Lake-N UHD Graphics
- Compositor: Hyprland (Wayland)
Suggested fix
- Use a single long-lived watcher and stop it (
running = false) before
re-asserting, or bind the watcher lifetime to the Process/shell lifecycle
so Quickshell kills it on exit (e.g. a Process that is part of the shell
process group / KillMode).
- Stop prior inotifywait (via the Process handle's running = false) in
onExited, or use a singleInstance/dedupe guard so only one process per
plugin dir exists.
View raw text
# Orphan `inotifywait` processes accumulate watching ~/.config/omarchy/plugins
## Summary
Quickshell's `PluginRegistry.qml` spawns an `inotifywait -m -r` watcher on
`~/.config/omarchy/plugins` to hot-reload local plugins. Over time the number
of such watcher processes grows unbounded, and stale ones become orphans
reparented to `systemd --user`, never terminating.
## Steps to reproduce
On an installed Omarchy system, over a session (especially after
`omarchy restart shell` / re-login, or plugin file changes that trigger the
watcher restart path), count the watchers:
```bash
ps -eo pid,ppid,cmd | grep "inotifywait.*omarchy/plugins"
```
Observed: 19-20 concurrent `inotifywait -m -r -q -e close_write,create,delete,move
--format %w%f /home/zhainan/.config/omarchy/plugins` processes, all but one with
PPID = `systemd --user` (orphaned, original parent gone).
## Expected behavior
Exactly one live watcher per running Quickshell instance; it should be
terminated together with the shell, and never accumulate across restarts.
## Evidence / Root cause
`/usr/share/omarchy/shell/services/PluginRegistry.qml`
```qml
property Process localPluginWatcher: Process {
command: ["inotifywait", "-m", "-r", "-q", "-e",
"close_write,create,delete,move", "--format", "%w%f",
registry.pluginsDir]
onExited: localPluginWatcherRestart.restart()
}
property Timer localPluginWatcherRestart: Timer {
interval: 1000
onTriggered: localPluginWatcher.running = true
}
```
The `running = true` re-assert path (and shell restart) starts a new
`inotifywait` without stopping the previous one. On Quickshell exit the child
`inotifywait` is not reaped (it becomes a `systemd --user` orphan), so each
shell lifecycle leaks one watcher. With restarts triggered by file events, the
leak is much faster (observed ~1/minute while plugin dir was being touched).
## Impact
- 20 resident processes, each holding an inotify watch on the whole
`~/.config/omarchy/plugins` tree (recursive), consuming inotify watch slots
and file descriptors.
- With `fs.inotify.max_user_watches` tuning, exhaustion of watch slots can
break other inotify-dependent tools (editors, file watchers, `vim`, `tmux`).
- Terminating the orphan watchers does NOT stop the leak; the underlying
process lifecycle is the bug.
## Workaround
```bash
# kill only orphans (parent = systemd --user)
pkill -P $(pgrep -f "systemd --user" | head -1) -f "inotifywait.*omarchy/plugins"
```
Note: `pkill -P <systemd-user-pid>` is fragile; safer is to match PPID.
## System
- Omarchy: 4.0.2-1 (pacman `omarchy`)
- Kernel: Linux 7.1.9-arch1-2
- CPU: Intel(R) N100 (4 cores)
- GPU: Intel Alder Lake-N UHD Graphics
- Compositor: Hyprland (Wayland)
## Suggested fix
- Use a single long-lived watcher and stop it (`running = false`) before
re-asserting, or bind the watcher lifetime to the `Process`/shell lifecycle
so Quickshell kills it on exit (e.g. a `Process` that is part of the shell
process group / `KillMode`).
- Stop prior `inotifywait` (via the `Process` handle's `running = false`) in
`onExited`, or use a `singleInstance`/dedupe guard so only one process per
plugin dir exists.
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.
No decision has been recorded yet.