Each `bash -lc` starts a login shell that re-sources the profile
(mise activation, /etc/profile.d) on every invocation — ~16 forks per
call versus ~2 for `bash -c` — which taxes every menu/panel/launcher
action the shell shells out for. The session already exports PATH and
env to the shell, so omarchy commands resolve fine under `bash -c`.
Switch the internal/omarchy-owned spawns (theme+background switches,
brightness, monitor scaling, DNS, lock/fingerprint, keyboard-layout
probe, voxtype status, and the `:`/printf state-file writes) to
`bash -c`. Leave `bash -lc` on the sites that run user-configurable
commands (custom bar-widget exec, menu provider/guard scripts,
launcher scan commands, configurable idle/screensaver command), where
a user's command may rely on their login environment.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The indicators widget broadcast a refresh every 2s, fanning out to four
status subprocesses (nightlight, idle, reminder, screen-recording), and
NightLight/StayAwake each ran an additional 5s poll. On an idle desktop
this was the dominant source of process churn (~33 of ~53 forks/sec in a
VM). The state-changing commands already push `omarchy.indicators
refresh` over IPC, so the polling was redundant.
Drop the 2s broadcast and the two 5s timers; indicators now refresh at
startup and on the IPC push. Also fix three callers that pushed to the
wrong target `Indicators` instead of `omarchy.indicators` (screen
recording, notification silencing, and the omarchy-shell help example) —
those pushes silently failed and only appeared to work because the poll
masked them.
Idle fork rate drops ~53/s to ~20/s.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The `Bar` uses a `Repeater` when building out the models. This has the
effect of marshalling the configuration, and causing JSON arrays to
become sequence wrappers.
A couple of the plugins had been checking for the existence of array
values with `Array.isArray`, which fails for the sequence wrappers,
causing the values to be ignored. This breaks associated functionality
(the "hide" and "pin" actions in the systray had stopped working, as had
exit node selection in Tailscale).
Switching the guards to use `instanceof Array` works correctly for
sequence values (as well as arrays).
Bar-widget panels (audio, bluetooth, network, power, monitor) used to be
toggled via their own per-plugin IpcHandler targets. Quickshell resolves
duplicate targets first-handler-wins, so after a plugin or bar reload the
stale handler of the destroyed widget instance kept claiming the target
and the hotkeys went dead.
The shell root's IpcHandler lives outside the reload cycle, so summon,
hide, and toggle now go through `omarchy-shell shell toggle <plugin>`
and the shell routes to the live widget instance via the bar's slot
registry. Panel plugins that are also panel/overlay/menu kinds keep
using the panel loader path. Failures to find a live widget are logged
so a widget missing from the bar layout stays diagnosable.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Set the default formatAlt to "dd MMMM 'W'ww yyyy" (was "dd MMMM yyyy")
in shell-defaults.json, the bundled settings-panel defaults, and the
form placeholder text — clock's own widget fallback already used this
spec but the shipped config overrode it.
Qt.formatDateTime doesn't recognize `ww` and renders it literally
(`20 May Www 2026`), so add an `isoWeek` helper to clock.qml that
pre-substitutes `ww` with a Qt-quoted literal of the ISO 8601 week
number before handing the format off to Qt. Users get `20 May W21 2026`
without anyone needing to know about the substitution.
Clock and daytime were near-duplicates with different click semantics
(clock toggles between formats on left-click and opens the timezone
selector on right-click; daytime was non-pressable with a hover tooltip).
Standardize on clock, since it's the more capable of the two.
- Delete widgets/daytime.qml and its FirstPartyWidgets entry.
- Migrate shell-defaults.json, shell.qml's builtin fallback, Bar.qml's
fallback bar config, and the settings panel's builtin defaults so the
center anchor and center-section entry both reference "clock".
- Rename the daytimeSettings form to clockSettings and rephrase
"Tooltip format" → "Alternate format (click to toggle)" so the field
label matches clock's actual behavior.
- Update the gallery dropdown options and bar/README docs.
Five sites hardcoded "#cacccc" or "JetBrainsMono Nerd Font" as the
fallback when no bar context was available. Those magic strings are
the *current* palette defaults — they diverge silently when the theme
changes. Bind to the Color / Style singletons so the fallback tracks
whatever the theme says the foreground / monospace family should be.
Color.qml itself keeps the literal "#cacccc" — that's the seed value
the singleton is bootstrapped with before the theme loads.
Six widgets (clock, daytime, keyboardLayout, lockKeys, activeWindow,
media) shipped identical copies of `function setting(name, fallback)`.
Eight widgets reimplemented `readonly property bool vertical`, and
three reimplemented `readonly property int barSize`. Move all three
onto the BarWidget base so widgets read the same wiring everyone else
gets for free.
While in here, drop the dead `setting()` declaration on media.qml — it
was defined but never called.