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

Bar: add an overflow region so the bar can hold more widgets than fit

Reported by TomFaulkner · filed Sep 14, 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

Bar: add an overflow region so the bar can hold more widgets than fitrevision 1 · captured 2026-09-28 21:23 UTC via poll

The problem

The bar has three regions (left, center, right) and one instance. Once a
session has enough bar widgets, they stop fitting and the regions overlap — on a
laptop at 2048px undocked, with 38 layout entries, the right and center sections
collide and the only fix today is to remove widgets. There is no place to move
them to.

The system tray already solves this shape of problem for itself: omarchy.tray
keeps a pinned set inline and puts the rest in a drawer behind a chevron. Bar
widgets have no equivalent.

Why a plugin can't fix it

I built one to try (io.github.tomfaulkner.tray, a popout grid of tiles) and it
works for most widgets but not all, because of how services are scoped:

  • shell.serviceFor(id) answers only for the calling plugin's own id, and
  • hosted widgets only get a live service when the trusted built-in bar

instantiates them — Bar.qml reaches shell.pluginShellForId(), which is not
on the capability-scoped API a third-party plugin receives, so any other host
falls through to the service-less pluginShellForBarEntry facade.

So a plugin that renders another plugin's widget gets a component that mounts but
cannot reach its own service. In my installed set that is 7 of 31 bar widgets
(hass, omarr, lotus, recall, omarewind, omaconnect, tomato-timer); the other 24
work fine. A third-party tray can never close that gap, because the gap is the
trust boundary. Anything that fixes it has to live in the bar.

Proposal: bar.layout.overflow, a fourth region

{
  "bar": {
    "position": "top",
    "layout": {
      "left": [{ "id": "omarchy.menu" }, { "id": "omarchy.workspaces" }],
      "center": [{ "id": "omarchy.clock" }],
      "right": [{ "id": "omarchy.audio" }, { "id": "omarchy.power" }],
      "overflow": [
        { "id": "hegjon.unifi" },
        { "id": "zeru.portwatch" },
        { "id": "io.github.qadram.nvme-health" }
      ]
    }
  }
}

Entries stay ordinary layout entries — same ids, same inline settings, same
omarchy bar move plumbing with --section overflow — but instead of being laid
out in a row they render inside a drawer anchored to an opener at the inner end
of a section (right by default, configurable). Because the bar is the host,
every widget in the drawer keeps its service: popups, tooltips, drag, and the
updateEntryInline settings round-trip all work as they do today.

Behaviour:

  • Opener appears only when overflow has entries; no entries, no opener, no

change at all for existing configs.
- Click opens the drawer; it joins the existing one-popout-at-a-time coordinator
so it cannot sit open next to another bar popup, and closes on outside click
or Esc.
- Drawer contents reuse the existing ModuleSlot component, so a widget in the
drawer is the same thing the bar would have drawn inline — one instance, no
duplicate IPC handlers.
- One drawer per bar surface, opening on the monitor whose bar was clicked;
keyboard navigable like the other popups.
- Drawer size follows the content, capped to the screen.

Compatibility: purely additive. Configs without the key are untouched, so no
migration. One internal note — BarModel.inlineSettingsDelta hardcodes
["left", "center", "right"], so the region needs adding there or settings edits
to a drawer entry won't reach a live widget (they'd take effect on the next
rebuild instead, which would still be correct, just less immediate).

Non-goals: no change to omarchy.tray or its SNI drawer; no per-monitor
layouts; and drag-reorder between the drawer and the sections can stay out of
the first pass.

Alternatives considered

  • Per-entry `"overflow": true` flag on any layout entry. More flexible, but

the opener's position and the section bookkeeping get murkier, and it makes
"where did my widget go" harder to answer from the config alone.
- Auto-collapse when the bar is full. Nice, but it needs a width model for
every widget and it moves widgets around behind the user's back. Explicit is
better here, and it matches how the tray drawer already works.
- Leave it to plugins. Tried; see above — it cannot host service-backed
widgets, and every plugin author would re-solve this differently.

I'd like to implement this

Happy to write it: BarModel.js (region normalization, inlineSettingsDelta),
Bar.qml (skip overflow entries in the section rows, opener module, drawer built
from ModuleSlot inside a KeyboardPanel/PopupCard, wired into
activePopout), a test/shell.d/bar-overflow-test.sh, plus the bar README
schema and manual/05-the-top-bar.md. Tell me if you'd rather it take a
different shape first — the config surface is the part worth agreeing on before
any code.

For reference, this is what the plugin version looks like in use, which is the
behaviour I'd be proposing for the drawer: popout grid with groups, and a fuzzy
finder over the same tiles.

!Grouped popout

!Finder over the same tiles

Running Omarchy 4.0.3-1.

View raw text
## The problem

