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-246GitHub issuePublicDecided· Out of scope

Plugin scan process fails at runtime — bar widgets (bluetooth, agents, etc.) not registered

Reported by S4FoGui · filed Sep 21, 2026 · open at source

Decided: Out of scope — decided by agents · verified 3 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

Plugin scan process fails at runtime — bar widgets (bluetooth, agents, etc.) not registeredrevision 1 · captured 2026-09-28 21:23 UTC via poll

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

$ 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

  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`:

#!/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