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.
Universal Fix for Wedged-Style Popup Panels in Third-Party Plugins
Reported by M0VO · filed Sep 13, 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
System: Omarchy 4.0.3-1 / Quickshell 0.3.1 / Hyprland
What's wrong?
Supersedes: omarchy-popup-fix-report-2026-09-13.md (previous per-plugin fix)
Problem
Third-party Omarchy bar plugins that use a popup panel exhibit stuck overlays:
the popup opens but refuses to close. The panel stays mapped on screen and
swallows all mouse input on that monitor. The only recovery is killing the
shell with the emergency SUPER + SHIFT + ESC binding.
This affects every third-party plugin that was written against the older
Omarchy bar plugin API where centerHoverRevealSuppressed was a plain
writable property. It recurs identically whenever such a plugin is installed
or updated.
Confirmed affected plugins:
| Plugin | Status |
|---|---|
io.github.calebhat.weather (Detailed Weather) | Fixed in previous session |
yooneskh.omaniclean (OmaniClean) | Fixed in previous session |
omargram (OmarGram) | Reproduced bug (journal evidence below), then removed by user at 13:53:30 |
Root Cause
The Omarchy bar plugin API (PluginBarApi.qml:25-26) now exposes the
bar's hover-reveal state to plugins as a read-only property, with a
dedicated setter function:
// /usr/share/omarchy/shell/Ui/PluginBarApi.qml
readonly property bool centerHoverRevealSuppressed: _centerHoverRevealSuppressed
function setCenterHoverRevealSuppressed(value) {
if (_setCenterHoverRevealSuppressed) _setCenterHoverRevealSuppressed(!!value)
}Third-party plugins copied an older Omarchy panel template that assigned
directly to the property:
function setCenterHoverRevealSuppressed(value) {
if (root.bar && "centerHoverRevealSuppressed" in root.bar)
root.bar.centerHoverRevealSuppressed = value // ← QML TypeError: read-only
}The read-only assignment throws a QML TypeError, which aborts close()
before root.controller.hide() runs. The panel stays mapped and keeps
grabbing input — the "wedged overlay" effect.
Journal evidence (omargram, 2026-09-13):
WARN scene: .../omargram/Panel.qml[171:-1]:
TypeError: Cannot assign to read-only property "centerHoverRevealSuppressed"This pattern occurs because every third-party plugin author copied the same
older Omarchy template. The API change (read-only + setter function) is
documented in the built-in first-party panels, but no migration path was
provided for third-party plugins.
Why It Recurs
The root cause is not in the user's configuration files (shell.json,
Hyprland, etc.). It is a latent API compatibility issue between the packaged
bar's plugin interface and third-party plugin code. Any plugin written against
the older template will hit it identically on first open+close cycle.
Files Changed
Previous session (per-plugin fix)
~/.config/omarchy/plugins/io.github.calebhat.weather/Panel.qml~/.config/omarchy/plugins/yooneskh.omaniclean/Panel.qml
Both already carry the safe pattern (verified this session):weather/Panel.qml:69-73, omaniclean/Panel.qml:92-96.
This session (universal auto-patch script)
- `~/.config/omarchy/fix-plugin-popups.sh` — new universal scan + patch script
Fix: Universal Auto-Patch Script
~/.config/omarchy/fix-plugin-popups.sh scans every plugin panel under~/.config/omarchy/plugins/*/Panel.qml and, where it finds the broken
helper, rewrites it in place to the safe first-party pattern:
// Before (broken):
function setCenterHoverRevealSuppressed(value) {
if (root.bar && "centerHoverRevealSuppressed" in root.bar)
root.bar.centerHoverRevealSuppressed = value
}
// After (safe):
function setCenterHoverRevealSuppressed(value) {
if (root.bar && typeof root.bar.setCenterHoverRevealSuppressed === "function")
root.bar.setCenterHoverRevealSuppressed(value)
else if (root.bar && "centerHoverRevealSuppressed" in root.bar)
root.bar.centerHoverRevealSuppressed = value
}Already-fixed files (containing typeof root.bar.setCenterHoverRevealSuppressed)
are skipped. Plugins without the helper at all are also skipped.
Usage
# Scan and patch all broken plugins, then restart the shell:
~/.config/omarchy/fix-plugin-popups.sh
# Dry-run — report only, change nothing:
~/.config/omarchy/fix-plugin-popups.sh --check
# Patch but don't restart the shell (if you plan to do it separately):
~/.config/omarchy/fix-plugin-popups.sh --no-restartGit-Managed Plugin Workflow
Patching a git-cloned plugin creates an uncommitted working tree change,
which blocks omarchy plugin update (it uses git merge --ff-only). The
recommended workflow is:
# 1. Stash the local fix before updating
git -C ~/.config/omarchy/plugins/<id> stash
# 2. Update the plugin
omarchy plugin update <id>
# 3. Re-run the fix script to re-apply the patch to the updated code
~/.config/omarchy/fix-plugin-popups.shThis is idempotent — the script won't re-patch files that already have
the safe pattern.
When to Run
Run the script after:
- omarchy plugin add (new plugin install)
- omarchy plugin update (after the stash → update → re-run workflow above)
Verification
Script check (current state)
$ ~/.config/omarchy/fix-plugin-popups.sh --check
No broken plugin panels found — every panel already uses the safe pattern.Live toggle (weather + omaniclean, after shell restart)
$ omarchy-shell shell toggle io.github.calebhat.weather # open
$ omarchy-shell shell toggle io.github.calebhat.weather # close — no error
$ omarchy-shell shell toggle yooneskh.omaniclean # open
$ omarchy-shell shell toggle yooneskh.omaniclean # close — no errorJournal (5-minute window): no TypeError / Cannot assign to read-only
entries.
omargram note
At 13:53:30 the user removed omargram via omarchy-plugin-remove omargram
while debugging the wedged overlay. The journal confirms the same read-only
TypeError before removal:
Sep 13 13:38:23 WARN scene: .../omargram/Panel.qml[171:-1]:
TypeError: Cannot assign to read-only property "centerHoverRevealSuppressed"
Sep 13 13:38:33 WARN scene: ...
(repeated ~10 times while panel was wedged)Upstream Recommendation
The underlying fix should be applied in the packaged bar API
(/usr/share/omarchy/shell/Ui/PluginBarApi.qml) to preserve backward
compatibility with existing third-party plugins. A single change would make
all current and future plugins work without per-plugin patching:
// Suggested change in PluginBarApi.qml:
// Make centerHoverRevealSuppressed a writable property that
// delegates to the setter on assignment.
property bool centerHoverRevealSuppressed: false
onCenterHoverRevealSuppressedChanged: {
if (_setCenterHoverRevealSuppressed)
_setCenterHoverRevealSuppressed(centerHoverRevealSuppressed)
}
// Keep _centerHoverRevealSuppressed as the authoritative binding target
// (read from bar), with the public property as a compat shim.This would allow old plugins to assign directly while new plugins
use the setter function — both paths produce the same effect. Consider
filing this as a backward-compatibility enhancement in the Omarchy
issue tracker: https://github.com/basecamp/omarchy/issues
Summary
| Action | Result |
|---|---|
| Previous per-plugin fix | ✅ weather + omaniclean fixed and verified |
| Universal auto-patch script | ✅ created at ~/.config/omarchy/fix-plugin-popups.sh |
| Script dry-run (all plugins) | ✅ "No broken plugin panels found" |
| Live toggle test (weather, omaniclean) | ✅ open+close, no QML errors |
| Journal check (5-minute window) | ✅ clean — no TypeError / Cannot assign entries |
| Shell restart (post-fix) | ✅ clean startup (PID 3352702), no errors |
| omargram | Removed by user; same bug confirmed in journal |
| Remaining broken plugins | None installed |
View raw text
### System details
System: Omarchy 4.0.3-1 / Quickshell 0.3.1 / Hyprland
### What's wrong?
**Supersedes:** `omarchy-popup-fix-report-2026-09-13.md` (previous per-plugin fix)
---
## Problem
Third-party Omarchy bar plugins that use a popup panel exhibit **stuck overlays**:
the popup opens but refuses to close. The panel stays mapped on screen and
swallows all mouse input on that monitor. The only recovery is killing the
shell with the emergency `SUPER + SHIFT + ESC` binding.
This affects every third-party plugin that was written against the older
Omarchy bar plugin API where `centerHoverRevealSuppressed` was a plain
writable property. It recurs identically whenever such a plugin is installed
or updated.
**Confirmed affected plugins:**
| Plugin | Status |
|--------|--------|
| `io.github.calebhat.weather` (Detailed Weather) | Fixed in previous session |
| `yooneskh.omaniclean` (OmaniClean) | Fixed in previous session |
| `omargram` (OmarGram) | Reproduced bug (journal evidence below), then removed by user at 13:53:30 |
---
## Root Cause
The Omarchy bar plugin API (`PluginBarApi.qml:25-26`) now exposes the
bar's hover-reveal state to plugins as a **read-only** property, with a
dedicated setter function:
```js
// /usr/share/omarchy/shell/Ui/PluginBarApi.qml
readonly property bool centerHoverRevealSuppressed: _centerHoverRevealSuppressed
function setCenterHoverRevealSuppressed(value) {
if (_setCenterHoverRevealSuppressed) _setCenterHoverRevealSuppressed(!!value)
}
```
Third-party plugins copied an older Omarchy panel template that assigned
directly to the property:
```js
function setCenterHoverRevealSuppressed(value) {
if (root.bar && "centerHoverRevealSuppressed" in root.bar)
root.bar.centerHoverRevealSuppressed = value // ← QML TypeError: read-only
}
```
The read-only assignment throws a **QML TypeError**, which aborts `close()`
**before** `root.controller.hide()` runs. The panel stays mapped and keeps
grabbing input — the "wedged overlay" effect.
**Journal evidence (omargram, 2026-09-13):**
```
WARN scene: .../omargram/Panel.qml[171:-1]:
TypeError: Cannot assign to read-only property "centerHoverRevealSuppressed"
```
This pattern occurs because every third-party plugin author copied the same
older Omarchy template. The API change (read-only + setter function) is
documented in the built-in first-party panels, but no migration path was
provided for third-party plugins.
### Why It Recurs
The root cause is **not** in the user's configuration files (`shell.json`,
Hyprland, etc.). It is a latent API compatibility issue between the packaged
bar's plugin interface and third-party plugin code. Any plugin written against
the older template will hit it identically on first open+close cycle.
---
## Files Changed
### Previous session (per-plugin fix)
- `~/.config/omarchy/plugins/io.github.calebhat.weather/Panel.qml`
- `~/.config/omarchy/plugins/yooneskh.omaniclean/Panel.qml`
Both already carry the safe pattern (verified this session):
`weather/Panel.qml:69-73`, `omaniclean/Panel.qml:92-96`.
### This session (universal auto-patch script)
- **`~/.config/omarchy/fix-plugin-popups.sh`** — new universal scan + patch script
---
## Fix: Universal Auto-Patch Script
`~/.config/omarchy/fix-plugin-popups.sh` scans every plugin panel under
`~/.config/omarchy/plugins/*/Panel.qml` and, where it finds the broken
helper, rewrites it in place to the safe first-party pattern:
```js
// Before (broken):
function setCenterHoverRevealSuppressed(value) {
if (root.bar && "centerHoverRevealSuppressed" in root.bar)
root.bar.centerHoverRevealSuppressed = value
}
// After (safe):
function setCenterHoverRevealSuppressed(value) {
if (root.bar && typeof root.bar.setCenterHoverRevealSuppressed === "function")
root.bar.setCenterHoverRevealSuppressed(value)
else if (root.bar && "centerHoverRevealSuppressed" in root.bar)
root.bar.centerHoverRevealSuppressed = value
}
```
Already-fixed files (containing `typeof root.bar.setCenterHoverRevealSuppressed`)
are skipped. Plugins without the helper at all are also skipped.
### Usage
```bash
# Scan and patch all broken plugins, then restart the shell:
~/.config/omarchy/fix-plugin-popups.sh
# Dry-run — report only, change nothing:
~/.config/omarchy/fix-plugin-popups.sh --check
# Patch but don't restart the shell (if you plan to do it separately):
~/.config/omarchy/fix-plugin-popups.sh --no-restart
```
### Git-Managed Plugin Workflow
Patching a git-cloned plugin creates an uncommitted working tree change,
which blocks `omarchy plugin update` (it uses `git merge --ff-only`). The
recommended workflow is:
```bash
# 1. Stash the local fix before updating
git -C ~/.config/omarchy/plugins/<id> stash
# 2. Update the plugin
omarchy plugin update <id>
# 3. Re-run the fix script to re-apply the patch to the updated code
~/.config/omarchy/fix-plugin-popups.sh
```
This is idempotent — the script won't re-patch files that already have
the safe pattern.
### When to Run
Run the script after:
- `omarchy plugin add` (new plugin install)
- `omarchy plugin update` (after the stash → update → re-run workflow above)
---
## Verification
### Script check (current state)
```
$ ~/.config/omarchy/fix-plugin-popups.sh --check
No broken plugin panels found — every panel already uses the safe pattern.
```
### Live toggle (weather + omaniclean, after shell restart)
```
$ omarchy-shell shell toggle io.github.calebhat.weather # open
$ omarchy-shell shell toggle io.github.calebhat.weather # close — no error
$ omarchy-shell shell toggle yooneskh.omaniclean # open
$ omarchy-shell shell toggle yooneskh.omaniclean # close — no error
```
Journal (5-minute window): **no** `TypeError` / `Cannot assign to read-only`
entries.
### omargram note
At 13:53:30 the user removed omargram via `omarchy-plugin-remove omargram`
while debugging the wedged overlay. The journal confirms the same read-only
TypeError before removal:
```
Sep 13 13:38:23 WARN scene: .../omargram/Panel.qml[171:-1]:
TypeError: Cannot assign to read-only property "centerHoverRevealSuppressed"
Sep 13 13:38:33 WARN scene: ...
(repeated ~10 times while panel was wedged)
```
---
## Upstream Recommendation
The underlying fix should be applied in the packaged bar API
(`/usr/share/omarchy/shell/Ui/PluginBarApi.qml`) to preserve backward
compatibility with existing third-party plugins. A single change would make
all current and future plugins work without per-plugin patching:
```qml
// Suggested change in PluginBarApi.qml:
// Make centerHoverRevealSuppressed a writable property that
// delegates to the setter on assignment.
property bool centerHoverRevealSuppressed: false
onCenterHoverRevealSuppressedChanged: {
if (_setCenterHoverRevealSuppressed)
_setCenterHoverRevealSuppressed(centerHoverRevealSuppressed)
}
// Keep _centerHoverRevealSuppressed as the authoritative binding target
// (read from bar), with the public property as a compat shim.
```
This would allow old plugins to assign directly while new plugins
use the setter function — both paths produce the same effect. Consider
filing this as a backward-compatibility enhancement in the Omarchy
issue tracker: https://github.com/basecamp/omarchy/issues
---
## Summary
| Action | Result |
|--------|--------|
| Previous per-plugin fix | ✅ weather + omaniclean fixed and verified |
| Universal auto-patch script | ✅ created at `~/.config/omarchy/fix-plugin-popups.sh` |
| Script dry-run (all plugins) | ✅ "No broken plugin panels found" |
| Live toggle test (weather, omaniclean) | ✅ open+close, no QML errors |
| Journal check (5-minute window) | ✅ clean — no `TypeError` / `Cannot assign` entries |
| Shell restart (post-fix) | ✅ clean startup (PID 3352702), no errors |
| omargram | Removed by user; same bug confirmed in journal |
| Remaining broken plugins | None installed |
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/11080· 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 12:41 UTC