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.
Cloned bar plugins: silent failure on denied service lookups, and nested QML files not hot-reloaded
Reported by piotrsynowiec · filed Sep 29, 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
Intel i7-9750H, Intel UHD 630 + AMD Radeon Pro 5500M (MacBook Pro T2), Omarchy 4.0.4-1
What's wrong?
Two related problems with cloned bar plugins (found with a clone of omarchy.indicators made via omarchy plugin clone):
1. Cloned indicators break silently after the scoped plugin shell API change
My clone (piotr.indicators, made before 4.0.4) had the StayAwake indicator looking up the idle service the old way:
readonly property string idleServiceId: bar?.shell?.pluginRegistry
? bar.shell.pluginRegistry.resolveEnabledId("omarchy.idle")
: "omarchy.idle"
readonly property var idleService: bar?.shell?.serviceFor(idleServiceId)With the scoped PluginShellApi / PluginRegistryApi, resolveEnabledId() returns "" for anything but the plugin's own id and serviceFor() only returns the plugin's own service, so idleService is always null. The icon still renders, but clicking it does nothing and it never shows as active. No warning is logged. The stock indicator already uses bar.shell.firstPartyServiceFor("omarchy.idle"), and switching the clone to that fixes it.
Expected: when a plugin asks for a service or id it's not allowed to access, the shell logs a warning (e.g. plugin piotr.indicators denied access to service omarchy.idle, use firstPartyServiceFor()), so broken clones are diagnosable after an update.
2. Hot reload doesn't pick up changes to nested QML files in a local plugin
Steps:
1. omarchy plugin clone omarchy.indicators
2. Edit ~/.config/omarchy/plugins/<user>.indicators/indicators/StayAwake.qml (e.g. add a console.warn in Component.onCompleted)
3. The log shows DEBUG qml: Local plugin changed, reloading: <user>.indicators, but the old StayAwake.qml keeps running (no new output, behaviour unchanged).
4. Only omarchy restart shell loads the edited file.
It looks like the QML component cache keeps the files loaded through Loader { source: Qt.resolvedUrl("indicators/" + id + ".qml") } in Indicators.qml, and the plugin reload only re-creates the entry point (engine.clearComponentCache(), or a cache-busting query on the source URL, would probably fix it).
View raw text
### System details
Intel i7-9750H, Intel UHD 630 + AMD Radeon Pro 5500M (MacBook Pro T2), Omarchy 4.0.4-1
### What's wrong?
Two related problems with cloned bar plugins (found with a clone of `omarchy.indicators` made via `omarchy plugin clone`):
**1. Cloned indicators break silently after the scoped plugin shell API change**
My clone (`piotr.indicators`, made before 4.0.4) had the `StayAwake` indicator looking up the idle service the old way:
```qml
readonly property string idleServiceId: bar?.shell?.pluginRegistry
? bar.shell.pluginRegistry.resolveEnabledId("omarchy.idle")
: "omarchy.idle"
readonly property var idleService: bar?.shell?.serviceFor(idleServiceId)
```
With the scoped `PluginShellApi` / `PluginRegistryApi`, `resolveEnabledId()` returns `""` for anything but the plugin's own id and `serviceFor()` only returns the plugin's own service, so `idleService` is always `null`. The icon still renders, but clicking it does nothing and it never shows as active. **No warning is logged.** The stock indicator already uses `bar.shell.firstPartyServiceFor("omarchy.idle")`, and switching the clone to that fixes it.
Expected: when a plugin asks for a service or id it's not allowed to access, the shell logs a warning (e.g. `plugin piotr.indicators denied access to service omarchy.idle, use firstPartyServiceFor()`), so broken clones are diagnosable after an update.
**2. Hot reload doesn't pick up changes to nested QML files in a local plugin**
Steps:
1. `omarchy plugin clone omarchy.indicators`
2. Edit `~/.config/omarchy/plugins/<user>.indicators/indicators/StayAwake.qml` (e.g. add a `console.warn` in `Component.onCompleted`)
3. The log shows `DEBUG qml: Local plugin changed, reloading: <user>.indicators`, but the old `StayAwake.qml` keeps running (no new output, behaviour unchanged).
4. Only `omarchy restart shell` loads the edited file.
It looks like the QML component cache keeps the files loaded through `Loader { source: Qt.resolvedUrl("indicators/" + id + ".qml") }` in `Indicators.qml`, and the plugin reload only re-creates the entry point (`engine.clearComponentCache()`, or a cache-busting query on the source URL, would probably fix it).
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-09 20:15 UTC