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.
Third-party menu plugins receive a null shell.appLibrary, so replacement launchers show an empty Apps list
Reported by TheHatBoxGhost · filed Sep 10, 2026Closed upstream on 2026-09-20 by bjarneo via an automated message, as a duplicate of #10661 (R-860). 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
On Omarchy 4.0.3, a third-party plugin that declares "menu" in its manifest kinds is handed a plugin shell facade whose appLibrary is always null. Any replacement launcher therefore renders an empty Apps list and cannot find applications by name. First-party menus are unaffected.
Impact
Replacing the stock launcher with a third-party menu plugin silently loses the entire application list. In my case quantumfire.omalaunch shows "Nothing here yet" under Apps, and no application is searchable. There is no QML error and nothing is logged, so it looks like a broken desktop-entry index rather than a withheld capability.
Root cause
shell.qml:603 gates the capability on manifestHasKind():
appLibrary: shell.manifestHasKind(manifest, "menu")
? shell.pluginAppLibraryFor(cacheKey, key) : null,manifestHasKind() (shell.qml:349) tests Array.isArray(manifest.kinds).
For panel/overlay/menu plugins the manifest reaches createScopedPluginShell() by way of the Instantiator model built in computePanelEntries() (shell.qml:1312) and read back in the delegate as modelData (shell.qml:1330). That round trip converts the plain JS array in manifest.kinds into a QVariantList. indexOf() still works on it, but Array.isArray() returns false, so manifestHasKind() reports false and the app library is withheld.
First-party menus never reach this branch: pluginShellFor() returns the real shell for __isFirstParty manifests at shell.qml:740. That is why the stock omarchy.menu works and only third-party launchers break.
Minimal reproduction of the underlying conversion
import QtQuick
import Quickshell
ShellRoot {
property var entries: [{ id: "x", manifest: { id: "x", kinds: ["menu", "bar-widget"] } }]
Instantiator {
model: entries
active: true
delegate: QtObject {
required property var modelData
readonly property var manifest: modelData.manifest
Component.onCompleted: {
console.log("ISARRAY=" + Array.isArray(manifest.kinds)
+ " typeof=" + typeof manifest.kinds
+ " indexOf=" + manifest.kinds.indexOf("menu"))
}
}
}
}Output:
ISARRAY=false typeof=object indexOf=0Steps to reproduce the user-visible bug
- Install a third-party plugin whose manifest declares
"kinds": ["menu", "bar-widget"], for examplequantumfire.omalaunch. - Disable
omarchy.menuand place the third-party widget on the bar. - Open the plugin's menu and navigate to Apps.
Expected
The Apps submenu lists the desktop entries, exactly as the stock menu does.
Actual
The Apps submenu is empty. Instrumenting the plugin's injected shell object confirms the capability is missing rather than the app list being empty:
DBGSHELL pluginId=quantumfire.omalaunch
DBGSHELL keys=objectName,pluginId,appLibrary,bar,barConfig,idleConfig,...
DBGSHELL appLibraryDirect=NULL bar=yes barConfig=yes
DBGAPPS mergeAppRows appLibrary=NULL rows=0bar and barConfig are populated; only appLibrary is null, and it stays null for the life of the process.
Omarchy's own AppLibrary is healthy. Instantiating shell/services/AppLibrary.qml directly in a test shell on the same machine returns the full list:
RAW=72 SORTED=53
CHATGPT_SORTED=["chatgpt"]
HIDDEN_CFG=39 HIDDEN_DESK=31Suggested fix
Make manifestHasKind() tolerate a QVariantList, since the value is still list-like after the model round trip. For example:
function manifestHasKind(manifest, kind) {
var kinds = manifest && manifest.kinds
return !!kinds && typeof kinds.indexOf === "function" && kinds.indexOf(kind) !== -1
}Alternatively, pass the registry manifest (shell.pluginRegistry.installedPlugins[id]) into pluginShellFor() from the panel delegate instead of the modelData copy, so the original array is preserved.
Note that computePanelEntries() (shell.qml:1302) and PluginRegistry.qml also use Array.isArray(manifest.kinds). Those run before the model round trip and are correct today, but the same class of check would fail anywhere it is applied to a manifest read back out of a model.
Workaround
Until this is fixed, an affected plugin can build its own instance of $OMARCHY_PATH/shell/services/AppLibrary.qml with Qt.createComponent() whenever shell.appLibrary is null. That restores the full Apps list with identical behaviour.
System details
- Omarchy 4.0.3-1
- Hyprland 0.56.2
- quickshell 0.3.1-1, qt6-declarative 6.11.2-1
- Kernel 7.2.3-arch1-3
- CPU: Intel Core Ultra 7 258V
- GPU: Intel Arc Graphics 130V/140V
omarchy debug is not present in 4.0.3 on this install (Unknown Omarchy command: omarchy debug), so the details above were collected manually. Happy to attach a screenshot of the empty Apps menu if useful.
View raw text
## Summary
On Omarchy 4.0.3, a third-party plugin that declares `"menu"` in its manifest `kinds` is handed a plugin shell facade whose `appLibrary` is always `null`. Any replacement launcher therefore renders an empty Apps list and cannot find applications by name. First-party menus are unaffected.
## Impact
Replacing the stock launcher with a third-party menu plugin silently loses the entire application list. In my case `quantumfire.omalaunch` shows "Nothing here yet" under Apps, and no application is searchable. There is no QML error and nothing is logged, so it looks like a broken desktop-entry index rather than a withheld capability.
## Root cause
`shell.qml:603` gates the capability on `manifestHasKind()`:
```qml
appLibrary: shell.manifestHasKind(manifest, "menu")
? shell.pluginAppLibraryFor(cacheKey, key) : null,
```
`manifestHasKind()` (`shell.qml:349`) tests `Array.isArray(manifest.kinds)`.
For panel/overlay/menu plugins the manifest reaches `createScopedPluginShell()` by way of the `Instantiator` model built in `computePanelEntries()` (`shell.qml:1312`) and read back in the delegate as `modelData` (`shell.qml:1330`). That round trip converts the plain JS array in `manifest.kinds` into a `QVariantList`. `indexOf()` still works on it, but `Array.isArray()` returns `false`, so `manifestHasKind()` reports false and the app library is withheld.
First-party menus never reach this branch: `pluginShellFor()` returns the real `shell` for `__isFirstParty` manifests at `shell.qml:740`. That is why the stock `omarchy.menu` works and only third-party launchers break.
## Minimal reproduction of the underlying conversion
```qml
import QtQuick
import Quickshell
ShellRoot {
property var entries: [{ id: "x", manifest: { id: "x", kinds: ["menu", "bar-widget"] } }]
Instantiator {
model: entries
active: true
delegate: QtObject {
required property var modelData
readonly property var manifest: modelData.manifest
Component.onCompleted: {
console.log("ISARRAY=" + Array.isArray(manifest.kinds)
+ " typeof=" + typeof manifest.kinds
+ " indexOf=" + manifest.kinds.indexOf("menu"))
}
}
}
}
```
Output:
```
ISARRAY=false typeof=object indexOf=0
```
## Steps to reproduce the user-visible bug
1. Install a third-party plugin whose manifest declares `"kinds": ["menu", "bar-widget"]`, for example `quantumfire.omalaunch`.
2. Disable `omarchy.menu` and place the third-party widget on the bar.
3. Open the plugin's menu and navigate to Apps.
## Expected
The Apps submenu lists the desktop entries, exactly as the stock menu does.
## Actual
The Apps submenu is empty. Instrumenting the plugin's injected `shell` object confirms the capability is missing rather than the app list being empty:
```
DBGSHELL pluginId=quantumfire.omalaunch
DBGSHELL keys=objectName,pluginId,appLibrary,bar,barConfig,idleConfig,...
DBGSHELL appLibraryDirect=NULL bar=yes barConfig=yes
DBGAPPS mergeAppRows appLibrary=NULL rows=0
```
`bar` and `barConfig` are populated; only `appLibrary` is null, and it stays null for the life of the process.
Omarchy's own `AppLibrary` is healthy. Instantiating `shell/services/AppLibrary.qml` directly in a test shell on the same machine returns the full list:
```
RAW=72 SORTED=53
CHATGPT_SORTED=["chatgpt"]
HIDDEN_CFG=39 HIDDEN_DESK=31
```
## Suggested fix
Make `manifestHasKind()` tolerate a `QVariantList`, since the value is still list-like after the model round trip. For example:
```qml
function manifestHasKind(manifest, kind) {
var kinds = manifest && manifest.kinds
return !!kinds && typeof kinds.indexOf === "function" && kinds.indexOf(kind) !== -1
}
```
Alternatively, pass the registry manifest (`shell.pluginRegistry.installedPlugins[id]`) into `pluginShellFor()` from the panel delegate instead of the `modelData` copy, so the original array is preserved.
Note that `computePanelEntries()` (`shell.qml:1302`) and `PluginRegistry.qml` also use `Array.isArray(manifest.kinds)`. Those run before the model round trip and are correct today, but the same class of check would fail anywhere it is applied to a manifest read back out of a model.
## Workaround
Until this is fixed, an affected plugin can build its own instance of `$OMARCHY_PATH/shell/services/AppLibrary.qml` with `Qt.createComponent()` whenever `shell.appLibrary` is null. That restores the full Apps list with identical behaviour.
## System details
- Omarchy 4.0.3-1
- Hyprland 0.56.2
- quickshell 0.3.1-1, qt6-declarative 6.11.2-1
- Kernel 7.2.3-arch1-3
- CPU: Intel Core Ultra 7 258V
- GPU: Intel Arc Graphics 130V/140V
`omarchy debug` is not present in 4.0.3 on this install (`Unknown Omarchy command: omarchy debug`), so the details above were collected manually. Happy to attach a screenshot of the empty Apps menu if useful.
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.