Commit Graph
5003 Commits
Author SHA1 Message Date
Ryan Hughes f852edfbd6 Split user-level setup into bin/omarchy-setup-user
User-level files (~/.config, ~/.local/share, ~/.agents, etc.) shouldn't
be written by install.sh — it runs as root or with system-level sudo,
and in offline (ISO chroot) mode the user doesn't exist yet. Moved into
a per-user idempotent command, called from omarchy-first-run.

Moved into bin/omarchy-setup-user (deleted from install/config/):
- omarchy-ai-skill.sh    AI skill symlinks
- omarchy-toggles.sh     hypr toggle flags
- nautilus-python.sh     nautilus extensions
- branding.sh            ~/.config/omarchy/branding/{about,screensaver}.txt
- user-dirs.sh           xdg-user-dirs-update + gtk bookmarks
- detect-keyboard-layout.sh  layout/variant sed into ~/.config/hypr/input.lua
- toggles.sh             ~/.local/state/omarchy/toggles mkdir
- mimetypes.sh           omarchy-refresh-applications + xdg-mime/xdg-settings

Kept in install/config/ (rely on OMARCHY_USER_NAME / OMARCHY_USER_EMAIL
that only exist during install):
- git.sh        git config --global user.{name,email}
- xcompose.sh   ~/.XCompose with name/email substituted

omarchy-setup-user:
- Refuses to run as root
- Idempotent via ~/.local/state/omarchy/setup-user.done marker
- --force escape hatch for re-running after dev-link or upstream changes
- Defaults OMARCHY_PATH to /usr/share/omarchy so it works outside install

bin/omarchy-first-run now invokes omarchy-setup-user unconditionally
(it self-gates), so first user login picks up the user setup.

install/config/all.sh: dropped the eight deleted entries.

All three packages (omarchy, omarchy-settings, omarchy-installer) still
build clean.
2026-06-04 18:34:35 -04:00
Ryan Hughes c26bce6235 Rewrite boot.sh as a thin bootstrap for the package install flow
Old boot.sh cloned the repo to ~/.local/share/omarchy and sourced the
checkout's install.sh. The package refactor moves all of that into the
omarchy-installer package, so boot.sh's job shrinks to:

  1. Configure /etc/pacman.d/omarchy.conf for the right channel
     (stable, edge for OMARCHY_REF=dev, rc for OMARCHY_REF=rc).
     Include it from /etc/pacman.conf if not already.
  2. pacman -Sy && pacman -S --needed omarchy-installer (depends pull in
     omarchy, omarchy-settings, omarchy-limine).
  3. exec omarchy-install (shipped by omarchy-installer at /usr/bin/).

The OMARCHY_REPO and clone logic are gone. The install.sh on disk
under /usr/share/omarchy is now the source of truth, and is invoked via
omarchy-install with OMARCHY_INSTALL_MODE=online (default).

OMARCHY_REF=dev/rc still maps to the right pacman channel for testing
pre-release builds.
2026-06-04 18:34:35 -04:00
Ryan Hughes 26b9ce5f96 Add bin/omarchy-install wrapper (shipped via omarchy-installer)
Brings back the omarchy-install command as a 5-line shell wrapper that
just exec's /usr/share/omarchy/install.sh. Not the 258-line Python
refactor-poc version — that one stays dropped.

The omarchy package keeps excluding bin/omarchy-install exactly so it
doesn't conflict with the omarchy-installer package's copy at /usr/bin.
All 25+ user-facing omarchy-install-* commands (gaming, browser, etc.)
still ship via omarchy.
2026-06-04 18:34:35 -04:00
Ryan Hughes 7fffc5f3c4 Simplify OMARCHY_INSTALL_MODE to online/offline only
Drop online-git: the new world has a single package-backed install path
that's either online (pacman pulls from omacom-pkgs.org) or offline (ISO
chroot pulls from the bundled mirror). The git-clone-and-run-installer
path is gone — boot.sh becomes a thin bootstrap that installs the
omarchy-installer package and invokes its installer.

- install/helpers/mode.sh: two modes, validation message updated. Default
  fallback is 'online' (the boot.sh path); OMARCHY_CHROOT_INSTALL=1 still
  shims to offline, OMARCHY_ONLINE_INSTALL=true still shims to online.
- install/preflight/all.sh: first-run-mode + disable-mkinitcpio gated on
  offline (offline is the from-scratch chroot path; online runs on an
  existing system).
- install/preflight/pacman.sh: DELETED. boot.sh now handles repo config
  before install.sh runs.
- install/packaging/all.sh: drop base.sh entirely. Both modes have
  base packages installed via omarchy-installer's depends before
  install.sh runs. base.sh remains on disk in case the ISO mirror build
  flow wants to invoke it directly.
