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>
A previous submap attempt was brittle because the script owned the
keyboard state: if it died between enter and exit, the submap stuck.
This version lets the compositor own both edges. The Lua config binds
plain Return when a layer surface with slurp's "selection" namespace
opens and unbinds it when the last one closes, so the bind exists
exactly while a pick is on screen. slurp dying for any reason (cancel,
crash, pkill, SIGKILL of the picker) fires layer.closed and the bind
evaporates — there is no code path where it leaks.
Return invokes omarchy-capture-region --take-fullscreen, which flags a
marker in XDG_RUNTIME_DIR and dismisses slurp; the picker treats an
empty slurp result with a fresh marker as the focused monitor, reusing
the existing fullscreen path. Since monitor focus follows the cursor,
that is the monitor under the slurp crosshair. The recording flow gets
monitor:NAME from the existing match, so Return during a recording
pick starts a native full-monitor capture.
The signal mode no-ops unless slurp is actually running, and both the
signal protocol and the layer-scoped bind lifecycle are verified live:
bind present only while slurp is open, real picks resolved by the
signal on both the screenshot and recording paths, no leftover binds.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Reorganizes Omarchy 4 around three layers for populating $HOME:
Seed: omarchy-settings ships defaults to /etc/skel; useradd -m
copies them on user creation
Finalize: omarchy-finalize-user (renamed from omarchy-setup-user)
handles only the runtime tweaks /etc/skel can't do — skill
symlinks, xdg-user-dirs, default browser/mailto, vconsole→hypr
keyboard sync, and install/user/all.sh
Resync: omarchy-reinstall-configs is the explicit, destructive
resync of /etc/skel into an existing user's $HOME
Package-owned files move out of config/ into default/, where the
omarchy-settings PKGBUILD installs them to real system paths:
config/environment.d/fcitx.conf -> /usr/lib/environment.d/
config/fontconfig/fonts.conf -> /usr/share/fontconfig/conf.avail/
config/mimeapps.list -> /usr/share/applications/
config/omarchy.ttf -> /usr/share/fonts/omarchy/
config/systemd/user/*.service -> /usr/lib/systemd/user/
config/uwsm/default -> /usr/share/omarchy/default/uwsm/
config/uwsm/env -> /usr/share/uwsm/env.d/10-omarchy
config/xdg-terminals.list -> /usr/share/xdg-terminal-exec/
omarchy-upgrade-to-4 grows a 'retire' action (renamed from 'move' to
clarify nothing is copied — the system path is owned by the new package
once the user's hash-matched ~/.config copy is removed). Mismatched
copies are kept as backups so user overrides survive the upgrade.
Other simplifications:
- Single env bootstrap at default/bash/env-bootstrap sourced by
/etc/profile.d/omarchy.sh, /etc/skel/.bashrc,
/usr/share/uwsm/env.d/10-omarchy, and default/bash/envs. PATH
prepend only in dev-link mode (production uses /usr/bin/omarchy-*).
- omarchy-refresh-config reads from /etc/skel/.config so refresh
means 'snap to skel'.
- omarchy-reinstall-configs collapses to 'cp -af /etc/skel/. ~/'
plus limine/plymouth/nvim refresh.
- omarchy-font-set uses awk against our own 30-omarchy.conf instead
of xmlstarlet; xmlstarlet dropped from omarchy-base.packages.
- Defer user systemd enables (bt-agent, sleep-lock,
recover-internal-monitor) to first-run via
install/user/first-run/enable-user-units.sh; delete
omarchy-user-systemctl-enable and the per-hardware install
scripts that called it.
- Wireplumber bluetooth-a2dp-autoconnect.conf moves to config/ so
/etc/skel ships it; install/user/hardware/bluetooth.sh deleted.
- Default terminal switched to foot.desktop.
- docs/file-layout.md documents the three-layer model and the
build-time repo→path map.
Remove legacy online installer entrypoints, collapse migrations for 4.0, and move setup responsibilities into target-side system, hardware, and user commands.
Evaluate NVIDIA session env vars from default/hypr/nvidia.lua during Hyprland startup instead of appending them to each user's envs.lua during setup. This removes the per-user NVIDIA setup script execution while preserving the GSP/non-GSP detection.
The git-era flow installed Omarchy to ~/.local/share/omarchy. In the
package-based flow it lives at /usr/share/omarchy (or, in dev mode, at
the path /etc/omarchy.conf's OMARCHY_PATH points at). Files that hard-
coded the old path broke on package installs:
- default/bash/rc: sourced ~/.local/share/omarchy/default/bash/*, so a
fresh user's terminal logged ENOENT for every line. Now sources from
$OMARCHY_PATH with /usr/share/omarchy as the safe default if the var
is unset.
- config/systemd/user/omarchy-recover-internal-monitor.service:
ExecStart pointed at %h/.local/share/omarchy/bin/. The script ships
to /usr/bin via the omarchy-installer package; point straight there.
- install/config/xcompose.sh: wrote an XCompose include line pointing
at the user-home path; use /usr/share/omarchy/ directly.
- default/hypr/paths.lua and config/hypr/hyprland.lua: fallback when
OMARCHY_PATH is unset is /usr/share/omarchy, not the home path.
Dev-only scripts (omarchy-dev-add-migration, omarchy-reinstall-git) and
the SKILL.md docs still reference the old path; those are separate
cleanups since they don't affect a fresh install's runtime.
A pass over the install scripts, dev-tools commands, and Hyprland Lua
files that I had stuffed with explain-everything preambles. Most of
those rationales (which files ship where, why hyprctl setenv doesn't
suffice, etc.) belong in commit messages or PR descriptions, not in
code people have to read forever. Kept the few comments that document
genuinely non-obvious behaviour: the keybind-env reason for hl.env in
envs.lua, why the runtime PAM seds stay scripted in
increase-lockout-limit, the chroot/--now distinction in chroot.sh, and
the dev-pkg-test split-install reason.
Two related fixes for omarchy-dev-link to actually affect Hyprland keybinds:
default/hypr/paths.lua: prefer /etc/omarchy.conf over the process env.
hyprctl setenv updates Hyprland's process env, but the user-reported case
shows it doesn't reach bind-exec dispatchers because their env is
captured at config-load time. Reading the dev-link conf directly means
paths.omarchy_path is correct on every hyprctl reload regardless of
whether the launching Hyprland session re-read its env.
default/hypr/envs.lua: explicitly hl.env("OMARCHY_PATH", ...) and
hl.env("PATH", "$OMARCHY_PATH/bin:$PATH") so keybind dispatchers (and
everything else spawned by Hyprland) inherit the dev-link values. PATH
is built with a dedup pass so reloads don't accumulate the bin/ prefix.
Tested locally: paths.lua reads /etc/omarchy.conf correctly; lua syntax
of both files validates with luac -p.
omarchy-dev-link (lands in a follow-up) writes OMARCHY_PATH=<checkout>
to /etc/omarchy.conf. Three boot/session entry points now source it
before falling back to /usr/share/omarchy:
- /etc/profile.d/omarchy.sh (login shells, SSH)
- config/uwsm/env (Hyprland session via UWSM)
- default/bash/envs (non-login interactive bash; duplicated for
SSH and similar)
All three use 'export OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}"'
so /etc/omarchy.conf wins over the default, and install.sh's script-mode
export wins over /etc/omarchy.conf (because both use the :- guard).
Hyprland updates session env on the fly via hyprctl setenv +
systemctl --user import-environment, so omarchy-dev-link can re-trigger
those to make live sessions pick up the new path without restart.
The /etc/profile.d/omarchy.sh default for OMARCHY_PATH was being clobbered
by shipped config files that re-export the variable to the old script-mode
path. In package mode, every login shell, UWSM session, and Hyprland
autostart was effectively reversing the migration. Fix:
- default/bashrc: source from $OMARCHY_PATH/default/bash/rc; default
OMARCHY_PATH to /usr/share/omarchy if not set (so the source line
works in any boot order, including non-login interactive shells).
- default/bash/envs: change 'export OMARCHY_PATH=$HOME/...' to
'export OMARCHY_PATH=${OMARCHY_PATH:-/usr/share/omarchy}' so the
profile.d default and install.sh script-mode override both win.
- config/uwsm/env: same defaulting pattern. UWSM may not source
profile.d, so the inline default still matters.
- default/hypr/autostart.lua: quickshell launched from $OMARCHY_PATH/shell
(not literal $HOME path). The bash that runs hl.exec_cmd sees
OMARCHY_PATH propagated from UWSM env.
- config/chromium-flags.conf: --load-extension hard-codes
/usr/share/omarchy/... because chromium doesn't expand env vars or
'~'. The omarchy-dev-link workflow symlinks /usr/share/omarchy to a
checkout.
- bin/omarchy-install-browser: same chromium-flag path correction for
brave-origin-beta-flags.conf.