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.
Plugin hot-reload never clears the component cache: the Qt.clearComponentCache guard is always false
Reported by pmbemax · filed Sep 7, 2026Closed upstream on 2026-09-20 by bjarneo via an automated message, as a duplicate of #6981 (R-1835). 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
Summary
shell/shell.qml:784 guards the cache clear that makes plugin hot-reload work:
function finishPluginReload() {
...
if (typeof Qt.clearComponentCache === "function") Qt.clearComponentCache()
shell.pluginRegistry.rescan()
}That condition is always false. clearComponentCache() is a QQmlEngine member (/usr/include/qt6/QtQml/qqmlengine.h:67) and is not exposed on the QML Qt object, so the call never runs and the engine keeps its cached component for the edited file. rescan() then re-instantiates the cached type, and the plugin keeps running its previous code while the file on disk says something else.
Measured on Qt 6.11.2 / Omarchy 4.0.2:
// /tmp/qmlprobe2.qml
import QtQuick
Item {
Component.onCompleted: {
var t = typeof Qt.clearComponentCache
console.warn("PROBE typeof Qt.clearComponentCache = " + t)
Qt.exit(t === "function" ? 0 : 3)
}
}$ QT_QPA_PLATFORM=offscreen qml6 /tmp/qmlprobe2.qml ; echo exit=$?
exit=3i.e. not a function. grep -rn clearComponentCache /usr/lib/qt6/qml/QtQml/plugins.qmltypes is likewise empty — it is not in the QML type registry, only in the C++ header.
Why it matters
docs/omarchy-shell.md:113 documents the rescanPlugins IPC as "re-walk plugin dirs and hot-reload plugin code", and agents/skills/migrations.md:135 relies on the shell hot-reloading edits. In practice, editing a plugin's QML and triggering a reload leaves the old code live with no warning anywhere.
The failure mode is expensive precisely because it is silent: a plugin author edits a file, sees the old behaviour, and concludes the edit was wrong. It cost me a full day on a bar plugin, "fixing" code that was never loaded — and the only reliable signal is comparing file mtimes against the shell process start time.
Observed here as WARN scene: file:///…/Panel.qml:833: TypeError lines citing line numbers from a previous version of a 600-line file, after a reload the shell reported as successful.
Possible directions
I have not written a patch because the fix is on the C++ side and I would be guessing at Quickshell's intentions. Options as I see them, in the order I would consider them:
- Have Quickshell expose the engine call (an IPC or an attached property) and use it here; if Quickshell already has an equivalent, this is a one-line change to reach for it instead.
- If no such API exists, make the limitation loud rather than silent: log once at
WARNwhen a local plugin changes and the cache cannot be cleared, and say indocs/omarchy-shell.mdthat plugin code edits needomarchy restart shellwhileshell.jsonedits hot-reload. That alone would have saved me the day. - Sidestep the cache by loading plugin components through a URL that changes per reload (a cache-busting query on the component URL), if Quickshell's loader allows it.
Happy to test any of these on this machine — three monitors, a handful of first-party clones and third-party plugins, and a reproducible case.
System
Omarchy 4.0.2-1, Hyprland 0.56.2, Qt 6.11.2 (runtime and build), Arch, AMD RX 7900 XTX. shell/shell.qml as of main (c82a0837) still carries the guard at line 784.
View raw text
## Summary
`shell/shell.qml:784` guards the cache clear that makes plugin hot-reload work:
```qml
function finishPluginReload() {
...
if (typeof Qt.clearComponentCache === "function") Qt.clearComponentCache()
shell.pluginRegistry.rescan()
}
```
That condition is **always false**. `clearComponentCache()` is a `QQmlEngine` member (`/usr/include/qt6/QtQml/qqmlengine.h:67`) and is not exposed on the QML `Qt` object, so the call never runs and the engine keeps its cached component for the edited file. `rescan()` then re-instantiates the *cached* type, and the plugin keeps running its previous code while the file on disk says something else.
Measured on Qt 6.11.2 / Omarchy 4.0.2:
```qml
// /tmp/qmlprobe2.qml
import QtQuick
Item {
Component.onCompleted: {
var t = typeof Qt.clearComponentCache
console.warn("PROBE typeof Qt.clearComponentCache = " + t)
Qt.exit(t === "function" ? 0 : 3)
}
}
```
```
$ QT_QPA_PLATFORM=offscreen qml6 /tmp/qmlprobe2.qml ; echo exit=$?
exit=3
```
i.e. not a function. `grep -rn clearComponentCache /usr/lib/qt6/qml/QtQml/plugins.qmltypes` is likewise empty — it is not in the QML type registry, only in the C++ header.
## Why it matters
`docs/omarchy-shell.md:113` documents the `rescanPlugins` IPC as *"re-walk plugin dirs and hot-reload plugin code"*, and `agents/skills/migrations.md:135` relies on the shell hot-reloading edits. In practice, editing a plugin's QML and triggering a reload leaves the old code live with no warning anywhere.
The failure mode is expensive precisely because it is silent: a plugin author edits a file, sees the old behaviour, and concludes the edit was wrong. It cost me a full day on a bar plugin, "fixing" code that was never loaded — and the only reliable signal is comparing file mtimes against the shell process start time.
Observed here as `WARN scene: file:///…/Panel.qml:833: TypeError` lines citing line numbers from a *previous* version of a 600-line file, after a reload the shell reported as successful.
## Possible directions
I have not written a patch because the fix is on the C++ side and I would be guessing at Quickshell's intentions. Options as I see them, in the order I would consider them:
1. Have Quickshell expose the engine call (an IPC or an attached property) and use it here; if Quickshell already has an equivalent, this is a one-line change to reach for it instead.
2. If no such API exists, make the limitation loud rather than silent: log once at `WARN` when a local plugin changes and the cache cannot be cleared, and say in `docs/omarchy-shell.md` that plugin **code** edits need `omarchy restart shell` while `shell.json` edits hot-reload. That alone would have saved me the day.
3. Sidestep the cache by loading plugin components through a URL that changes per reload (a cache-busting query on the component URL), if Quickshell's loader allows it.
Happy to test any of these on this machine — three monitors, a handful of first-party clones and third-party plugins, and a reproducible case.
## System
Omarchy 4.0.2-1, Hyprland 0.56.2, Qt 6.11.2 (runtime and build), Arch, AMD RX 7900 XTX. `shell/shell.qml` as of `main` (`c82a0837`) still carries the guard at line 784.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.