- install/helpers/chroot.sh, errors.sh, post-install/finished.sh,
  config/mise-work.sh: rename mode checks to use online/offline.
2026-06-04 18:34:35 -04:00
Ryan Hughes 81e81fe0c8 Address momus review of OMARCHY_INSTALL_MODE work
- install.sh: use realpath to follow symlinks when deriving OMARCHY_PATH
  from script location. Logical pwd left dev-link symlink chains pointing
  at the wrong dir; realpath resolves to the underlying checkout.
- install/helpers/mode.sh: validate explicit OMARCHY_INSTALL_MODE values
  and exit on typos. Also export_legacy_mode_flags now UNSETS the
  contradictory legacy flag for each mode so unmigrated callers can't
  see both OMARCHY_CHROOT_INSTALL=1 and OMARCHY_ONLINE_INSTALL=true.
- install/helpers/errors.sh: retry uses "$OMARCHY_PATH/install.sh"
  and preserves OMARCHY_INSTALL_MODE explicitly; the previous hardcoded
  ~/.local/share/omarchy/install.sh broke package-mode retries.
- bin/omarchy-install-mode: soften the summary; the helper only knows
  the current env, not any persisted post-install state.
2026-06-04 18:34:35 -04:00
Ryan Hughes 6f74091fb6 Make install.sh mode-aware with OMARCHY_INSTALL_MODE
Three modes the installer now branches on:

  iso-chroot      Running inside the new system's chroot from the ISO build.
                  pacman is configured by archinstall; systemd isn't running,
                  so service enables skip --now.
  online-package  Running on an existing Arch where the omarchy-* packages
                  are already installed. Skip base.sh and the bootstrap
                  preflight steps; only the per-host runtime ops in
                  config/login/post-install need to run.
  online-git      boot.sh path: clone into $HOME/.local/share/omarchy and
                  bootstrap everything from scratch.

install.sh derives OMARCHY_PATH from its own location, so the same script
works whether it's at /usr/share/omarchy/install.sh (package mode) or
$HOME/.local/share/omarchy/install.sh (git mode). install_mode_is helper
replaces direct ${OMARCHY_CHROOT_INSTALL:-} / ${OMARCHY_ONLINE_INSTALL:-}
checks in chroot.sh, finished.sh, errors.sh, mise-work.sh, preflight/pacman.sh.

Legacy vars still work through export_legacy_mode_flags, which sets
OMARCHY_CHROOT_INSTALL=1 / OMARCHY_ONLINE_INSTALL=true based on the
canonical mode for any caller that hasn't been updated.

bin/omarchy-install-mode prints the current mode for scripts/users that
need to introspect.

Smoke-tested all four entry paths (explicit mode, both legacy shims,
auto-detection from OMARCHY_PATH); each resolves correctly and the
legacy flags are exported in matching modes.
2026-06-04 18:34:35 -04:00
Ryan Hughes 6e0079a66d omarchy-dev-link/unlink: strip prior dev-link bin/ from PATH
Sequential 'dev-link A' then 'dev-link B' previously left A/bin in
PATH because the prepend didn't strip the old one. unlink had the
same issue (it was trying to strip $(dirname $0), which only worked
if you invoked unlink via an absolute path that happened to match
the dev-link bin).

Both now read the previous OMARCHY_PATH from /etc/omarchy.conf before
overwriting/deleting it, and strip that path's bin/ from PATH before
prepending the new one (or nothing, for unlink).
2026-06-04 18:34:35 -04:00
Ryan Hughes b887d18b84 Trim over-commented Chunk 3+/4 work
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.
2026-06-04 18:34:35 -04:00
Ryan Hughes ea54e25bba Tighten omarchy-tzupdate sudoers to set-timezone subcommand only
Mirrors the upstream tightening in install/config/timezones.sh (which
this etc-overrides file replaced): scope the wheel passwordless rule
to 'timedatectl set-timezone *' instead of the whole timedatectl, so
the rule can't be used to flip other system clock settings.

Adopted while rebasing onto current origin/omarchy-shell.
2026-06-04 18:34:35 -04:00
Ryan Hughes 9e1ed8f85c omarchy-dev-pkg-test: install with pacman -U --overwrite=*; add plymouth to transition overwrites
Two related fixes for installing package builds onto a system that has
the legacy script-installed Omarchy files already in place:

bin/omarchy-dev-pkg-test: split makepkg -s (build) from sudo pacman -U
(install) so we can pass --overwrite='*' to pacman. makepkg -i forwards
a fixed flag set to pacman and doesn't expose --overwrite, so dev pkg
tests on an existing script-install fail on every conflicting file
(plymouth themes, /etc drop-ins, sudoers). --overwrite='*' is correct
for the dev use case: the build IS the new authoritative state.

