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-4947GitHub issuePublicReceived

Cloning a first-party service plugin silently breaks its bar indicator: serviceFor() does not resolve clones

Reported by kstorm12 · filed Sep 7, 2026Closed upstream on 2026-09-20 by bjarneo via an automated message, as a duplicate of #7355 (R-1694). GitHub close reason: completed.

Received and recorded verbatim. Nothing has been checked yet.

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

Cloning a first-party service plugin silently breaks its bar indicator: serviceFor() does not resolve clonesrevision 1 · captured 2026-10-04 12:10 UTC via poll

What happened

Cloning a first-party service plugin permanently breaks the bar indicator that talks to it. The indicator stops responding to clicks and never shows its active state. Nothing is logged: no QML warning, no journal entry, no visible error.

I hit this with omarchy plugin clone omarchy.idle, which killed the Stay Awake toggle.

Cause

plugins/bar/indicators/StayAwake.qml:7 resolves the service by its literal built-in id:

readonly property var idleService: bar?.shell?.firstPartyServiceFor("omarchy.idle")

shell.qml:275 is a raw map lookup:

function serviceFor(pluginId) {
  return _services[String(pluginId)] || null
}

function firstPartyServiceFor(pluginId) {
  return serviceFor(pluginId)
}

PluginRegistry.resolveEnabledId() (services/PluginRegistry.qml:146) exists for exactly this redirect, and its own comment says so:

// Callers keep using the built-in id after cloning; the enabled local
// manifest is the implementation that should receive the call.

It is used at shell.qml:441, 481, 498, 511 and 568, but not by serviceFor().

Cloning a plugin whose kinds include a non-widget kind adds the built-in id to disabledPlugins (PluginRegistry.qml:523), so _services["omarchy.idle"] is gone and the lookup returns null. active is then pinned false and toggle() is a no-op, since both are guarded on the null service.

Cloned bar widgets are unaffected, because the clone rewrites the layout entry in shell.json. Only service clones hit this.

Steps to reproduce

  1. omarchy plugin clone omarchy.idle
  2. omarchy restart shell
  3. Hover the indicator cluster and click the Stay Awake (coffee cup) icon.

Expected: idle inhibition toggles and the icon lights up.
Actual: nothing happens, ever. The journal shows the cloned service running normally (omarchy idle ... service-ready), so the service itself is fine; only the indicator's lookup fails.

The CLI path still works, which makes the split easy to see: omarchy toggle idle writes the state file and the service's watcher picks it up, logging stay-awake: enabled state-file. A working indicator click logs stay-awake: enabled ipc instead. Seeing state-file but never ipc is the signature.

Scope

Four call sites resolve a first-party service by literal id, so the same break is waiting for anyone who clones any of these services:

ConsumerService id
plugins/bar/indicators/StayAwake.qml:7omarchy.idle
plugins/bar/indicators/Dnd.qml:8omarchy.notifications
plugins/bar/indicators/NightLight.qml:7omarchy.nightlight
plugins/panels/audio/Panel.qml:20, plugins/services/media/BarWidget.qml:10omarchy.media

Suggested fix

Route the lookup through the helper that already exists:

function serviceFor(pluginId) {
  var id = pluginRegistry ? pluginRegistry.resolveEnabledId(pluginId) : pluginId
  return _services[String(id)] || null
}

That matches how shell.qml dispatches everywhere else and needs no change in the indicators.

Workaround

Clone omarchy.indicators as well and point the indicator at the clone. Cheap, because Indicators.manifest.json declares clonePaths for ../indicators, so the clone is the one widget plus its six indicator files rather than the whole bar:

readonly property var idleService: bar?.shell?.firstPartyServiceFor("<user>.idle")
  || bar?.shell?.firstPartyServiceFor("omarchy.idle")

System

  • Omarchy 4.0.2-1
  • Quickshell 0.3.1 (Arch)
  • Hyprland 0.56.2
  • AMD Ryzen 7 7735HS / Radeon 680M
  • Linux 7.1.9-arch1-2