The bar has three regions (`left`, `center`, `right`) and one instance. Once a
session has enough bar widgets, they stop fitting and the regions overlap — on a
laptop at 2048px undocked, with 38 layout entries, the right and center sections
collide and the only fix today is to remove widgets. There is no place to move
them to.

The system tray already solves this shape of problem for itself: `omarchy.tray`
keeps a pinned set inline and puts the rest in a drawer behind a chevron. Bar
widgets have no equivalent.

## Why a plugin can't fix it

I built one to try (`io.github.tomfaulkner.tray`, a popout grid of tiles) and it
works for most widgets but not all, because of how services are scoped:

- `shell.serviceFor(id)` answers only for the calling plugin's own id, and
- hosted widgets only get a live service when the **trusted built-in bar**
  instantiates them — `Bar.qml` reaches `shell.pluginShellForId()`, which is not
  on the capability-scoped API a third-party plugin receives, so any other host
  falls through to the service-less `pluginShellForBarEntry` facade.

So a plugin that renders another plugin's widget gets a component that mounts but
cannot reach its own service. In my installed set that is 7 of 31 bar widgets
(hass, omarr, lotus, recall, omarewind, omaconnect, tomato-timer); the other 24
work fine. A third-party tray can never close that gap, because the gap *is* the
trust boundary. Anything that fixes it has to live in the bar.

## Proposal: `bar.layout.overflow`, a fourth region

```json
{
  "bar": {
    "position": "top",
    "layout": {
      "left": [{ "id": "omarchy.menu" }, { "id": "omarchy.workspaces" }],
      "center": [{ "id": "omarchy.clock" }],
      "right": [{ "id": "omarchy.audio" }, { "id": "omarchy.power" }],
      "overflow": [
        { "id": "hegjon.unifi" },
        { "id": "zeru.portwatch" },
        { "id": "io.github.qadram.nvme-health" }
      ]
    }
  }
}
```

Entries stay ordinary layout entries — same ids, same inline settings, same
`omarchy bar move` plumbing with `--section overflow` — but instead of being laid
out in a row they render inside a drawer anchored to an opener at the inner end
of a section (`right` by default, configurable). Because the bar is the host,
every widget in the drawer keeps its service: popups, tooltips, drag, and the
`updateEntryInline` settings round-trip all work as they do today.

Behaviour:

- Opener appears only when `overflow` has entries; no entries, no opener, no
  change at all for existing configs.
- Click opens the drawer; it joins the existing one-popout-at-a-time coordinator
  so it cannot sit open next to another bar popup, and closes on outside click
  or Esc.
- Drawer contents reuse the existing `ModuleSlot` component, so a widget in the
  drawer is the same thing the bar would have drawn inline — one instance, no
  duplicate IPC handlers.
- One drawer per bar surface, opening on the monitor whose bar was clicked;
  keyboard navigable like the other popups.
- Drawer size follows the content, capped to the screen.

Compatibility: purely additive. Configs without the key are untouched, so no
migration. One internal note — `BarModel.inlineSettingsDelta` hardcodes
`["left", "center", "right"]`, so the region needs adding there or settings edits
to a drawer entry won't reach a live widget (they'd take effect on the next
rebuild instead, which would still be correct, just less immediate).

Non-goals: no change to `omarchy.tray` or its SNI drawer; no per-monitor
layouts; and drag-reorder between the drawer and the sections can stay out of
the first pass.

## Alternatives considered

- **Per-entry `"overflow": true` flag** on any layout entry. More flexible, but
  the opener's position and the section bookkeeping get murkier, and it makes
  "where did my widget go" harder to answer from the config alone.
- **Auto-collapse when the bar is full.** Nice, but it needs a width model for
  every widget and it moves widgets around behind the user's back. Explicit is
  better here, and it matches how the tray drawer already works.
- **Leave it to plugins.** Tried; see above — it cannot host service-backed
  widgets, and every plugin author would re-solve this differently.

## I'd like to implement this

Happy to write it: `BarModel.js` (region normalization, `inlineSettingsDelta`),
`Bar.qml` (skip overflow entries in the section rows, opener module, drawer built
from `ModuleSlot` inside a `KeyboardPanel`/`PopupCard`, wired into
`activePopout`), a `test/shell.d/bar-overflow-test.sh`, plus the bar README
schema and `manual/05-the-top-bar.md`. Tell me if you'd rather it take a
different shape first — the config surface is the part worth agreeing on before
any code.

For reference, this is what the plugin version looks like in use, which is the
behaviour I'd be proposing for the drawer: popout grid with groups, and a fuzzy
finder over the same tiles.

![Grouped popout](https://raw.githubusercontent.com/TomFaulkner/omarchy-popout-tray/master/screenshots/grid.png)

![Finder over the same tiles](https://raw.githubusercontent.com/TomFaulkner/omarchy-popout-tray/master/preview.png)

Running Omarchy 4.0.3-1.

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 13:26 UTC