bin/omarchy-update-system-pkgs: add /usr/share/plymouth/themes/omarchy/*
to the transition --overwrite list. The old install/login/plymouth.sh
cp -r'd the theme files into that directory, so existing installs
conflict on the omarchy-settings package's plymouth payload.
2026-06-04 18:34:35 -04:00
Ryan Hughes ac452dd311 Drop the shell-expansion guard from omarchy-dev-link's conf
The previous format wrote 'export OMARCHY_PATH="${OMARCHY_PATH:-<path>}"'
to /etc/omarchy.conf, intended so install.sh's script-mode OMARCHY_PATH
could win over the dev-link value. But install.sh doesn't source
/etc/omarchy.conf (only profile.d/uwsm/bash do, all post-install), so the
guard was protecting a non-scenario.

It also caused a real bug: paths.lua parses /etc/omarchy.conf as text
and returned the literal '${OMARCHY_PATH:-<path>}' string as the
omarchy_path, breaking dev-link in Hyprland.

Switch to plain 'export OMARCHY_PATH="<path>"'. dev-link is the only
writer, and when it's active, its value should win unconditionally.
2026-06-04 18:34:35 -04:00
Ryan Hughes 4f031e10c8 Propagate OMARCHY_PATH and PATH to Hyprland-spawned processes; dev-link-aware paths.lua
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.
2026-06-04 18:34:35 -04:00
Ryan Hughes f4e68d5bb2 Refuse omarchy-dev-{link,unlink} when invoked under sudo
When the script is run under outer sudo, the environment loses
HYPRLAND_INSTANCE_SIGNATURE, XDG_RUNTIME_DIR, and DBUS_SESSION_BUS_ADDRESS,
so the 'hyprctl version' check silently fails and the live-session
refresh (setenv / import-environment / restart shell / hyprctl reload)
gets skipped. The user is left with /etc/omarchy.conf written but no
session updates — confusing because the env in the current shell still
shows the old value.

Reject EUID=0 invocations with a clear message pointing at the right
pattern: invoke as your user, the script prompts for sudo only when it
needs to write /etc/omarchy.conf.
2026-06-04 18:34:35 -04:00
Ryan Hughes a2feffa803 Add omarchy-dev-{link,unlink,status,pkg-test} commands
The four dev-tools commands that complete the developer-ergonomics
story for the package refactor:

- omarchy-dev-link <path>: writes /etc/omarchy.conf so OMARCHY_PATH
  resolves to <path> in all new shells, the Hyprland session env, and
  systemd --user. Updates the live session via hyprctl setenv +
  systemctl --user import-environment, restarts omarchy-shell, and
  reloads Hyprland so the changes are visible immediately. Affects
  every tree resolved via $OMARCHY_PATH: bin/, default/, shell/,
  themes/, applications/, config/.

- omarchy-dev-unlink: removes /etc/omarchy.conf and reverses the live
  session updates back to /usr/share/omarchy.

- omarchy-dev-status: reports current dev-link state (configured path,
  current shell, hyprland session env).

- omarchy-dev-pkg-test [pkg] [checkout]: builds and installs a package
  from the checkout via OMARCHY_SRC + makepkg -si --skipchecksums.
  Used for changes that land at fixed system paths (/etc/, /usr/lib/,
  udev rule bodies, plymouth themes, /etc/skel) that dev-link can't
  shadow. The built package's pkgver is tagged 'dev.<short-sha>[.dirty]'
  so 'pacman -Q' makes its source obvious. Defaults: package
  omarchy-settings, checkout ~/Work/omarchy/omarchy-installer,
  PKGBUILDs read from ~/Work/omarchy/omarchy-pkgs/pkgbuilds/.

All four ship via omarchy-dev-tools (existing PKGBUILD wildcard).
Verified package build picks them up at /usr/bin/omarchy-dev-*.
2026-06-04 18:34:35 -04:00
Ryan Hughes dfc8065915 Clear cached omarchy Lua modules on hyprctl reload
Lua's require() caches modules in package.loaded; without explicit
invalidation, changes to default/hypr/*.lua or ~/.config/hypr/*.lua
won't take effect after hyprctl reload even though hyprland.lua itself
re-runs.

The clear runs unconditionally — benefits both dev-link workflows
(checkout files re-evaluate after every reload) and normal users who
edit their own ~/.config/hypr/*.lua and run omarchy-restart-hyprctl.
Cost is negligible: package.loaded has a handful of entries.

Pattern matches the require_all.lua reload option (which sets
package.loaded[module] = nil before require()), but applied broadly to
the omarchy module namespace at the entry point so individual modules
don't need to opt in.
2026-06-04 18:34:35 -04:00
Ryan Hughes 7e7a665663 Switch dev-link mechanism from shadow-dir to /etc/omarchy.conf
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.
2026-06-04 18:34:35 -04:00
Ryan Hughes 0777b20967 Make profile.d prefer /usr/share/omarchy-dev when present
Sets up the shadow-dir pattern that omarchy-dev-link will use: when
/usr/share/omarchy-dev exists (as a symlink to a local checkout),
$OMARCHY_PATH resolves there instead of /usr/share/omarchy. The PATH
prepend then makes the checkout's bin/ override the package's
/usr/bin copies.

This covers every hot-edit surface that resolves via $OMARCHY_PATH:
bin/, default/, shell/, and themes/. Things that don't go through
$OMARCHY_PATH (udev rules, systemd drop-ins, /etc-installed configs,
plymouth themes, /etc/skel seeds) remain unaffected by dev-link and
require omarchy-dev-pkg-test to verify changes — which is also what
you'd want before shipping any of those anyway.
2026-06-04 18:34:35 -04:00
Ryan Hughes a4c4e5964f Clarify why profile.d/omarchy.sh prepends $OMARCHY_PATH/bin
The previous comment said 'mainly relevant for the script-install path',
but install.sh and default/bash/envs already prepend it there. The real
reason is dev-link: when /usr/share/omarchy is a symlink to a local
checkout, this prepend lets the checkout's bin/ override the /usr/bin/
copies installed by the package.
2026-06-04 18:34:35 -04:00
Ryan Hughes 0ebbe34760 Add chrootable_systemctl_enable_only for services we shouldn't start during install
The previous centralization into enable-services.sh accidentally changed
semantics for three services: docker.socket, iwd.service, and
power-profiles-daemon.service used to be enabled with bare
'sudo systemctl enable' (no --now); chrootable_systemctl_enable promoted
them to 'enable --now' outside chroot.

For iwd this is the riskiest: it's typically what's keeping the installer
online, so starting it mid-install is at best a no-op and at worst can
disrupt the active network connection. For docker.socket and
power-profiles-daemon the change is cosmetic (the socket is already
inactive, the daemon does no harm to start) but the original intent was
deferral to first boot.

New helper in install/helpers/chroot.sh:

  chrootable_systemctl_enable_only <unit>  # plain enable, no --now

enable-services.sh uses it for the three services that were previously
bare-enabled. The other five (bluetooth, cups, cups-browsed,
avahi-daemon, linux-modules-cleanup) keep the --now behavior they had
under chrootable_systemctl_enable.
2026-06-04 18:34:35 -04:00
Ryan Hughes 0e91948b8f Stop runtime defaults from clobbering OMARCHY_PATH
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.
2026-06-04 18:34:35 -04:00
Ryan Hughes f02f4a25b3 Ship /etc/profile.d/omarchy.sh defaulting OMARCHY_PATH
For shells outside the install flow (login shells, cron jobs, dev work)
the install.sh-set OMARCHY_PATH isn't in scope. Without a system-wide
default, omarchy-* commands shipped at /usr/bin can't find runtime data
under /usr/share/omarchy/.

profile.d sets OMARCHY_PATH=/usr/share/omarchy if not already set, so
install.sh's override (to $HOME/.local/share/omarchy during script-install)
still wins. The omarchy-dev-link workflow manages a symlink at
/usr/share/omarchy that points at a local checkout when active.

Also prepends $OMARCHY_PATH/bin to PATH if the directory exists (mainly
matters for script-install mode; /usr/bin is on PATH for package mode).
2026-06-04 18:34:04 -04:00
Ryan Hughes 25bd9aec9e Normalize remaining ~/.local/share/omarchy refs in bin/
Missed in the previous pass:
- bin/omarchy-launch-screensaver: alacritty/ghostty config paths
- bin/omarchy-refresh-applications: source paths for icons and .desktop
- bin/omarchy-refresh-config: docstring/comment references

Still NOT touched (intentional):
- bin/omarchy-reinstall-git: stages '~/.local/share/omarchy-{old,new}' for
  the script-mode upgrade dance; needs redesign for package mode.
- bin/omarchy-dev-add-migration: uses 'cd ~/.local/share/omarchy' to read
  a git log; only meaningful in dev mode.
- bin/omarchy-install-browser:69: writes a string into a chromium config file.
- install/helpers/errors.sh:125: boot.sh relaunch (separate redesign).
2026-06-04 18:34:04 -04:00
Ryan Hughes 510636b8c9 Normalize hard-coded ~/.local/share/omarchy refs to $OMARCHY_PATH
The package-installed paths live at /usr/share/omarchy; the script-install
paths live at ~/.local/share/omarchy. $OMARCHY_PATH is set by install.sh
during the install flow and by /etc/profile.d/omarchy.sh in package mode.
Scripts that hard-code the script-install path don't honour that and will
misbehave once shipped to /usr/bin.

16 files migrated via sed s|~/\.local/share/omarchy|$OMARCHY_PATH|g
and s|$HOME/\.local/share/omarchy|$OMARCHY_PATH|g:

bin/:
- omarchy-plymouth-{preview,reset,set}
- omarchy-refresh-{limine,plymouth}
- omarchy-reinstall-configs
- omarchy-show-logo
- omarchy-games-retro-install
- omarchy-install-gaming-battlenet

install/:
- config/branding.sh
- packaging/{fonts,icons}.sh
- post-install/{finished,pacman}.sh
- preflight/{migrations,pacman}.sh

Deliberately NOT migrated:
- bin/omarchy-dev-add-migration: uses 'cd ~/.local/share/omarchy' to
  resolve a git repo for 'git log'. The packaged binary doesn't have a
  git repo to read; this command only makes sense in dev mode where
  the home path is the right one.
- bin/omarchy-install-browser:69: writes a string into a chromium
  config file that chromium itself interprets; not a bash-resolved path.
- install/helpers/errors.sh:125: the boot.sh-style relaunch behaviour
  needs a separate redesign.
2026-06-04 18:34:04 -04:00
Ryan Hughes 12826d4076 Centralize service enables into install/config/enable-services.sh
The previous setup scattered systemctl enables across docker.sh,
printer.sh, bluetooth.sh, network.sh, powerprofilesctl-rules.sh, and
kernel-modules-hook.sh. Some used chrootable_systemctl_enable; others
used bare 'sudo systemctl enable'. Centralizing makes the install-time
service surface auditable in one place and consistent in chroot/non-chroot
behavior.

install/config/enable-services.sh enables:
- bluetooth.service
- cups.service, cups-browsed.service, avahi-daemon.service
- docker.socket
- iwd.service
- linux-modules-cleanup.service
- power-profiles-daemon.service

Each via chrootable_systemctl_enable, which uses 'enable --now' on a live
system and bare 'enable' in chroot (set OMARCHY_CHROOT_INSTALL=1).

Stays in original script (deliberately):
- sddm.sh: bare 'systemctl enable sddm.service' (no --now during install
  would log the user out; lives in install/login/)
- limine-snapper.sh: limine-snapper-sync (bootloader-specific path)
- first-run/firewall.sh: ufw (deferred to first-run for UX)
- hardware/{t2,intel/lpmd,intel/thermald,apple/fix-suspend-nvme}: gated
  on hardware detection

Side cleanups:
- install/config/kernel-modules-hook.sh: DELETED (sole line was the enable
  for linux-modules-cleanup, now in enable-services.sh).
- install/config/hardware/printer.sh: DELETED (sole purpose was the
  three cups/avahi enables; nothing else to do).
- install/config/hardware/network.sh: keep the systemd-networkd-wait-online
  disable+mask; drop the iwd enable.
- install/config/hardware/bluetooth.sh: keep the AutoEnable=false sed and
  the wireplumber/bt-agent user-session setup; drop the system enable.
- install/config/docker.sh: drop the docker.socket enable.
- install/config/powerprofilesctl-rules.sh: drop the
  power-profiles-daemon enable.
- install/config/all.sh: register enable-services.sh; remove the two
  deleted entries.
2026-06-04 18:34:04 -04:00
Ryan Hughes 080c8ba38c omarchy-wifi-powersave: nullglob; plocate drop-in daemon-reload; idempotent legacy cleanup
- bin/omarchy-wifi-powersave: shopt -s nullglob. Previously, machines
  with no wireless interfaces ran the loop once with the literal glob
  ('iface=*'), failed iw, and exited 237. With the new always-installed
  udev rule that invokes this on every AC transition, the failure
  would surface as failed transient omarchy-wifi-powersave-* units on
  desktops. Now it cleanly no-ops.
- migrations/1779307845.sh: add 'systemctl daemon-reload' so the
  plocate-updatedb.service.d/ac-only.conf drop-in is picked up on
  upgrade. Arch's systemd pacman hook only triggers on
  /usr/lib/systemd/system/*, not /etc/systemd/system/*.
- install/config/powerprofilesctl-rules.sh and wifi-powersave-rules.sh:
  rm -f the pre-rename legacy paths before udevadm reload, so the
  cleanup is idempotent outside the one-shot migration (matters for
  re-install/downgrade testing).
2026-06-04 18:34:04 -04:00
Ryan Hughes dcac0ed953 Convert plocate-ac-only, power-profile, wifi-powersave, unmount-fuse to package files
Four scripts that wrote static /etc or /usr files become package-shipped
files. The other config-script audit candidates (omarchy-ai-skill,
nautilus-python, omarchy-toggles, input-group) correctly stay scripts —
they're user-level operations, not /etc writes.

New package-owned files (omarchy-installer/etc/, shipped by
omarchy-settings):
- etc/systemd/system/plocate-updatedb.service.d/ac-only.conf
- etc/udev/rules.d/99-omarchy-power-profile.rules
- etc/udev/rules.d/99-omarchy-wifi-powersave.rules

The two udev rule files are renamed for namespacing (99-power-profile
-> 99-omarchy-power-profile; 99-wifi-powersave -> 99-omarchy-wifi-powersave)
and rewritten to invoke /usr/bin/omarchy-powerprofiles-set and
/usr/bin/omarchy-wifi-powersave instead of $HOME/.local/share/omarchy/bin/...
(both binaries ship in the omarchy package at /usr/bin/).

The battery-present gate from the original scripts is dropped — the rules
trigger on power_supply udev events, which are benign on desktops without
batteries. (The runtime commands no-op on AC-only systems.)

Script changes:
- install/config/plocate-ac-only.sh: DELETED (file ships, daemon-reload
  happens via pacman hook).
- install/config/unmount-fuse.sh: DELETED (file ships at
  /usr/lib/systemd/system-sleep/unmount-fuse via omarchy-settings).
- install/config/powerprofilesctl-rules.sh: SHRINK to runtime ops
  (enable power-profiles-daemon, udevadm reload+trigger).
- install/config/wifi-powersave-rules.sh: SHRINK to udevadm reload+trigger.
- install/config/all.sh: drop the two deleted entries.

bin/omarchy-update-system-pkgs: add --overwrite for plocate-updatedb
drop-in and unmount-fuse paths (the udev rule renames need no overwrite
since the new paths are virgin).

migrations/1779307845.sh: remove the legacy 99-power-profile.rules and
99-wifi-powersave.rules paths on existing installs, then reload udev.
2026-06-04 18:34:04 -04:00
Ryan Hughes 5683750b29 Add pacman --overwrite for transition paths; fix mimeapps/HEY and PAM idempotency
Four corrections to the omarchy-settings transition:

- bin/omarchy-update-system-pkgs: pass --overwrite for the 13 paths
  omarchy-settings now owns. Existing Omarchy installs would otherwise
  fail pacman conflict checks on the upgrade that ships the package
  (the files exist as unowned filesystem entries from the previous
  install scripts). The flags are no-ops once the transition release
  is everyone's baseline; remove then.
- config/mimeapps.list: drop the HEY.desktop mailto mapping. HEY.desktop
  is generated by install/packaging/webapps.sh at install time, not
  shipped under applications/, so it isn't valid for a fresh /etc/skel
  user before the installer runs.
- install/config/mimetypes.sh: add 'xdg-mime default HEY.desktop
  x-scheme-handler/mailto' as a runtime op since the mapping no longer
  lives in mimeapps.list.
- install/config/increase-lockout-limit.sh: delete existing
  pam_faillock.so authsucc lines before re-adding, so re-running the
  installer doesn't duplicate the authsucc entry in
  /etc/pam.d/sddm-autologin.
2026-06-04 18:34:04 -04:00
Ryan Hughes 3636f57f0c Migrate: clean up legacy /etc paths from prior installs
Existing users upgrading from script-installed Omarchy still have files
the install scripts wrote at the OLD paths. The new package can't own
those old paths (they were either renamed or replaced by drop-ins), so
this migration tidies them up:

- /etc/sysctl.d/99-sysctl.conf: strip the appended net.ipv4.tcp_mtu_probing
  line (new file is /etc/sysctl.d/99-omarchy-sysctl.conf)
- /etc/modprobe.d/disable-usb-autosuspend.conf: removed
  (new file is /etc/modprobe.d/omarchy-usb-autosuspend.conf)
- /etc/sudoers.d/{passwd-tries,asdcontrol}: removed
  (new files are /etc/sudoers.d/omarchy-{passwd-tries,asdcontrol})
- /etc/systemd/system/user@.service.d/faster-shutdown.conf: removed
  (new file is 10-faster-shutdown.conf)
- /etc/systemd/logind.conf HandlePowerKey=ignore line: reset to its
  commented default so the logind.conf.d/ drop-in is the only source

After cleanup, systemctl daemon-reload + sysctl --system to pick up the
new state immediately.
2026-06-04 18:34:04 -04:00
Ryan Hughes 89242fafc6 Ship mimeapps.list via /etc/skel; shrink mimetypes.sh
config/mimeapps.list ships at /etc/skel/.config/mimeapps.list (via
omarchy-settings's existing config/** -> /etc/skel/.config copy).
New users get the full Omarchy MIME defaults on first login without
running install scripts.

install/config/mimetypes.sh shrinks to two runtime ops that a static
file can't replace:
- omarchy-refresh-applications: copies .desktop entries and icons into
  the user home and refreshes the desktop database
- xdg-settings set default-web-browser chromium.desktop: sets the
  system-default browser; omarchy-install-browser overrides this if
  the user later picks a different browser.
2026-06-04 18:34:04 -04:00
Ryan Hughes 993e6a0812 Shrink printer.sh to service enables only
The three /etc writes (resolved.conf.d drop-in, nsswitch.conf override,
cups-browsed.conf override) now ship via omarchy-settings. The service
enables stay scripted because they need chrootable_systemctl_enable to
work both inside the ISO chroot and on a live system.
2026-06-04 18:34:04 -04:00
Ryan Hughes 26bcbb7dd8 Shrink fast-shutdown, gpg, increase-file-watchers, increase-lockout-limit to runtime-only ops
Each script's static-file write moves to omarchy-settings. The scripts
keep only the runtime side: reload systemd, restart dirmngr, sysctl --system,
or (for lockout-limit) the PAM seds that have to stay scripted because
/etc/pam.d/system-auth and /etc/pam.d/sddm-autologin are upstream-owned and
need targeted line edits rather than a full-file override.

faillock.conf's deny=10 (formerly inside increase-sudo-tries.sh sed) now
rides through the etc-overrides dance in omarchy-settings.
2026-06-04 18:34:04 -04:00
Ryan Hughes df1ea87331 Shrink docker.sh to runtime-only ops
The three Docker config files (etc/docker/daemon.json,
etc/systemd/system/docker.service.d/no-block-boot.conf,
etc/systemd/resolved.conf.d/20-docker-dns.conf) now ship via the
omarchy-settings package. The script keeps only the actions a static
file can't do:

- restart systemd-resolved so the new drop-in takes effect
- usermod -aG docker $USER (user-specific, can't be packaged)
- systemctl enable docker.socket and daemon-reload
2026-06-04 18:34:04 -04:00
Ryan Hughes 2b749124ef Delete install scripts whose job is now done by package files
Each of these scripts only wrote a single /etc file (or copied
config/bashrc into the user home). The corresponding files now ship
from the omarchy-settings package — either directly into /etc (drop-ins
the package fully owns) or via the /usr/share/omarchy/etc-overrides
post_install dance (for upstream-owned paths).

Deleted:
- install/config/timezones.sh          -> etc/sudoers.d/omarchy-tzupdate
- install/config/sudoless-asdcontrol.sh -> etc/sudoers.d/omarchy-asdcontrol
                                          ($USER rewritten to %wheel)
- install/config/increase-sudo-tries.sh -> etc/sudoers.d/omarchy-passwd-tries
                                          (faillock.conf side now in etc-overrides)
- install/config/hardware/ignore-power-button.sh
                                        -> etc/systemd/logind.conf.d/10-ignore-power-button.conf
                                          (replaces sed-edit of logind.conf)
- install/config/hardware/usb-autosuspend.sh
                                        -> etc/modprobe.d/omarchy-usb-autosuspend.conf
- install/config/ssh-flakiness.sh       -> etc/sysctl.d/99-omarchy-sysctl.conf
- install/config/config.sh              -> /etc/skel seeds ~/.config from config/**;
                                          ~/.bashrc seeded from etc-overrides
- install/login/plymouth.sh             -> theme files already shipped by
                                          omarchy-settings; etc/plymouth/plymouthd.conf
                                          handled via etc-overrides

A separate migration tidies up the old paths on existing installs.
all.sh entries updated to drop these scripts.
2026-06-04 18:34:04 -04:00
Ryan Hughes e6e6328db7 Add etc/ source tree for package-shipped /etc files
This tree is the source for omarchy-settings to install into /etc
(for paths Omarchy fully owns) or stage at /usr/share/omarchy/etc-overrides
(for paths upstream packages own, which the post_install copies into place).

Package-owned drop-ins (no upstream conflict):
- etc/docker/daemon.json
- etc/systemd/system/docker.service.d/no-block-boot.conf
- etc/systemd/resolved.conf.d/20-docker-dns.conf
- etc/systemd/resolved.conf.d/10-disable-multicast.conf
- etc/systemd/system.conf.d/10-faster-shutdown.conf
- etc/systemd/system/user@.service.d/10-faster-shutdown.conf
  (renamed from .../faster-shutdown.conf for consistency)
- etc/systemd/logind.conf.d/10-ignore-power-button.conf
  (replaces the previous in-place sed-edit of logind.conf)
- etc/gnupg/dirmngr.conf
- etc/sysctl.d/99-omarchy-sysctl.conf  (renamed from the 99-sysctl.conf
  appendage; a migration cleans up the old path on existing installs)
- etc/sysctl.d/90-omarchy-file-watchers.conf
- etc/modprobe.d/omarchy-usb-autosuspend.conf
  (renamed from disable-usb-autosuspend.conf)
- etc/sudoers.d/omarchy-asdcontrol
  (renamed from asdcontrol; $USER -> %wheel for packaging)
- etc/sudoers.d/omarchy-tzupdate
- etc/sudoers.d/omarchy-passwd-tries
  (renamed from passwd-tries for namespacing)

Etc-overrides (upstream-owned paths; staged by the PKGBUILD at
/usr/share/omarchy/etc-overrides/ and cp'd in by post_install):
- etc/security/faillock.conf (owned by pam)
- etc/nsswitch.conf (owned by filesystem)
- etc/cups/cups-browsed.conf (owned by cups-browsed)
- etc/plymouth/plymouthd.conf (owned by plymouth)

All sudoers files validate with visudo -cf.

The install scripts that previously wrote these files are updated or
removed in follow-up commits.
2026-06-04 18:34:04 -04:00
Ryan Hughes add570dac2 Fix one-sided menu row borders 2026-06-04 12:11:41 -04:00
David Heinemeier HanssonandClaude Opus 4.8 e5290b0a12 Add yt-dlp "Download Video" Chromium extension
Download the current page's video with yt-dlp via Alt+Shift+D or a click
on the toolbar icon. A native-messaging host runs the download, shows live
progress on the Quickshell OSD, and posts a clickable "Download complete"
toast that opens the file in mpv.

- Extension: pinned key for a stable id, green download-video icon,
  keyboard command + toolbar action (reads the active tab URL).
- Native host (omarchy-chromium-ytdlp-host): verifies the URL with
  yt-dlp --simulate (else "No video found"), streams progress to the OSD
  (time-throttled to ~4/s), saves to ~/Videos, opens mpv on click.
- Installer (omarchy-install-chromium-ytdlp) writes the native-messaging
  manifest into installed Chromium/Chrome/Brave/Edge profiles; wired into
  browser install and chromium refresh, with a migration for existing users.
- omarchy-osd: add -d/--duration so the OSD can persist during a download.
- Add yt-dlp to base packages, load the extension via --load-extension,
  and document the Alt+Shift+D binding.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 11:15:28 +02:00
David Heinemeier Hansson 1d6467c91c Add explicit toggle states 2026-06-04 11:14:04 +02:00
David Heinemeier Hansson c31825dca4 Apparently this needs to be said 2026-06-04 10:16:00 +02:00
David Heinemeier Hansson 4884f8c64a Persist watched clipboard text 2026-06-04 10:09:38 +02:00
David Heinemeier Hansson 79470dde92 Refine shell panel and lock theming 2026-06-03 22:14:48 +02:00
David Heinemeier Hansson 3cdfb52a74 Didn't actually like the stock hyprland active color
Especially not on the notifications or lock screen
2026-06-03 21:05:19 +02:00
David Heinemeier Hansson 7a47604e27 Show which panel is open 2026-06-03 14:48:47 +02:00
David Heinemeier Hansson d35957b23c Better spacing 2026-06-03 13:59:33 +02:00
David Heinemeier Hansson e1099e4413 Match lock border to Hyprland style 2026-06-03 13:10:48 +02:00
David Heinemeier Hansson a8080d4016 All click targets should have click hands 2026-06-03 11:27:09 +02:00
David Heinemeier Hansson 198d01f8bc Reveal all hidden tooling when hovering over the center part of the bar 2026-06-03 08:23:32 +02:00
David Heinemeier Hansson ddc013aea9 More subtle tweaks to the lock screen 2026-06-03 08:22:50 +02:00
David Heinemeier Hansson 807f500888 More finessing of lock screen proportions 2026-06-03 07:56:48 +02:00
Ryan Hughes 0f715dff88 Lock screen improvements 2026-06-02 23:32:53 -04:00
Ryan Hughes e8a8fcf183 Fix theme switcher preload scrim race 2026-06-02 22:38:31 -04:00