View raw text
### What happened

Cloning a first-party **service** plugin permanently breaks the bar indicator that talks to it. The indicator stops responding to clicks and never shows its active state. Nothing is logged: no QML warning, no journal entry, no visible error.

I hit this with `omarchy plugin clone omarchy.idle`, which killed the Stay Awake toggle.

### Cause

`plugins/bar/indicators/StayAwake.qml:7` resolves the service by its literal built-in id:

```qml
readonly property var idleService: bar?.shell?.firstPartyServiceFor("omarchy.idle")
```

`shell.qml:275` is a raw map lookup:

```qml
function serviceFor(pluginId) {
  return _services[String(pluginId)] || null
}

function firstPartyServiceFor(pluginId) {
  return serviceFor(pluginId)
}
```

`PluginRegistry.resolveEnabledId()` (`services/PluginRegistry.qml:146`) exists for exactly this redirect, and its own comment says so:

```qml
// Callers keep using the built-in id after cloning; the enabled local
// manifest is the implementation that should receive the call.
```

It is used at `shell.qml:441`, `481`, `498`, `511` and `568`, but **not** by `serviceFor()`.

Cloning a plugin whose kinds include a non-widget kind adds the built-in id to `disabledPlugins` (`PluginRegistry.qml:523`), so `_services["omarchy.idle"]` is gone and the lookup returns `null`. `active` is then pinned `false` and `toggle()` is a no-op, since both are guarded on the null service.

Cloned *bar widgets* are unaffected, because the clone rewrites the layout entry in `shell.json`. Only service clones hit this.

### Steps to reproduce

1. `omarchy plugin clone omarchy.idle`
2. `omarchy restart shell`
3. Hover the indicator cluster and click the Stay Awake (coffee cup) icon.

Expected: idle inhibition toggles and the icon lights up.
Actual: nothing happens, ever. The journal shows the cloned service running normally (`omarchy idle ... service-ready`), so the service itself is fine; only the indicator's lookup fails.

The CLI path still works, which makes the split easy to see: `omarchy toggle idle` writes the state file and the service's watcher picks it up, logging `stay-awake: enabled state-file`. A working indicator click logs `stay-awake: enabled ipc` instead. Seeing `state-file` but never `ipc` is the signature.

### Scope

Four call sites resolve a first-party service by literal id, so the same break is waiting for anyone who clones any of these services:

| Consumer | Service id |
| --- | --- |
| `plugins/bar/indicators/StayAwake.qml:7` | `omarchy.idle` |
| `plugins/bar/indicators/Dnd.qml:8` | `omarchy.notifications` |
| `plugins/bar/indicators/NightLight.qml:7` | `omarchy.nightlight` |
| `plugins/panels/audio/Panel.qml:20`, `plugins/services/media/BarWidget.qml:10` | `omarchy.media` |

### Suggested fix

Route the lookup through the helper that already exists:

```qml
function serviceFor(pluginId) {
  var id = pluginRegistry ? pluginRegistry.resolveEnabledId(pluginId) : pluginId
  return _services[String(id)] || null
}
```

That matches how `shell.qml` dispatches everywhere else and needs no change in the indicators.

### Workaround

Clone `omarchy.indicators` as well and point the indicator at the clone. Cheap, because `Indicators.manifest.json` declares `clonePaths` for `../indicators`, so the clone is the one widget plus its six indicator files rather than the whole bar:

```qml
readonly property var idleService: bar?.shell?.firstPartyServiceFor("<user>.idle")
  || bar?.shell?.firstPartyServiceFor("omarchy.idle")
```

### System

- Omarchy 4.0.2-1
- Quickshell 0.3.1 (Arch)
- Hyprland 0.56.2
- AMD Ryzen 7 7735HS / Radeon 680M
- Linux 7.1.9-arch1-2

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.