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 scan process fails at runtime — bar widgets (bluetooth, agents, etc.) not registered
Reported by S4FoGui · filed Sep 21, 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
Especificações do Sistema ┌────────────────┬────────────────────────────────────────────────┐ │ Componente │ Detalhes │ ├────────────────┼────────────────────────────────────────────────┤ │ CPU │ AMD Ryzen 3 PRO 2200G com Radeon Vega Graphics │ ├────────────────┼────────────────────────────────────────────────┤ │ Cores/Threads │ 4 cores / 4 threads (1 thread por core) │ ├────────────────┼────────────────────────────────────────────────┤ │ Clock │ Base 1.6 GHz · Boost 3.7 GHz · Atual ~1.56 GHz │ ├────────────────┼────────────────────────────────────────────────┤ │ Socket │ AM4 │ ├────────────────┼────────────────────────────────────────────────┤ │ Placa-mãe │ Gigabyte B450M DS3H-CF (rev "Default string") │ ├────────────────┼────────────────────────────────────────────────┤ │ BIOS │ AMI F67a (04/11/2024) │ ├────────────────┼────────────────────────────────────────────────┤ │ RAM Total │ 13.6 GiB (14.2 GB) │ ├────────────────┼────────────────────────────────────────────────┤ │ RAM Livre │ ~4.3 GiB │ ├────────────────┼────────────────────────────────────────────────┤ │ RAM Disponível │ ~8.5 GiB (com cache) │ ├────────────────┼────────────────────────────────────────────────┤ │ Swap │ 27 GiB (358 MiB usado) │ ├────────────────┼────────────────────────────────────────────────┤ │ NUMA │ Single node (node0: CPUs 0-3) │ └────────────────┴────────────────────────────────────────────────┘ Notas: - iGPU Vega integrada (sem GPU discreta detectada) - DDR4 presumida (B450 suporta até 3200 MHz OC) - dmidecode sem detalhes de módulos DIMM (precisa sudo ou kernel sem exposição SMBIOS completa)
What's wrong?
Bug Report: Plugin scan process fails at runtime — bar widgets (bluetooth, agents, etc.) not registered
System Details
- Omarchy Version: 4.0.4-1 (stable)
- Channel: stable
- Kernel:
$(uname -r) - Hyprland:
$(hyprctl version | head -1) - Quickshell:
$(quickshell --version 2>/dev/null || echo "unknown")
Issue Summary
The Omarchy shell's plugin registry scan process (scanProcess in PluginRegistry.qml) fails to execute at runtime. This prevents first-party plugins (bluetooth, agents, audio, network, etc.) from being discovered and registered as bar widgets. The widgets are configured in shell.json and their manifests are valid, but they never appear in the top bar.
Expected Behavior
- On shell startup,
PluginRegistry.rescan()runs the scan script - Scan script outputs
===firstparty::...===and===thirdparty::...===blocks for each plugin parseScanOutputpopulatesinstalledPluginsonScanFinishedtriggerssyncPluginWidgets()- Widgets with
kinds: ["bar-widget"]are loaded viaQt.createComponent()and registered inBarWidgetRegistry - Bluetooth widget (and others) appear in the bar
Actual Behavior
- No
===firstparty::...===or===thirdparty::...===output in quickshell logs installedPluginsremains emptysyncPluginWidgets()has nothing to register- Bluetooth widget missing from bar despite being in
bar.layout.right - Other first-party widgets also missing (agents, etc.)
Evidence: Bluetooth Backend Works Perfectly
$ systemctl status bluetooth
● bluetooth.service - Bluetooth service
Active: active (running)
$ bluetoothctl show
Controller 04:7F:0E:0F:CA:B3 (public)
Powered: yes
$ bluetoothctl info EC:4D:5E:6E:CD:B0
Device EC:4D:5E:6E:CD:B0 (public)
Name: RS56
Connected: yes
Battery Percentage: 0x14 (20)Quickshell logs show Bluetooth C++ backend working:
Tracked new adapter BluetoothAdapter(0x..., path="/org/bluez/hci0")
Updated property org.bluez/.../PowerState to qs::bluetooth::BluetoothAdapterState::Enabled
Tracked new device BluetoothDevice(0x..., path="/org/bluez/hci0/dev_EC_4D_5E_6E_CD_B0")
Added device ... to adapter ...Root Cause Analysis
In /usr/share/omarchy/shell/services/PluginRegistry.qml, the rescan() function assigns a long multi-line bash script string to scanProcess.command:
function rescan() {
if (scanning) return
scanning = true
var script = ""
+ "emit_manifest() { ... }; "
+ "scan_firstparty() { ... }; "
+ "scan_thirdparty() { ... }; "
+ "scan_firstparty \"$0\"; "
+ "scan_thirdparty \"$1\""
scanProcess.command = ["bash", "-c", script, registry.firstPartyDir, registry.pluginsDir]
scanProcess.running = true
}The Process component (from Quickshell.Io) fails to start when command is assigned a long dynamic string at runtime. Other Process components in the same file work fine:
- localPluginWatcher (inotifywait) — simple command, works
- initProcess (mkdir -p) — simple command, works
Manual execution of the exact same script works perfectly:
$ bash -c '...scan script...' /usr/share/omarchy/shell/plugins /home/gui/.config/omarchy/plugins
===firstparty::/usr/share/omarchy/shell/plugins/panels/bluetooth===
{ "id": "omarchy.bluetooth", "kinds": ["bar-widget"], ... }
=== EOM ===
...
(1022 lines total, 20+ plugins discovered)Shell Config (shell.json)
{
"bar": {
"layout": {
"right": [
{ "id": "omarchy.tray" },
{ "id": "tzglobic.monitor-arranger" },
{ "id": "omarchy.agents" },
{ "id": "omarchy.bluetooth" }, // ← configured but not rendered
{ "id": "omarchy.network" },
{ "id": "omarchy.audio" }
]
}
}
}Reproduction Steps
- Fresh Omarchy install (4.0.4-1)
- Login to Hyprland session
- Observe top bar — bluetooth widget missing
- Check quickshell logs:
strings /run/user/1000/quickshell/by-id/*/log.qslog | grep "===firstparty" - No scan output found
- Run
omarchy shell shell rescanPlugins— no effect - Run
omarchy restart shell— no effect
Proposed Fix
Move the scan script to an external file and execute it:
1. Create `/usr/share/omarchy/shell/services/scan-plugins.sh`:
#!/bin/bash
set -euo pipefail
emit_manifest() {
local kind="$1"; local manifest="$2"; local sub
if [[ ${manifest##*/} == "manifest.json" ]]; then sub="${manifest%/manifest.json}"; else sub="$(dirname -- "$manifest")"; fi
printf '===%s::%s===\n' "$kind" "$sub"
cat "$manifest"
printf '\n=== EOM ===\n'
}
scan_firstparty() {
local dir="$1"; [[ -d "$dir" ]] || return 0
while IFS= read -r manifest; do emit_manifest firstparty "$manifest"; done < <(find "$dir" -mindepth 2 -maxdepth 3 -type f \( -name manifest.json -o -name '*.manifest.json' \) | sort)
}
scan_thirdparty() {
local dir="$1"; [[ -d "$dir" ]] || return 0
for sub in "$dir"/*/; do [[ -f "$sub/manifest.json" ]] || continue; emit_manifest thirdparty "$sub/manifest.json"; done
}
scan_firstparty "$1"
scan_thirdparty "$2"2. Update `PluginRegistry.qml` `rescan()`:
function rescan() {
if (scanning) return
scanning = true
var scriptPath = "/usr/share/omarchy/shell/services/scan-plugins.sh"
scanProcess.command = ["bash", scriptPath, registry.firstPartyDir, registry.pluginsDir]
scanProcess.running = true
}Workaround (User-level)
omarchy hook install startup 'sleep 3 && omarchy restart shell'(Sometimes works if user plugin dir exists at startup)
Related Files
/usr/share/omarchy/shell/services/PluginRegistry.qml(lines ~715-730)/usr/share/omarchy/shell/shell.qml(lines ~1440-1500,syncPluginWidgets,onScanFinished)/usr/share/omarchy/shell/plugins/panels/bluetooth/manifest.json/usr/share/omarchy/shell/plugins/panels/bluetooth/Panel.qml
This is a critical bug affecting all first-party bar widgets on fresh installs. The Bluetooth backend works; only the widget registration pipeline is broken.
View raw text
### System details
Especificações do Sistema ┌────────────────┬────────────────────────────────────────────────┐ │ Componente │ Detalhes │ ├────────────────┼────────────────────────────────────────────────┤ │ CPU │ AMD Ryzen 3 PRO 2200G com Radeon Vega Graphics │ ├────────────────┼────────────────────────────────────────────────┤ │ Cores/Threads │ 4 cores / 4 threads (1 thread por core) │ ├────────────────┼────────────────────────────────────────────────┤ │ Clock │ Base 1.6 GHz · Boost 3.7 GHz · Atual ~1.56 GHz │ ├────────────────┼────────────────────────────────────────────────┤ │ Socket │ AM4 │ ├────────────────┼────────────────────────────────────────────────┤ │ Placa-mãe │ Gigabyte B450M DS3H-CF (rev "Default string") │ ├────────────────┼────────────────────────────────────────────────┤ │ BIOS │ AMI F67a (04/11/2024) │ ├────────────────┼────────────────────────────────────────────────┤ │ RAM Total │ 13.6 GiB (14.2 GB) │ ├────────────────┼────────────────────────────────────────────────┤ │ RAM Livre │ ~4.3 GiB │ ├────────────────┼────────────────────────────────────────────────┤ │ RAM Disponível │ ~8.5 GiB (com cache) │ ├────────────────┼────────────────────────────────────────────────┤ │ Swap │ 27 GiB (358 MiB usado) │ ├────────────────┼────────────────────────────────────────────────┤ │ NUMA │ Single node (node0: CPUs 0-3) │ └────────────────┴────────────────────────────────────────────────┘ Notas: - iGPU Vega integrada (sem GPU discreta detectada) - DDR4 presumida (B450 suporta até 3200 MHz OC) - dmidecode sem detalhes de módulos DIMM (precisa sudo ou kernel sem exposição SMBIOS completa)
### What's wrong?
## Bug Report: Plugin scan process fails at runtime — bar widgets (bluetooth, agents, etc.) not registered
### System Details
- **Omarchy Version:** 4.0.4-1 (stable)
- **Channel:** stable
- **Kernel:** `$(uname -r)`
- **Hyprland:** `$(hyprctl version | head -1)`
- **Quickshell:** `$(quickshell --version 2>/dev/null || echo "unknown")`
### Issue Summary
The Omarchy shell's plugin registry scan process (`scanProcess` in `PluginRegistry.qml`) fails to execute at runtime. This prevents first-party plugins (bluetooth, agents, audio, network, etc.) from being discovered and registered as bar widgets. The widgets are configured in `shell.json` and their manifests are valid, but they never appear in the top bar.
### Expected Behavior
- On shell startup, `PluginRegistry.rescan()` runs the scan script
- Scan script outputs `===firstparty::...===` and `===thirdparty::...===` blocks for each plugin
- `parseScanOutput` populates `installedPlugins`
- `onScanFinished` triggers `syncPluginWidgets()`
- Widgets with `kinds: ["bar-widget"]` are loaded via `Qt.createComponent()` and registered in `BarWidgetRegistry`
- Bluetooth widget (and others) appear in the bar
### Actual Behavior
- No `===firstparty::...===` or `===thirdparty::...===` output in quickshell logs
- `installedPlugins` remains empty
- `syncPluginWidgets()` has nothing to register
- Bluetooth widget missing from bar despite being in `bar.layout.right`
- Other first-party widgets also missing (agents, etc.)
### Evidence: Bluetooth Backend Works Perfectly
```bash
$ systemctl status bluetooth
● bluetooth.service - Bluetooth service
Active: active (running)
$ bluetoothctl show
Controller 04:7F:0E:0F:CA:B3 (public)
Powered: yes
$ bluetoothctl info EC:4D:5E:6E:CD:B0
Device EC:4D:5E:6E:CD:B0 (public)
Name: RS56
Connected: yes
Battery Percentage: 0x14 (20)
```
Quickshell logs show Bluetooth C++ backend working:
```
Tracked new adapter BluetoothAdapter(0x..., path="/org/bluez/hci0")
Updated property org.bluez/.../PowerState to qs::bluetooth::BluetoothAdapterState::Enabled
Tracked new device BluetoothDevice(0x..., path="/org/bluez/hci0/dev_EC_4D_5E_6E_CD_B0")
Added device ... to adapter ...
```
### Root Cause Analysis
In `/usr/share/omarchy/shell/services/PluginRegistry.qml`, the `rescan()` function assigns a long multi-line bash script string to `scanProcess.command`:
```qml
function rescan() {
if (scanning) return
scanning = true
var script = ""
+ "emit_manifest() { ... }; "
+ "scan_firstparty() { ... }; "
+ "scan_thirdparty() { ... }; "
+ "scan_firstparty \"$0\"; "
+ "scan_thirdparty \"$1\""
scanProcess.command = ["bash", "-c", script, registry.firstPartyDir, registry.pluginsDir]
scanProcess.running = true
}
```
The `Process` component (from `Quickshell.Io`) fails to start when `command` is assigned a long dynamic string at runtime. Other `Process` components in the same file work fine:
- `localPluginWatcher` (inotifywait) — simple command, works
- `initProcess` (mkdir -p) — simple command, works
Manual execution of the exact same script works perfectly:
```bash
$ bash -c '...scan script...' /usr/share/omarchy/shell/plugins /home/gui/.config/omarchy/plugins
===firstparty::/usr/share/omarchy/shell/plugins/panels/bluetooth===
{ "id": "omarchy.bluetooth", "kinds": ["bar-widget"], ... }
=== EOM ===
...
(1022 lines total, 20+ plugins discovered)
```
### Shell Config (shell.json)
```json
{
"bar": {
"layout": {
"right": [
{ "id": "omarchy.tray" },
{ "id": "tzglobic.monitor-arranger" },
{ "id": "omarchy.agents" },
{ "id": "omarchy.bluetooth" }, // ← configured but not rendered
{ "id": "omarchy.network" },
{ "id": "omarchy.audio" }
]
}
}
}
```
### Reproduction Steps
1. Fresh Omarchy install (4.0.4-1)
2. Login to Hyprland session
3. Observe top bar — bluetooth widget missing
4. Check quickshell logs: `strings /run/user/1000/quickshell/by-id/*/log.qslog | grep "===firstparty"`
5. No scan output found
6. Run `omarchy shell shell rescanPlugins` — no effect
7. Run `omarchy restart shell` — no effect
### Proposed Fix
Move the scan script to an external file and execute it:
**1. Create `/usr/share/omarchy/shell/services/scan-plugins.sh`:**
```bash
#!/bin/bash
set -euo pipefail
emit_manifest() {
local kind="$1"; local manifest="$2"; local sub
if [[ ${manifest##*/} == "manifest.json" ]]; then sub="${manifest%/manifest.json}"; else sub="$(dirname -- "$manifest")"; fi
printf '===%s::%s===\n' "$kind" "$sub"
cat "$manifest"
printf '\n=== EOM ===\n'
}
scan_firstparty() {
local dir="$1"; [[ -d "$dir" ]] || return 0
while IFS= read -r manifest; do emit_manifest firstparty "$manifest"; done < <(find "$dir" -mindepth 2 -maxdepth 3 -type f \( -name manifest.json -o -name '*.manifest.json' \) | sort)
}
scan_thirdparty() {
local dir="$1"; [[ -d "$dir" ]] || return 0
for sub in "$dir"/*/; do [[ -f "$sub/manifest.json" ]] || continue; emit_manifest thirdparty "$sub/manifest.json"; done
}
scan_firstparty "$1"
scan_thirdparty "$2"
```
**2. Update `PluginRegistry.qml` `rescan()`:**
```qml
function rescan() {
if (scanning) return
scanning = true
var scriptPath = "/usr/share/omarchy/shell/services/scan-plugins.sh"
scanProcess.command = ["bash", scriptPath, registry.firstPartyDir, registry.pluginsDir]
scanProcess.running = true
}
```
### Workaround (User-level)
```bash
omarchy hook install startup 'sleep 3 && omarchy restart shell'
```
(Sometimes works if user plugin dir exists at startup)
### Related Files
- `/usr/share/omarchy/shell/services/PluginRegistry.qml` (lines ~715-730)
- `/usr/share/omarchy/shell/shell.qml` (lines ~1440-1500, `syncPluginWidgets`, `onScanFinished`)
- `/usr/share/omarchy/shell/plugins/panels/bluetooth/manifest.json`
- `/usr/share/omarchy/shell/plugins/panels/bluetooth/Panel.qml`
---
**This is a critical bug affecting all first-party bar widgets on fresh installs. The Bluetooth backend works; only the widget registration pipeline is broken.**
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 02:28 UTC