Proof Portal

Project overview

Omarchy

ProbeLabs65 findings · 95 requirements

A 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.

Inbox
ReportR-1200GitHub issuePublicDecided· Out of scope

Shell plugin hot-reload never picks up edited QML until full restart

Reported by kryakenHub · filed Aug 30, 2026Closed upstream on 2026-10-09 by the bot omarchybot, as a duplicate (target not recorded).

Decided: Out of scope — decided by agents · verified 4 days ago.

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

Shell plugin hot-reload never picks up edited QML until full restartrevision 1 · captured 2026-09-28 21:24 UTC via poll

Summary

User plugin code under ~/.config/omarchy/plugins/<id>/ does not actually hot-reload on save. The shell detects the change, logs Local plugin changed, reloading: <id> and re-instantiates the plugin — but the recreated instance is compiled from the old QML. Edits only take effect after a full shell restart.

Expected

Per the documented design "user plugin code under ~/.config/omarchy/plugins/ hot-reload on save": saving a plugin QML file should reload that plugin with the new code.

What actually happens

  1. Edit a plugin QML (e.g. add Component.onCompleted: console.log("V2MARKER") to BarWidget.qml).
  2. The shell logs Local plugin changed, reloading: KryakeN.Omarchy.Vless and re-creates the plugin — the Panel's Component.onCompleted debug line fires again ([KryakeN.Omarchy.Vless] completed: ...).
  3. The new code (V2MARKER) is never executed after the in-place reload.
  4. Only a full restart (e.g. pkill -x quickshell) loads the edited QML — the marker prints within ~100 ms of boot.

Evidence

Journal excerpt — in-place reload fired and re-instantiated the panel, but the marker added to the file on disk did not run:

Aug 31 03:56:58 omarchy-pc omarchy-shell[2606419]:  DEBUG qml: Local plugin changed, reloading: KryakeN.Omarchy.Vless
Aug 31 03:56:59 omarchy-pc omarchy-shell[2606419]:  DEBUG qml: [KryakeN.Omarchy.Vless] completed: testProcess=Process(...) statusProcess=Process(...) isTesting=false
# grep V2MARKER over this window: no output

After restart, the marker printed immediately. Additionally, no new entry was written under ~/.cache/quickshell/qmlcache/ after the save+reload — the loader served a cached compiled type instead of recompiling from the edited source.

Root-cause probe (runtime test against Quickshell 0.3.1):

console.log(typeof Qt.clearComponentCache)  // => "undefined"

Suspected cause

shell.qml in finishPluginReload() does:

if (typeof Qt.clearComponentCache === "function") Qt.clearComponentCache()

Quickshell does not expose Qt.clearComponentCache (the symbol exists only as the private Qt API QQmlEngine::clearComponentCache() in libQt6Qml.so), so the typeof guard silently never fires and the in-memory QML component cache is never flushed. After unloadPanels()/unloadPluginWidgets(), Qt.createComponent(url) in loadPluginWidget() therefore returns the previously compiled type for the same URL. Secondary stale path: syncPluginWidgets() re-registers the same existing.component when the registry key already exists.

Worth noting: this same reload-under-load path is a plausible contributor to the QQmlComponent::createWithProperties → __dynamic_cast → SIGSEGV crashes seen when iterating on plugin code (reload destroying a stale instance mid-signal-chain).

Suggested direction for a fix

  • On local plugin change, force a fresh compilation of that plugin's QML instead of relying on Qt.clearComponentCache (which Quickshell doesn't provide): e.g. purge ~/.cache/quickshell/qmlcache / the engine entry for the plugin URLs, or
  • If fresh components cannot be guaranteed within the running process, do a full shell restart instead of logging a misleading "reloading".

Environment

  • Omarchy 4.0.1-1 (Arch Linux), omarchy version
  • quickshell 0.3.1 (Arch package)
  • Hyprland under uwsm (Wayland), Intel i7-8700, VMware SVGA
View raw text
## Summary

User plugin code under `~/.config/omarchy/plugins/<id>/` does not actually hot-reload on save. The shell detects the change, logs `Local plugin changed, reloading: <id>` and re-instantiates the plugin — but the recreated instance is compiled from the **old** QML. Edits only take effect after a full shell restart.

## Expected

Per the documented design "user plugin code under `~/.config/omarchy/plugins/` hot-reload on save": saving a plugin QML file should reload that plugin with the new code.

## What actually happens

1. Edit a plugin QML (e.g. add `Component.onCompleted: console.log("V2MARKER")` to `BarWidget.qml`).
2. The shell logs `Local plugin changed, reloading: KryakeN.Omarchy.Vless` and re-creates the plugin — the Panel's `Component.onCompleted` debug line fires again (`[KryakeN.Omarchy.Vless] completed: ...`).
3. The new code (`V2MARKER`) is **never** executed after the in-place reload.
4. Only a full restart (e.g. `pkill -x quickshell`) loads the edited QML — the marker prints within ~100 ms of boot.

## Evidence

Journal excerpt — in-place reload fired and re-instantiated the panel, but the marker added to the file on disk did not run:

```
Aug 31 03:56:58 omarchy-pc omarchy-shell[2606419]:  DEBUG qml: Local plugin changed, reloading: KryakeN.Omarchy.Vless
Aug 31 03:56:59 omarchy-pc omarchy-shell[2606419]:  DEBUG qml: [KryakeN.Omarchy.Vless] completed: testProcess=Process(...) statusProcess=Process(...) isTesting=false
# grep V2MARKER over this window: no output
```

After restart, the marker printed immediately. Additionally, no new entry was written under `~/.cache/quickshell/qmlcache/` after the save+reload — the loader served a cached compiled type instead of recompiling from the edited source.

Root-cause probe (runtime test against Quickshell 0.3.1):

```
console.log(typeof Qt.clearComponentCache)  // => "undefined"
```

## Suspected cause

`shell.qml` in `finishPluginReload()` does:

```qml
if (typeof Qt.clearComponentCache === "function") Qt.clearComponentCache()
```

Quickshell does not expose `Qt.clearComponentCache` (the symbol exists only as the **private** Qt API `QQmlEngine::clearComponentCache()` in `libQt6Qml.so`), so the `typeof` guard silently never fires and the in-memory QML component cache is never flushed. After `unloadPanels()`/`unloadPluginWidgets()`, `Qt.createComponent(url)` in `loadPluginWidget()` therefore returns the previously compiled type for the same URL. Secondary stale path: `syncPluginWidgets()` re-registers the *same* `existing.component` when the registry key already exists.

Worth noting: this same reload-under-load path is a plausible contributor to the `QQmlComponent::createWithProperties → __dynamic_cast → SIGSEGV` crashes seen when iterating on plugin code (reload destroying a stale instance mid-signal-chain).

## Suggested direction for a fix

- On local plugin change, force a fresh compilation of that plugin's QML instead of relying on `Qt.clearComponentCache` (which Quickshell doesn't provide): e.g. purge `~/.cache/quickshell/qmlcache` / the engine entry for the plugin URLs, or
- If fresh components cannot be guaranteed within the running process, do a full shell restart instead of logging a misleading "reloading".

## Environment

- Omarchy 4.0.1-1 (Arch Linux), `omarchy version`
- quickshell 0.3.1 (Arch package)
- Hyprland under uwsm (Wayland), Intel i7-8700, VMware SVGA

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 10:09 UTC