Compare commits

..
115 Commits
Author SHA1 Message Date
Ryan Hughes 17f024d481 Make dev unlink reset Omarchy path defensively 2026-06-07 16:35:54 -04:00
Ryan Hughes 5178405d19 Merge remote-tracking branch 'origin/omarchy-shell' into omarchy-4 2026-06-07 14:56:08 -04:00
Ryan Hughes 132e67bf4c Default pkg-test to dev packages 2026-06-06 20:36:21 -04:00
Ryan Hughes fc6feedae5 Load Omarchy fontconfig after generic aliases 2026-06-06 19:31:51 -04:00
Ryan Hughes d2c1544d78 Fix sleep lock service during Omarchy 4 upgrade 2026-06-06 19:31:51 -04:00
Ryan Hughes 4c17f6a675 Merge remote-tracking branch 'origin/omarchy-shell' into omarchy-4
# Conflicts:
#	bin/omarchy-debug
#	bin/omarchy-upload-log
2026-06-06 13:28:47 -04:00
Ryan Hughes 2c44fdf5f3 Merge remote-tracking branch 'origin/omarchy-shell' into omarchy-4 2026-06-05 18:35:34 -04:00
Ryan Hughes e5516d882d Simplify system update popover 2026-06-04 19:23:54 -04:00
Ryan Hughes 92de15214c Reconcile omarchy-shell rebase 2026-06-04 18:40:57 -04:00
Ryan Hughes cb3fc79385 Add dev package mode to Omarchy 4 upgrade 2026-06-04 18:38:25 -04:00
Ryan Hughes ddd7e058a2 Auto-mount removable drives by default with udiskie 2026-06-04 18:38:25 -04:00
Ryan Hughes 23f8418ed6 Move boot drop-ins into Omarchy repo 2026-06-04 18:38:25 -04:00
Ryan Hughes 20d79fe443 Improve update widget 2026-06-04 18:38:25 -04:00
Ryan Hughes d0cac7346a Finish v4 upgrade cleanup 2026-06-04 18:38:25 -04:00
Ryan Hughes 0804962619 Improve update and migration flow 2026-06-04 18:38:25 -04:00
Ryan Hughes c8ed1e77ae Fix Chromium copy URL extension path on v4 upgrade 2026-06-04 18:38:25 -04:00
Ryan Hughes 3f5b92b413 upgrade-to-4: inject [omarchy-dev] above [omarchy] in pacman.conf
TEMPORARY: while the omarchy-4 stack is being iterated, the production
edge/stable/rc channels at pkgs.omarchy.org/<ring>/x86_64 don't have the
new omarchy and omarchy-settings packages — only omarchy-keyring and
omarchy-nvim are published. The work-in-progress packages live in the
dev repo at share.heyoodle.com/omarchy/dev/<arch> via
omarchy-pkgs/bin/publish-dev-repo.

To stop hand-editing pacman.conf after every run of this script,
configure_pacman_channel() now emits a [omarchy-dev] block right above
[omarchy] with SigLevel = Never and the share.heyoodle URL. Pacman
honors repo declaration order, so dev packages take precedence when
both ring publish them.

The awk also dedupes any pre-existing [omarchy-dev] block (so rerunning
the script doesn't pile up duplicate entries) and falls back to
appending both blocks at the end if no [omarchy] section was present.

Revert this block once the production rings have caught up.
2026-06-04 18:38:25 -04:00
Ryan Hughes 6f73eb5d9d upgrade-to-4: drop omarchy-limine from core_packages install list
omarchy-limine no longer exists as a separate package — it was folded
into omarchy-settings (configs) and omarchy (bootloader stack hard dep).
Listing it in install_omarchy_4_packages's pacman -Syu invocation
produced 'error: target not found: omarchy-limine' on every run.

Also fix the now-stale 'shipped by omarchy-settings / omarchy-limine'
comment in the retire-action header (line 1119) — the files come from
omarchy-settings alone now.

The bootloader stack (limine, limine-mkinitcpio-hook, limine-snapper-sync,
snapper) is hard-depended by the omarchy package, so dropping
omarchy-limine from the explicit list doesn't change what gets installed
on a real upgrade.
2026-06-04 18:38:25 -04:00
Ryan Hughes 4e10d41f0e Start user units immediately in first-run, not just enable
systemctl --user enable only writes the .wants symlinks; the services
don't actually run until next login. Switching to --now enables AND
starts them, so the first session has bt-agent (bluetooth pairing) and
omarchy-sleep-lock active immediately rather than waiting a reboot.

omarchy-recover-internal-monitor is Type=oneshot with a
ConditionPathExists guard, so --now is harmless for it (it'll skip if
the toggle isn't set).
2026-06-04 18:38:25 -04:00
Ryan Hughes aa12358201 Update file layout for the two-package architecture
Reflects the two upstream changes in this work:
- omarchy-dev-tools folds into omarchy (bin/omarchy-dev-* ship with the
  main package).
- omarchy-limine folds into omarchy-settings (limine + snapper configs,
  mkinitcpio hooks, and the default/{limine,snapper}/ trees ship from
  omarchy-settings; the package was always installed in lockstep with
  it in the early bootstrap anyway).

Mental-model section: from four packages to two (omarchy +
omarchy-settings), plus the two unchanged independents (omarchy-keyring,
omarchy-nvim).

Build-time map: drop the omarchy-dev-tools and omarchy-limine columns;
add the new limine source files (omarchy_hooks.conf,
thunderbolt_module.conf, omarchy-defaults.conf, omarchy-uki.conf) under
omarchy-settings.
2026-06-04 18:38:25 -04:00
Ryan Hughes 041f280f68 Document env-bootstrap and first-run in file layout
- Add default/bash/env-bootstrap to the build-time map and a dedicated
  section describing what it sets, who sources it, and the dev-link gate
  on the PATH prepend.
- Drop 'bluetooth' from the install/user/all.sh hardware-quirks list
  (the per-hardware install script is gone now that the wireplumber
  config ships through /etc/skel and bt-agent enables at first-run).
- Add a first-run section listing the post-login steps, including the
  new enable-user-units.sh that defers user systemctl enables.
2026-06-04 18:38:25 -04:00
Ryan Hughes babfafa5e9 Split user defaults into skel seed, finalize, and resync
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.
2026-06-04 18:38:25 -04:00
Ryan Hughes 85da6af886 Make retired package cleanup dependency-aware 2026-06-04 18:38:25 -04:00
Ryan Hughes 5214bfd1ad Harden Omarchy 4 live upgrade cutover 2026-06-04 18:38:25 -04:00
Ryan Hughes f1bdec3e67 add cleanup 2026-06-04 18:38:25 -04:00
Ryan Hughes e707ca116f Remove retired upgrade packages together 2026-06-04 18:38:25 -04:00
Ryan Hughes 85bf7f108d Harden Omarchy 4 upgrade and first-run retry 2026-06-04 18:38:25 -04:00
Ryan Hughes 06db866467 Prepare installer for ISO-owned finalization 2026-06-04 18:38:25 -04:00
Ryan Hughes bcf07e424a Add Omarchy 4 upgrade bridge
Introduce a self-contained omarchy-upgrade-to-4 command for legacy installs and remove the 4.0 package-layout transition from the normal migration runner.
2026-06-04 18:37:32 -04:00
Ryan Hughes 75cb4f7195 Make setup ISO-only
Remove legacy online installer entrypoints, collapse migrations for 4.0, and move setup responsibilities into target-side system, hardware, and user commands.
2026-06-04 18:37:32 -04:00
Ryan Hughes b45e8464ef Move NVIDIA env setup to Hyprland Lua
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.
2026-06-04 18:35:01 -04:00
Ryan Hughes 27f6d9d364 migrations: keep system helpers sudo-compatible 2026-06-04 18:35:01 -04:00
Ryan Hughes bf14f69017 installer: require target user for system finalizer 2026-06-04 18:35:01 -04:00
Ryan Hughes 67c401c125 docs: refresh SDDM crosswalk 2026-06-04 18:35:01 -04:00
Ryan Hughes 487fcb8038 install: rely on packaged SDDM assets 2026-06-04 18:35:01 -04:00
Ryan Hughes 844278ad19 docs: add installer review crosswalk 2026-06-04 18:35:01 -04:00
Ryan Hughes acdb1d1b57 install: split SDDM static config from autologin 2026-06-04 18:35:01 -04:00
Ryan Hughes d12d449b03 install: split and harden hardware config scripts 2026-06-04 18:35:01 -04:00
Ryan Hughes 6056f8800c install: drop helpers replaced by package-owned config 2026-06-04 18:35:01 -04:00
Ryan Hughes f451b504eb install: route theme setup through split scripts 2026-06-04 18:35:01 -04:00
Ryan Hughes e393a3a836 install: centralize service enablement 2026-06-04 18:35:01 -04:00
Ryan Hughes 7ef5bc56fd install: make system scripts root-finalizer aware 2026-06-04 18:35:01 -04:00
Ryan Hughes 0cfa1b66c4 installer: route install through system and user phases 2026-06-04 18:35:01 -04:00
Ryan Hughes 53e2611507 install: add split system and user targets 2026-06-04 18:35:01 -04:00
Ryan Hughes b29747a54b installer: reduce offline finalizer work 2026-06-04 18:35:01 -04:00
Ryan Hughes 724f46f145 installer: trace finalizer in debug builds 2026-06-04 18:35:01 -04:00
Ryan Hughes b5ed8cad4d installer: slim finalizer bootstrap 2026-06-04 18:35:01 -04:00
Ryan Hughes 96a020f756 installer: tolerate missing tty in offline finalizer 2026-06-04 18:35:01 -04:00
Ryan Hughes e67128e4c9 installer: keep chroot log output plain 2026-06-04 18:35:01 -04:00
Ryan Hughes 250799af81 installer: tolerate missing archinstall duration 2026-06-04 18:35:01 -04:00
Ryan Hughes 41b2fa0174 installer: preserve error menu exit status 2026-06-04 18:35:01 -04:00
Ryan Hughes e01c233431 installer: keep offline finalizer non-interactive 2026-06-04 18:35:01 -04:00
Ryan Hughes 830c798bde installer: honor configured Limine ESP path 2026-06-04 18:35:01 -04:00
Ryan Hughes 9feab5081f installer: preserve explicit exit status in exit trap 2026-06-04 18:35:01 -04:00
Ryan Hughes 2bf3315719 installer: avoid gsettings in chrooted installs 2026-06-04 18:35:01 -04:00
Ryan Hughes 74aaff5ed3 installer: calculate install duration from epoch 2026-06-04 18:34:35 -04:00
Ryan Hughes d6cdefcf6b installer: recover install start time from log 2026-06-04 18:34:35 -04:00
Ryan Hughes ddee039cd2 installer: leave offline snapper setup to orchestrator 2026-06-04 18:34:35 -04:00
Ryan Hughes a1a15ef663 installer: configure snapper without dbus in offline finalizer 2026-06-04 18:34:35 -04:00
Ryan Hughes 88f3181124 installer: split runtime and installer paths in finalizer 2026-06-04 18:34:35 -04:00
Ryan Hughes 58f03a9216 installer: preserve exit code in error handler 2026-06-04 18:34:35 -04:00
Ryan Hughes bd9692d6e3 omarchy-upload-log: avoid hostname dependency 2026-06-04 18:34:35 -04:00
Ryan Hughes f2821bb657 limine-snapper.sh: validate parsed CMDLINE in pre-populated branch
The harvest branch already enforces non-empty cmdline + presence of
root=. The pre-populated branch (added in 0d2688a5) was missing the
same validation, so a malformed /etc/default/limine could slip
through and the later cryptdevice= check would silently no-op
because $CMDLINE was empty.
2026-06-04 18:34:35 -04:00
Ryan Hughes e9aa8835ee limine-snapper.sh: skip harvest dance when /etc/default/limine is pre-populated
The ISO orchestrator now writes /etc/default/limine directly from the
install config (with the real cmdline already substituted) before the
chroot phase runs. The previous unconditional find+harvest+copy+sed
sequence would (a) find our orchestrator-staged /boot/limine.conf which
has no `cmdline:` line and (b) exit 1 on "failed to extract kernel
cmdline".

Skip the harvest entirely when /etc/default/limine already exists
without the @@CMDLINE@@ placeholder. Parse CMDLINE from the existing
file so the downstream cryptdevice= validation still has it to compare.

The harvest path remains as a fallback for online reinstalls and any
flow where /etc/default/limine wasn't pre-populated by the orchestrator.
2026-06-04 18:34:35 -04:00
Ryan Hughes 9800b5b73b Drop orchestrator from omarchy-installer (moved to omarchy-iso)
The orchestrator only runs on the live ISO, so it lives in omarchy-iso
where the rest of the ISO-specific code (configurator, .automated_script
.sh, archinstall pacman config) lives. omarchy-installer stays the
monorepo of Omarchy source content (configs, themes, default files,
install scripts) without a Python install driver mixed in.

bin/omarchy-install simplifies to a one-liner: it's the online entry
point now, no --config dispatcher. The orchestrator never invokes it;
it runs finalize.sh directly via arch-chroot.
2026-06-04 18:34:35 -04:00
Ryan Hughes c6ccd62550 Wire archinstall adapter + concrete phase implementations
Chunks 2-6 of the C3 refactor. With the adapter in place, the phase
list collapses from 12 stubs to 5 real phases:

  prepare_live          parse user_*.json into archinstall handlers
  arch_install          partition + base + bootloader + limine config +
                        early omarchy + useradd + runtime omarchy (all
                        inside a single Installer context manager)
  run_chroot_finalizer  arch-chroot -u $user → finalize.sh
  validate_boot         halt if /boot/limine.conf, /etc/kernel/cmdline,
                        or UKI are missing/malformed
  finish                reboot prompt

Key reordering vs upstream guided.py: write_limine_config runs BETWEEN
add_bootloader and the first add_additional_packages call. By the time
omarchy-limine pulls limine-mkinitcpio-hook (in the runtime package
install), /etc/default/limine and /etc/kernel/cmdline are in place, so
the UKI is built correctly on the first try — no stale-UKI purge,
no follow-up limine-update.

add_additional_packages is split into two calls so /etc/skel is
populated (via omarchy-settings in EARLY_PACKAGES) BEFORE useradd:

  EARLY_PACKAGES = base-devel git omarchy-keyring omarchy-settings omarchy-installer
  → installer.create_users(users)
  → runtime: omarchy + omarchy-base.packages

archinstall_adapter.py is the ONLY module that imports from archinstall.
If archinstall's API churns, the blast radius is contained here. Tested
against archinstall 4.3 / Python 3.14.

Limine template lookup tries the new install/assets/limine/ path first
and falls back to the legacy default/limine/ location during the
template-ownership migration (lands in a follow-up chunk).
2026-06-04 18:34:35 -04:00
Ryan Hughes df645a202d Simplify finalize.sh and install.sh's preflight ownership
finalize.sh just does the in-target work: env setup, source helpers,
mark current migrations as done (idempotent), run packaging/config/
login/post-install. No preflight orchestration, no install_mode_is
offline branches.

install.sh (online) inlines the preflight bits that are online-specific:
guard.sh, begin.sh, show-env.sh. The first-run-mode setup that used to
live in preflight (offline-only) moves to an orchestrator phase in a
later chunk; disable-mkinitcpio.sh is obsolete entirely because the C3
phase ordering means the limine UKI hook fires exactly once with
correct config in place.

install/preflight/{all,disable-mkinitcpio,first-run-mode}.sh still
exist on disk but are no longer sourced. They'll get removed in a
later chunk once the orchestrator absorbs first-run-mode.
2026-06-04 18:34:35 -04:00
Ryan Hughes 2beda6abed Scaffold Python orchestrator + split install.sh / finalize.sh
Chunk 1 of the C3 refactor: replace the two-pass install model (archinstall
CLI + custom shell dance + chroot bash installer) with a single Python
orchestrator that owns phase ordering, using archinstall as a library
subsystem.

Splits the bash entry point into two:
- install.sh: online entry point. Ensures omarchy runtime + base.packages
  are installed/up to date, then exec's finalize.sh.
- finalize.sh: the in-target portion (preflight + packaging + config +
  login + post-install). Called by install.sh (online) AND by the
  orchestrator after arch-chroot -u $USER (offline).

Adds the orchestrator skeleton under install/orchestrator/:
- main.py: entry point, builds + runs the phase list
- context.py: InstallContext (parsed configurator JSON + invocation paths)
- phases.py: phase state machine (logging + state.json + error wrapping)
- phases_impl.py: stubbed phase implementations (filled in by chunks 2-6)
- archinstall_adapter.py: thin compat wall around archinstall lib imports
  (only this module imports from archinstall.*)
- ui.py: gum subprocess wrappers so the orchestrator keeps the same
  styled-terminal UX as the bash installer

Updates bin/omarchy-install to dispatch:
- --config <json> in args → python -m orchestrator.main (ISO install)
- anything else → bash install.sh (online rerun on installed system)

Concrete phase logic lands in subsequent chunks. All phases currently
raise NotImplementedError; the orchestrator imports cleanly and --help
works as a smoke check.
2026-06-04 18:34:35 -04:00
Ryan Hughes d0ec7c481f Add qmk-hid to omarchy-other.packages
install/config/hardware/framework/qmk-hid.sh installs the qmk-hid
package on Framework 16 hardware, but it wasn't listed in any of the
ISO builder's package sources, so it wasn't being pulled into the
offline mirror. Adding it under the Framework 16 section in
omarchy-other.packages so the ISO build picks it up.
2026-06-04 18:34:35 -04:00
Ryan Hughes cd05c69820 omarchy-upload-log: find omarchy install log under /mnt in ISO context
The omarchy install runs inside an arch-chroot to /mnt, so its log file
(/var/log/omarchy-install.log from the installer's perspective) is at
/mnt/var/log/omarchy-install.log from the live ISO. The previous script
only read /var/log/omarchy-install.log, and 'cat $ARCHINSTALL_LOG
$OMARCHY_LOG 2>/dev/null' swallowed the resulting 'No such file' error,
so uploaded logs from the ISO contained only the archinstall portion.

Prefer the /mnt path when it exists (live ISO post-install), fall back
to /var/log when running on the installed system. Also print a visible
separator between the two log sections and warn on stderr if the omarchy
log is missing entirely (instead of silently producing an incomplete
upload).
2026-06-04 18:34:35 -04:00
Ryan Hughes 99de786ce1 Drop install/first-run/gdk-scale.sh
The lua-based monitors config (~/.config/hypr/monitors.lua) ships from
skel with sensible defaults (omarchy_gdk_scale = 2, omarchy_monitor_scale
= "auto"). Hyprland handles the dynamic monitor scale at runtime via
"auto"; 'omarchy hyprland monitor scaling <N>' already updates both
omarchy_monitor_scale and omarchy_gdk_scale in monitors.lua when the
user wants to adjust.

The first-run 'detect what hyprland picked and write it back' dance
was leftover from the .conf-based config; it's redundant on the lua
flow and was the script that aborted omarchy-first-run under set -e
when it sed'd a missing monitors.conf.
2026-06-04 18:34:35 -04:00
Ryan Hughes 0dd91106e7 omarchy-first-run: run setup-user first; fix gdk-scale.sh for lua config
Two bugs caused fresh users to land without branding files / AI skill
symlinks / nautilus extensions / xdg dirs / etc.:

1. install/first-run/gdk-scale.sh sed-edited ~/.config/hypr/monitors.conf,
   but the lua-based config flow uses ~/.config/hypr/monitors.lua. sed -i
   on the missing .conf returned non-zero, set -e fired, omarchy-first-run
   aborted mid-block AFTER deleting ~/.local/state/omarchy/first-run.mode.
   omarchy-setup-user (called at the bottom of the script, outside the
   if-block) never ran, so setup-user.done never got written and the
   per-user defaults (~/.config/omarchy/branding/*, ~/.agents/skills/omarchy,
   xdg dirs, etc.) never got created.

   Replace the .conf sed with a call to omarchy-hyprland-monitor-scaling
   which already knows how to persist into monitors.lua.

2. Move 'omarchy-setup-user || true' to the TOP of omarchy-first-run, before
   the privileged first-run block. setup-user is idempotent and gated on
   its own marker, so running it first is safe and means a failure in any
   of the privileged steps can't prevent user setup from completing.
2026-06-04 18:34:35 -04:00
Ryan Hughes 71659cd42b Switch from 1password-beta back to 1password
The edge mirror temporarily lacked a current 1password build (315e60d
hadn't been rebuilt), so install/omarchy-base.packages was pointing at
1password-beta as a workaround. Reverting now that the stable package
is available, and matching the entry in omarchy-remove-preinstalls so
that bin actually drops the package we installed.
2026-06-04 18:34:35 -04:00
Ryan Hughes a086b03dd1 Replace ~/.local/share/omarchy runtime paths with $OMARCHY_PATH
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.
2026-06-04 18:34:35 -04:00
Ryan Hughes 612f947e1d limine-snapper.sh: move validation after snapper + hook re-enable
Per apollo audit: the /boot/limine.conf assertion grep was firing
BEFORE snapper config setup, btrfs quota disable, service enable, and
the mkinitcpio pacman hook re-enable. A validation failure (the failure
path the validation exists for) would leave the system half-configured.

Move the validation block to after 'mkinitcpio hooks re-enabled' so all
the post-config steps run first. Guard it with LIMINE_CONFIGURED=true so
non-limine setups still pass straight through to efibootmgr cleanup.
2026-06-04 18:34:35 -04:00
Ryan Hughes caa47c7595 limine-snapper.sh: use limine-update + purge stale UKIs
mkinitcpio -P alone doesn't trigger limine's UKI pipeline. The
limine-mkinitcpio-hook package installs /etc/pacman.d/hooks/90-mkinitcpio
-install.hook (overriding mkinitcpio's normal hook) which executes
/usr/share/libalpm/scripts/limine-mkinitcpio-install only on pacman
transactions, OR via the limine-mkinitcpio / limine-update CLI wrappers.

The previous fix (mkinitcpio -P) rebuilt initramfs-linux.img but left
the stale empty-cmdline UKI at /boot/EFI/Linux/<machine-id>_linux.efi
untouched. limine-update then booted that file.

Changes:
- Validate the cmdline extracted from /boot/limine.conf: fail loudly if
  empty or missing root=
- Delete every alternate /boot/limine.conf so limine-update can't pick
  the wrong one
- Delete stale UKIs for every installed kernel pkgbase before rebuilding
- Replace 'mkinitcpio -P' with 'limine-update' (which does
  limine-install + limine-mkinitcpio, reading KERNEL_CMDLINE from
  /etc/default/limine via limine-entry-tool and embedding it into a
  fresh UKI)
- Assert /boot/limine.conf has the Omarchy entry and (for encrypted
  installs) the cryptdevice= cmdline before continuing
2026-06-04 18:34:35 -04:00
Ryan Hughes 53a07811c8 limine-snapper.sh: write /etc/kernel/cmdline and rebuild UKI
In the package-based install, omarchy-limine is a hard dep of omarchy,
so archinstall pacstraps limine-mkinitcpio-hook (via omarchy-limine's
depends) early. That triggers a UKI build BEFORE limine-snapper.sh
runs, which means the UKI is built with no kernel cmdline (the
'Kernel command line is not available' warning in the archinstall log).
The system then can't unlock the LUKS root on boot because the encrypt
hook has no cryptdevice= to act on, and drops to an emergency shell.

The previous flow worked because 'pacman -S limine-mkinitcpio-hook'
inside limine-snapper.sh installed the hook for the first time, firing
its post-transaction UKI rebuild AFTER /etc/default/limine had been
written. With it pre-installed, '--needed' makes that line a no-op.

Fix: after writing /etc/default/limine, write the same cmdline to
/etc/kernel/cmdline (the source mkinitcpio --uki reads) and explicitly
run mkinitcpio -P to rebuild the UKIs with the correct cmdline.
2026-06-04 18:34:35 -04:00
Ryan Hughes a481c17846 Drop install/packaging/fonts.sh, fix omarchy-setup-lock exit code
fonts.sh: obsolete. omarchy-settings installs omarchy.ttf to
/usr/share/fonts/omarchy/ system-wide and the fontconfig package's
post-install hook updates the cache, so copying it to ~/.local/share/
fonts and re-running fc-cache is redundant. The script was also failing
because omarchy-settings explicitly removes the source path
/usr/share/omarchy/config/omarchy.ttf during package install.

omarchy-setup-lock: the final line was 'omarchy-shell lock status
>/dev/null && echo "..."' which inherits the failed exit code when
omarchy-shell can't reach a running shell (always the case during chroot
install). set -e exempts cmd1 of && from triggering, but the script
still returns that non-zero as its own exit code, which the install
wrapper treated as a script failure. Wrap in an if/then so a failed
status check doesn't poison the script's exit code.
2026-06-04 18:34:35 -04:00
Ryan Hughes ed06892970 Switch log uploader from 0x0.st to logs.omarchy.org
0x0.st has been intermittently down. logs.omarchy.org accepts the same
curl -F 'file=@-' POST and returns the resulting URL in the response
body, so the swap is purely the endpoint. Dropping the -Fexpires=24
parameter since logs.omarchy.org doesn't honour it (and doesn't expire
uploads by default).
2026-06-04 18:34:35 -04:00
Ryan Hughes ad5c942725 install.sh: pacman -S omarchy-base.packages alongside omarchy meta
omarchy no longer hard-depends on the full install set; ensure_omarchy_runtime
now installs everything in install/omarchy-base.packages in addition to
the omarchy meta. Offline mode's assertion stays the same (the ISO does
the equivalent via .automated_script.sh).
2026-06-04 18:34:35 -04:00
Ryan Hughes 8e05d4d92a Move full-runtime dep to omarchy meta; thin omarchy-installer
Apollo-recommended dep split:
- omarchy-installer: bash gum jq git only (just the runner)
- omarchy: depends on omarchy-keyring + omarchy-settings + omarchy-limine
  + the runtime stack
- omarchy-settings, omarchy-limine: standalone

install.sh now installs the runtime (pacman -Syu --needed omarchy) before
sourcing preflight/all.sh in online mode, and asserts it's already
present in offline mode (ISO pacstraps it before user creation so
/etc/skel is populated).

boot.sh installs only omarchy-keyring + omarchy-installer (small + fast),
then exec's omarchy-install which handles the full-runtime pull.

User-visible effect: 'pacman -S omarchy-installer' now installs ~5 files
instead of the entire Omarchy stack. Users get a clean choice between
'I just want the installer' and 'I want the full Omarchy desktop'.
2026-06-04 18:34:35 -04:00
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
585 changed files with 6915 additions and 4790 deletions
+4
View File
@@ -0,0 +1,4 @@
# Python bytecode (orchestrator)
__pycache__/
*.pyc
+24 -16
View File
@@ -74,18 +74,19 @@ Example:
# Install Scripts
Install entry points (`install.sh`, `boot.sh`) use `#!/bin/bash`. Many scripts under `install/` are sourced via `run_logged` and intentionally do not have shebangs.
The ISO owns installation orchestration. This repo ships target-side setup commands and reusable setup leaves:
Install stage files follow this pattern:
- `bin/omarchy-setup-system` runs root-owned system setup during ISO finalization.
- `bin/omarchy-setup-hardware` runs idempotent hardware-specific setup and is called by `omarchy-setup-system`.
- `bin/omarchy-finalize-user` runs the per-user runtime finalization (skill symlinks, xdg-user-dirs, mime defaults, `install/user/all.sh`). Shipped user defaults are seeded by `/etc/skel` from `omarchy-settings`, not by this command. `bin/omarchy-reinstall-configs` is the explicit destructive resync of those defaults into an existing user's `$HOME`.
- leaf scripts under `install/` are sourced by `run_logged $OMARCHY_INSTALL/path/to/script.sh` and intentionally do not have shebangs.
- avoid `exit` in sourced setup scripts unless intentionally aborting setup.
- use `$OMARCHY_INSTALL` and `$OMARCHY_PATH` instead of hard-coded Omarchy paths.
- keep root-scoped hardware setup under `install/hardware/` and orchestrate it through `install/hardware/all.sh`.
- keep every per-user setup leaf under `install/user/` (including `install/user/hardware/` and `install/user/first-run/`) so it is clear what must run for each user.
- prefer helper commands for package and command checks where available.
- `install/*/all.sh` lists scripts in execution order
- leaf scripts are sourced by `run_logged $OMARCHY_INSTALL/path/to/script.sh`
- avoid `exit` in sourced install scripts unless intentionally aborting the install
- use `$OMARCHY_INSTALL` and `$OMARCHY_PATH` instead of hard-coded Omarchy paths
- keep hardware-specific logic under `install/config/hardware/`
- prefer helper commands for package and command checks where available
Raw `command -v`, `pacman`, and `pacman-key` are acceptable in bootstrap/preflight/package-helper contexts where the helper commands may not be available yet or where direct package-manager behavior is the point of the script.
Raw `command -v`, `pacman`, and `pacman-key` are acceptable in package-helper contexts where direct package-manager behavior is the point of the script.
# Helper Commands
@@ -98,7 +99,7 @@ Use these instead of raw shell commands:
- `omarchy-notification-send` - send desktop notifications; do not call `notify-send` directly
- `omarchy-hw-asus-rog` - detect ASUS ROG hardware (and similar `hw-*` commands)
Exceptions are allowed for bootstrap, preflight, migration, and package-helper scripts where the helper may not be available yet, where the helper itself is being implemented, or where direct package-manager behavior is required.
Exceptions are allowed for migration and package-helper scripts where the helper may not be available yet, where the helper itself is being implemented, or where direct package-manager behavior is required.
# Config Structure
@@ -170,19 +171,26 @@ To copy a default config to user config with automatic backup:
omarchy-refresh-config hypr/hyprlock.conf
```
This copies `~/.local/share/omarchy/config/hypr/hyprlock.conf` to `~/.config/hypr/hyprlock.conf`.
This copies `/etc/skel/.config/hypr/hyprlock.conf` to `~/.config/hypr/hyprlock.conf`.
# Migrations
To create a new migration, run `omarchy-dev-add-migration --no-edit`. This creates a migration file named after the unix timestamp of the last commit.
Read `docs/migrations.md` before creating or changing migrations.
Migrations are split by execution scope:
- `migrations/system/<timestamp>.sh` — root, noninteractive, safe to run from pacman via `omarchy-migrate-system` (`omarchy` `post_upgrade` calls it). Use for `/etc`, `/usr`, `/boot`, services, hardware quirks, and other system state. Do not prompt.
- `migrations/user/<timestamp>.sh` — current user/session, may touch `~/.config`, `~/.local`, user systemd, browser prefs, DBus/session state, and may prompt if necessary. Runs through `omarchy-migrate` / `omarchy-migrate-user`; pending state is per-user based on missing files under `~/.local/state/omarchy/migrations/user/`.
To create a new migration, run `omarchy-dev-add-migration system --no-edit` or `omarchy-dev-add-migration user --no-edit` based on scope.
New migration format:
- File permissions must be `0644` (`-rw-r--r--`); migrations are sourced, not executed directly
- File permissions must be `0644` (`-rw-r--r--`); migration runners execute them with `bash -euo pipefail`, not through executable bits
- No shebang line
- Start with an `echo` describing what the migration does
- Use `$OMARCHY_PATH` to reference the omarchy directory
- Prefer helper commands such as `omarchy-cmd-present`, `omarchy-cmd-missing`, `omarchy-pkg-present`, and `omarchy-pkg-missing`
Some older migrations predate these rules. Do not copy older migrations that start with shebangs, omit the leading `echo`, or hard-code `~/.local/share/omarchy`.
Omarchy 4.0 is upgraded through `bin/omarchy-upgrade-to-4`, not through the normal migration runner. Do not add compatibility migrations for old installer layouts; put pre-4 package-layout transition work in the upgrade command instead.
Migrations may use raw `pacman`, `command -v`, or direct config edits when needed for historical compatibility or one-off repair work.
Migrations may use raw `pacman`, `command -v`, or direct config edits when needed for one-off repair work.
+8
View File
@@ -0,0 +1,8 @@
[Desktop Entry]
Version=1.0
Name=Basecamp
Exec=omarchy-launch-webapp https://launchpad.37signals.com
Terminal=false
Type=Application
Icon=basecamp
StartupNotify=true
+8
View File
@@ -0,0 +1,8 @@
[Desktop Entry]
Version=1.0
Name=ChatGPT
Exec=omarchy-launch-webapp https://chatgpt.com/
Terminal=false
Type=Application
Icon=chatgpt
StartupNotify=true
+8
View File
@@ -0,0 +1,8 @@
[Desktop Entry]
Version=1.0
Name=Discord
Exec=omarchy-launch-webapp https://discord.com/channels/@me
Terminal=false
Type=Application
Icon=discord
StartupNotify=true
+8
View File
@@ -0,0 +1,8 @@
[Desktop Entry]
Version=1.0
Name=Disk Usage
Exec=xdg-terminal-exec --app-id=TUI.float -e bash -c "dust -r; read -n 1 -s"
Terminal=false
Type=Application
Icon=disk-usage
StartupNotify=true
+8
View File
@@ -0,0 +1,8 @@
[Desktop Entry]
Version=1.0
Name=Docker
Exec=xdg-terminal-exec --app-id=TUI.tile -e lazydocker
Terminal=false
Type=Application
Icon=docker
StartupNotify=true
+8
View File
@@ -0,0 +1,8 @@
[Desktop Entry]
Version=1.0
Name=Figma
Exec=omarchy-launch-webapp https://figma.com/
Terminal=false
Type=Application
Icon=figma
StartupNotify=true
+8
View File
@@ -0,0 +1,8 @@
[Desktop Entry]
Version=1.0
Name=Fizzy
Exec=omarchy-launch-webapp https://app.fizzy.do/
Terminal=false
Type=Application
Icon=fizzy
StartupNotify=true
+8
View File
@@ -0,0 +1,8 @@
[Desktop Entry]
Version=1.0
Name=GitHub
Exec=omarchy-launch-webapp https://github.com/
Terminal=false
Type=Application
Icon=github
StartupNotify=true
+8
View File
@@ -0,0 +1,8 @@
[Desktop Entry]
Version=1.0
Name=Google Contacts
Exec=omarchy-launch-webapp https://contacts.google.com/
Terminal=false
Type=Application
Icon=google-contacts
StartupNotify=true
+8
View File
@@ -0,0 +1,8 @@
[Desktop Entry]
Version=1.0
Name=Google Maps
Exec=omarchy-launch-webapp https://maps.google.com
Terminal=false
Type=Application
Icon=google-maps
StartupNotify=true
+8
View File
@@ -0,0 +1,8 @@
[Desktop Entry]
Version=1.0
Name=Google Messages
Exec=omarchy-launch-webapp https://messages.google.com/web/conversations
Terminal=false
Type=Application
Icon=google-messages
StartupNotify=true
+8
View File
@@ -0,0 +1,8 @@
[Desktop Entry]
Version=1.0
Name=Google Photos
Exec=omarchy-launch-webapp https://photos.google.com/
Terminal=false
Type=Application
Icon=google-photos
StartupNotify=true
+9
View File
@@ -0,0 +1,9 @@
[Desktop Entry]
Version=1.0
Name=HEY
Exec=omarchy-webapp-handler-hey %u
Terminal=false
Type=Application
Icon=hey
StartupNotify=true
MimeType=x-scheme-handler/mailto
+8
View File
@@ -0,0 +1,8 @@
[Desktop Entry]
Version=1.0
Name=WhatsApp
Exec=omarchy-launch-webapp https://web.whatsapp.com/
Terminal=false
Type=Application
Icon=whatsapp
StartupNotify=true
+8
View File
@@ -0,0 +1,8 @@
[Desktop Entry]
Version=1.0
Name=X
Exec=omarchy-launch-webapp https://x.com/
Terminal=false
Type=Application
Icon=x
StartupNotify=true
+8
View File
@@ -0,0 +1,8 @@
[Desktop Entry]
Version=1.0
Name=YouTube
Exec=omarchy-launch-webapp https://youtube.com/
Terminal=false
Type=Application
Icon=youtube
StartupNotify=true
+9
View File
@@ -0,0 +1,9 @@
[Desktop Entry]
Version=1.0
Name=Zoom
Exec=omarchy-webapp-handler-zoom %u
Terminal=false
Type=Application
Icon=zoom
StartupNotify=true
MimeType=x-scheme-handler/zoommtg;x-scheme-handler/zoomus
+1 -1
View File
@@ -4,7 +4,7 @@ Name=Battle.net
GenericName=Game Launcher
Comment=Blizzard game launcher (umu-launcher + GE-Proton)
Exec=omarchy-launch-battlenet
Icon=Battle.net
Icon=battle-net
Terminal=false
Categories=Game;
StartupNotify=true
+1
View File
@@ -39,6 +39,7 @@ GROUP_DESCRIPTIONS[clipboard]="Clipboard helpers"
GROUP_DESCRIPTIONS[cmd]="Command and shortcut helpers"
GROUP_DESCRIPTIONS[config]="System configuration helpers"
GROUP_DESCRIPTIONS[debug]="Diagnostics and support logs"
GROUP_DESCRIPTIONS[finalize]="Finalize user setup"
GROUP_DESCRIPTIONS[default]="Default application selection"
GROUP_DESCRIPTIONS[dev]="Omarchy development tools"
GROUP_DESCRIPTIONS[dns]="DNS resolver configuration"
-18
View File
@@ -1,18 +0,0 @@
#!/bin/bash
# omarchy:summary=Set the branch for Omarchy's git repository.
# omarchy:args=<master|rc|dev>
if (($# == 0)); then
echo "Usage: omarchy-branch-set [master|rc|dev]"
exit 1
else
branch="$1"
fi
if [[ $branch != "master" && $branch != "rc" && $branch != "dev" ]]; then
echo "Error: Invalid branch '$branch'. Must be one of: master, rc, dev"
exit 1
fi
git -C $OMARCHY_PATH switch $branch
+7 -8
View File
@@ -1,22 +1,21 @@
#!/bin/bash
# omarchy:summary=Set the Omarchy channel, which dictates what git branch and package repository is used.
# omarchy:summary=Set the Omarchy package channel.
# omarchy:args=<stable|rc|edge|dev>
# omarchy:requires-sudo=true
set -e
if (($# == 0)); then
echo "Usage: omarchy-channel-set [stable|rc|edge|dev]"
exit 1
else
channel="$1"
fi
channel="$1"
case "$channel" in
"stable") omarchy-branch-set "master" && omarchy-refresh-pacman "stable" ;;
"rc") omarchy-branch-set "rc" && omarchy-refresh-pacman "rc" ;;
"edge") omarchy-branch-set "master" && omarchy-refresh-pacman "edge" ;;
"dev") omarchy-branch-set "dev" && omarchy-refresh-pacman "edge" ;;
*) echo "Unknown channel: $channel"; exit 1; ;;
stable|rc|edge) omarchy-refresh-pacman "$channel" ;;
dev) omarchy-refresh-pacman edge ;;
*) echo "Unknown channel: $channel"; exit 1 ;;
esac
omarchy-update -y
+2 -4
View File
@@ -37,7 +37,7 @@ fi
cat > "$LOG_FILE" <<EOF
Date: $(date)
Hostname: $(hostname)
Omarchy Branch: $(git -C "$OMARCHY_PATH" branch --show-current 2>/dev/null || echo "unknown")
Omarchy Package: $(pacman -Q omarchy 2>/dev/null || echo "unknown")
=========================================
SYSTEM INFORMATION
@@ -75,14 +75,12 @@ ACTION=$(gum choose "${OPTIONS[@]}")
case "$ACTION" in
"Upload log")
echo "Uploading debug log to logs.omarchy.org..."
URL=$(curl -sF "file=@$LOG_FILE" -Fexpires=24 https://logs.omarchy.org)
URL=$(curl -sf -F "file=@$LOG_FILE" -Fexpires=24 https://logs.omarchy.org/)
if (( $? == 0 )) && [[ -n $URL ]]; then
echo "✓ Log uploaded successfully!"
echo "Share this URL:"
echo ""
echo " $URL"
echo ""
echo "This link will expire in 24 hours."
else
echo "Error: Failed to upload log file"
exit 1
+2 -1
View File
@@ -5,7 +5,8 @@
# omarchy:examples=omarchy default terminal ghostty | omarchy default terminal kitty
if (($# == 0)); then
desktop_id=$(grep -vE '^($|#)' ~/.config/xdg-terminals.list 2>/dev/null | head -n 1)
desktop_id=$(xdg-terminal-exec --print-id 2>/dev/null || true)
desktop_id=${desktop_id%%:*}
case "$desktop_id" in
Alacritty.desktop) echo "alacritty" ;;
foot.desktop) echo "foot" ;;
+27 -7
View File
@@ -1,13 +1,33 @@
#!/bin/bash
# omarchy:summary=Creates a new Omarchy migration named after the unix timestamp of the last commit.
# omarchy:summary=Create a new Omarchy migration in the current source tree.
# omarchy:args=<system|user> [--no-edit]
cd ~/.local/share/omarchy
migration_file="$HOME/.local/share/omarchy/migrations/$(git log -1 --format=%cd --date=unix).sh"
touch $migration_file
set -euo pipefail
if [[ $1 != "--no-edit" ]]; then
nvim $migration_file
scope="${1:-}"
case "$scope" in
system|user)
shift
;;
-h|--help|"")
echo "Usage: omarchy-dev-add-migration <system|user> [--no-edit]"
exit 0
;;
*)
echo "Unknown migration scope: $scope" >&2
echo "Usage: omarchy-dev-add-migration <system|user> [--no-edit]" >&2
exit 1
;;
esac
cd "${OMARCHY_PATH:-$(pwd)}"
mkdir -p "migrations/$scope"
migration_file="migrations/$scope/$(git log -1 --format=%cd --date=unix).sh"
touch "$migration_file"
if [[ ${1:-} != "--no-edit" ]]; then
nvim "$migration_file"
fi
echo $migration_file
printf '%s\n' "$PWD/$migration_file"
+80
View File
@@ -0,0 +1,80 @@
#!/bin/bash
# omarchy:summary=Point Omarchy at a local checkout for live editing
# omarchy:group=dev
# omarchy:args=<path-to-checkout>
# omarchy:examples=omarchy dev link ~/Work/omarchy/omarchy-installer
set -euo pipefail
# Sudo wipes HYPRLAND_INSTANCE_SIGNATURE, so the live-session refresh below
# can't reach hyprctl. Run as user; we sudo internally for the conf write.
if [[ $EUID -eq 0 ]]; then
echo "Error: run omarchy-dev-link as your user, not under sudo." >&2
exit 1
fi
if [[ $# -ne 1 || $1 == "-h" || $1 == "--help" ]]; then
cat <<USAGE
Usage: omarchy dev link <path-to-checkout>
Writes /etc/omarchy.conf so OMARCHY_PATH resolves to <path-to-checkout>
in all new shells, the Hyprland session, and Quickshell. Restarts
omarchy-shell and reloads hyprctl so changes take effect immediately.
Affects only \$OMARCHY_PATH-resolved trees: bin/, default/, shell/,
themes/, applications/, config/. Files installed at fixed system paths
(/etc/, /usr/lib/systemd/, udev rule bodies, /etc/skel after user
creation, /usr/share/plymouth) are NOT covered — for those, use
omarchy-dev-pkg-test to build and install the package from the checkout.
USAGE
exit 0
fi
target=$(realpath -e "$1" 2>/dev/null) || {
echo "Error: path does not exist: $1" >&2
exit 1
}
for required in bin default shell; do
if [[ ! -d "$target/$required" ]]; then
echo "Warning: $target/$required not found — does this look like an Omarchy source checkout?" >&2
fi
done
# Strip any previous dev-link's bin/ from PATH before adding the new one,
# so repeated link calls don't accumulate stale entries.
prior_target=""
if [[ -f /etc/omarchy.conf ]]; then
prior_target=$(sed -n 's/^[[:space:]]*export[[:space:]]\+OMARCHY_PATH="\?\([^"]*\)"\?/\1/p' /etc/omarchy.conf | tail -1)
fi
echo "Pointing Omarchy at $target"
printf 'export OMARCHY_PATH="%s"\n' "$target" | sudo tee /etc/omarchy.conf >/dev/null
export OMARCHY_PATH="$target"
if [[ -n $prior_target && $prior_target != "$target" ]]; then
PATH=$(printf '%s' "$PATH" | tr ':' '\n' | grep -vFx "$prior_target/bin" | paste -sd:)
fi
export PATH="$target/bin:$PATH"
if command -v hyprctl >/dev/null 2>&1 && hyprctl version &>/dev/null; then
hyprctl setenv OMARCHY_PATH "$target" >/dev/null
hyprctl setenv PATH "$PATH" >/dev/null
echo " Updated Hyprland session env."
systemctl --user import-environment OMARCHY_PATH PATH 2>/dev/null || true
echo " Updated systemd --user env."
if pgrep -x quickshell >/dev/null 2>&1; then
omarchy-restart-shell
echo " Restarted omarchy-shell."
fi
hyprctl reload >/dev/null
echo " Reloaded Hyprland config."
fi
echo
echo "Done. Open a new shell (or restart existing ones) to pick up the new"
echo "OMARCHY_PATH. Run 'omarchy dev unlink' to restore the package install."
+137
View File
@@ -0,0 +1,137 @@
#!/bin/bash
# omarchy:summary=Build and install an Omarchy package from a local checkout
# omarchy:group=dev
# omarchy:args=[package-name] [path-to-checkout]
# omarchy:examples=omarchy dev pkg-test | omarchy dev pkg-test omarchy-dev ~/Work/omarchy/omarchy-installer
set -euo pipefail
if [[ ${1:-} == "-h" || ${1:-} == "--help" ]]; then
cat <<USAGE
Usage: omarchy dev pkg-test [package-name] [path-to-checkout]
Builds and installs an Omarchy package from a local Omarchy source
checkout. Use when changes need to land at fixed system paths (/etc/,
/usr/lib/systemd/, udev rule bodies, plymouth) that omarchy-dev-link
can't shadow.
Defaults:
packages omarchy-settings-dev omarchy-dev
path-to-checkout ~/Work/omarchy/omarchy-installer
Examples:
omarchy dev pkg-test
omarchy dev pkg-test omarchy-settings-dev
omarchy dev pkg-test omarchy-dev ~/Work/omarchy/omarchy-installer
The pkgver of the built package is tagged 'dev.<short-sha>[.dirty]' so
'pacman -Q' makes it obvious where the installed version came from.
PKGBUILDs are read from \${OMARCHY_PKGBUILDS_DIR:-~/Work/omarchy/omarchy-pkgs/pkgbuilds}/<package-name>/.
USAGE
exit 0
fi
remove_pkgver_function() {
local pkgbuild="$1"
local tmp="$pkgbuild.tmp"
awk '
/^pkgver\(\)[[:space:]]*\{/ {
in_pkgver = 1
depth = 0
}
in_pkgver {
line = $0
opens = gsub(/\{/, "{", line)
line = $0
closes = gsub(/\}/, "}", line)
depth += opens - closes
if (depth <= 0) {
in_pkgver = 0
}
next
}
{ print }
' "$pkgbuild" >"$tmp"
mv "$tmp" "$pkgbuild"
}
dev_package_name() {
local pkg="$1"
case "$pkg" in
omarchy | omarchy-settings)
printf '%s-dev\n' "$pkg"
;;
*)
printf '%s\n' "$pkg"
;;
esac
}
if (( $# == 0 )); then
PKGS=(omarchy-settings-dev omarchy-dev)
CHECKOUT="$HOME/Work/omarchy/omarchy-installer"
MAKEPKG_ARGS=()
else
PKGS=("$(dev_package_name "$1")")
CHECKOUT="${2:-$HOME/Work/omarchy/omarchy-installer}"
MAKEPKG_ARGS=("${@:3}")
fi
PKGBUILDS_ROOT="${OMARCHY_PKGBUILDS_DIR:-$HOME/Work/omarchy/omarchy-pkgs/pkgbuilds}"
if [[ ! -d "$CHECKOUT" ]]; then
echo "Error: checkout not found at $CHECKOUT" >&2
exit 1
fi
for PKG in "${PKGS[@]}"; do
PKGBUILD_DIR="$PKGBUILDS_ROOT/$PKG"
if [[ ! -f "$PKGBUILD_DIR/PKGBUILD" ]]; then
echo "Error: PKGBUILD not found at $PKGBUILD_DIR/PKGBUILD" >&2
echo " Pass a different package name as arg 1, or set OMARCHY_PKGBUILDS_DIR." >&2
exit 1
fi
done
build_dir=$(mktemp -d -t omarchy-dev-pkg-test.XXXXXX)
trap 'rm -rf "$build_dir"' EXIT
# pkgver=dev.<sha>[.dirty] so pacman -Q makes the source obvious.
short_sha=$(git -C "$CHECKOUT" rev-parse --short HEAD 2>/dev/null || echo "local")
dirty=""
if [[ -d "$CHECKOUT/.git" ]] && [[ -n "$(git -C "$CHECKOUT" status --porcelain)" ]]; then
dirty=".dirty"
fi
new_pkgver="dev.${short_sha}${dirty}"
for PKG in "${PKGS[@]}"; do
PKGBUILD_DIR="$PKGBUILDS_ROOT/$PKG"
package_build_dir="$build_dir/$PKG"
mkdir -p "$package_build_dir"
cp -a "$PKGBUILD_DIR/." "$package_build_dir/"
remove_pkgver_function "$package_build_dir/PKGBUILD"
sed -i "s/^pkgver=.*/pkgver=${new_pkgver}/" "$package_build_dir/PKGBUILD"
echo "Building $PKG ${new_pkgver} from $CHECKOUT"
echo " build dir: $package_build_dir"
echo " PKGBUILD : $PKGBUILD_DIR/PKGBUILD"
echo
(
cd "$package_build_dir"
OMARCHY_SRC="$CHECKOUT" makepkg -s --skipchecksums --noconfirm "${MAKEPKG_ARGS[@]}"
)
# Install separately so we can pass --overwrite='*' (makepkg -i can't).
# Dev builds frequently conflict with files left behind by previous
# script-installed Omarchy versions; the build is the authoritative state.
built_pkg=$(ls -t "$package_build_dir"/*.pkg.tar.* 2>/dev/null | grep -v '\.sig$' | head -1)
if [[ -z $built_pkg ]]; then
echo "Error: no built package found in $package_build_dir" >&2
exit 1
fi
sudo pacman -U --noconfirm --overwrite='*' "$built_pkg"
done
+51
View File
@@ -0,0 +1,51 @@
#!/bin/bash
# omarchy:summary=Show the current Omarchy dev-link state
# omarchy:group=dev
default_target="/usr/share/omarchy"
configured="$default_target"
conf_present=0
linked=0
if [[ -f /etc/omarchy.conf ]]; then
conf_present=1
configured=$(
OMARCHY_PATH=
# shellcheck disable=SC1091
. /etc/omarchy.conf
printf '%s' "${OMARCHY_PATH:-<empty>}"
)
if [[ $configured != "$default_target" ]]; then
linked=1
fi
fi
if (( linked )); then
echo "dev-link: ACTIVE"
echo " /etc/omarchy.conf -> OMARCHY_PATH=$configured"
else
echo "dev-link: inactive"
if (( conf_present )); then
echo " /etc/omarchy.conf -> OMARCHY_PATH=$configured (default guard)"
fi
fi
echo " current shell: OMARCHY_PATH=${OMARCHY_PATH:-<unset>}"
if (( linked )) && [[ ${OMARCHY_PATH:-} != "$configured" ]]; then
echo
echo "Note: this shell predates dev-link. Open a new shell to pick up the change,"
echo "or 'export OMARCHY_PATH=$configured' to update just this shell."
elif (( ! linked )) && [[ ${OMARCHY_PATH:-$default_target} != "$default_target" ]]; then
echo
echo "Note: no dev-link is configured, but this shell still has a stale OMARCHY_PATH."
echo "Open a new shell or run 'export OMARCHY_PATH=$default_target'."
fi
if command -v hyprctl >/dev/null 2>&1 && hyprctl version &>/dev/null; then
hypr_path=$(hyprctl getoption -j env 2>/dev/null | sed -n 's/.*OMARCHY_PATH=\([^"]*\).*/\1/p' | head -1)
if [[ -n "$hypr_path" ]]; then
echo " hyprland session: OMARCHY_PATH=$hypr_path"
fi
fi
+82
View File
@@ -0,0 +1,82 @@
#!/bin/bash
# omarchy:summary=Restore Omarchy to the package install (undo omarchy-dev-link)
# omarchy:group=dev
set -euo pipefail
if [[ $EUID -eq 0 ]]; then
echo "Error: run omarchy-dev-unlink as your user, not under sudo." >&2
exit 1
fi
if [[ ${1:-} == "-h" || ${1:-} == "--help" ]]; then
cat <<USAGE
Usage: omarchy dev unlink
Writes /etc/omarchy.conf defensively so OMARCHY_PATH resolves to
/usr/share/omarchy (the package install), even from stale session env.
Updates Hyprland/systemd session env and restarts omarchy-shell so live
state matches.
USAGE
exit 0
fi
default_target="/usr/share/omarchy"
linked=0
prior_target=""
if [[ -f /etc/omarchy.conf ]]; then
# Capture the path dev-link wrote BEFORE we reset the conf, so we know
# which bin/ to strip from PATH.
prior_target=$(sed -n 's/^[[:space:]]*export[[:space:]]\+OMARCHY_PATH="\?\([^"]*\)"\?/\1/p' /etc/omarchy.conf | tail -1)
if [[ $prior_target != "$default_target" ]]; then
linked=1
echo "Unlinking Omarchy from ${prior_target:-<empty>}"
else
echo "/etc/omarchy.conf already points at $default_target."
fi
elif [[ ${OMARCHY_PATH:-$default_target} != "$default_target" ]]; then
prior_target="$OMARCHY_PATH"
echo "Not currently linked: /etc/omarchy.conf is absent."
echo "This shell still has OMARCHY_PATH=$OMARCHY_PATH; writing the default guard."
else
echo "Not currently linked. Writing the default OMARCHY_PATH guard."
fi
printf 'export OMARCHY_PATH="%s"\n' "$default_target" | sudo tee /etc/omarchy.conf >/dev/null
echo "Set /etc/omarchy.conf -> OMARCHY_PATH=$default_target"
export OMARCHY_PATH="$default_target"
if [[ -n $prior_target && $prior_target != "$default_target" ]]; then
PATH=$(printf '%s' "$PATH" | tr ':' '\n' | awk -v drop="$prior_target/bin" '$0 != drop' | paste -sd:)
export PATH
fi
if command -v systemctl >/dev/null 2>&1; then
if systemctl --user import-environment OMARCHY_PATH PATH 2>/dev/null; then
echo " Updated systemd --user env."
fi
fi
if command -v hyprctl >/dev/null 2>&1 && hyprctl version &>/dev/null; then
hyprctl setenv OMARCHY_PATH "$default_target" >/dev/null
hyprctl setenv PATH "$PATH" >/dev/null
echo " Updated Hyprland session env."
if pgrep -x quickshell >/dev/null 2>&1; then
omarchy-restart-shell
echo " Restarted omarchy-shell."
fi
hyprctl reload >/dev/null
echo " Reloaded Hyprland config."
fi
echo
if (( linked )) || [[ -n $prior_target ]]; then
echo "Done. Existing shells still have the old OMARCHY_PATH until restarted."
echo "For this shell, run: export OMARCHY_PATH=$default_target"
else
echo "Done."
fi
+133
View File
@@ -0,0 +1,133 @@
#!/bin/bash
# omarchy:summary=Finalize Omarchy user setup (runtime tweaks /etc/skel can't do)
# omarchy:group=finalize
# omarchy:examples=omarchy finalize user | omarchy finalize user --force
set -euo pipefail
usage() {
cat <<USAGE
Usage: omarchy finalize user [--force] [--first-install]
Runs the per-user setup steps that /etc/skel can't seed:
dev-aware skill symlinks, xdg-user-dirs + gtk bookmarks (need \$HOME),
vconsole→hypr keyboard sync, default browser/mailto, and install/user/all.sh.
For shipped configs see /etc/skel (new users) and omarchy-reinstall-configs
(existing users explicitly resyncing).
--first-install is used by the ISO in the target chroot. It marks shipped
user migrations complete for the freshly-created user.
Idempotency marker: ~/.local/state/omarchy/finalize-user.done
USAGE
}
if (( EUID == 0 )); then
echo "Error: run omarchy-finalize-user as the user being configured, not as root." >&2
exit 1
fi
force=0
first_install=0
while (($#)); do
case "$1" in
--force)
force=1
shift
;;
--first-install)
first_install=1
force=1
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: $1" >&2
usage >&2
exit 1
;;
esac
done
state_dir="$HOME/.local/state/omarchy"
marker="$state_dir/finalize-user.done"
mkdir -p "$state_dir"
if [[ -f $marker && $force -eq 0 ]]; then
echo "User finalization already complete (rerun with --force to refresh)."
exit 0
fi
export OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}"
export OMARCHY_INSTALL="${OMARCHY_INSTALL:-$OMARCHY_PATH/install}"
export OMARCHY_SETUP_CONTEXT="${OMARCHY_SETUP_CONTEXT:-runtime}"
export PATH="$OMARCHY_PATH/bin:$PATH"
if (( first_install )); then
export OMARCHY_SETUP_CONTEXT=iso-chroot
fi
if [[ -n ${OMARCHY_INSTALL_LOG_FILE:-} && -f $OMARCHY_INSTALL/helpers/logging.sh ]]; then
source "$OMARCHY_INSTALL/helpers/logging.sh"
else
run_logged() {
local script="$1"
bash -eE -c 'source "$1"' bash "$script"
}
fi
# Dev-aware skill symlinks. Cannot live in /etc/skel because OMARCHY_PATH may
# point at a dev checkout (omarchy dev link) where the target differs.
mkdir -p ~/.agents/skills ~/.claude/skills ~/.codex/skills ~/.pi/agent/skills
ln -sfn "$OMARCHY_PATH/default/omarchy-skill" ~/.agents/skills/omarchy
ln -sfn "$OMARCHY_PATH/default/omarchy-skill" ~/.claude/skills/omarchy
ln -sfn "$OMARCHY_PATH/default/omarchy-skill" ~/.codex/skills/omarchy
ln -sfn "$OMARCHY_PATH/default/omarchy-skill" ~/.pi/agent/skills/omarchy
mkdir -p ~/Downloads ~/Pictures ~/Videos ~/.config/gtk-3.0
xdg-user-dirs-update --set TEMPLATES "$HOME"
xdg-user-dirs-update --set PUBLICSHARE "$HOME"
xdg-user-dirs-update --set DESKTOP "$HOME"
rmdir ~/Templates ~/Public ~/Desktop 2>/dev/null || true
touch ~/.config/gtk-3.0/bookmarks
for dir in Downloads Projects Pictures Videos; do
bookmark="file://$HOME/$dir $dir"
grep -qxF "$bookmark" ~/.config/gtk-3.0/bookmarks || echo "$bookmark" >>~/.config/gtk-3.0/bookmarks
done
conf=/etc/vconsole.conf
hyprlua="$HOME/.config/hypr/input.lua"
if [[ -f $conf && -f $hyprlua ]]; then
sed -i '/^[[:space:]]*kb_layout[[:space:]]*=/d' "$hyprlua"
sed -i '/^[[:space:]]*kb_variant[[:space:]]*=/d' "$hyprlua"
if grep -q '^XKBLAYOUT=' "$conf"; then
layout=$(grep '^XKBLAYOUT=' "$conf" | cut -d= -f2 | tr -d '"')
sed -i "/^[[:space:]]*kb_options *=/i\ kb_layout = \"$layout\"," "$hyprlua"
fi
if grep -q '^XKBVARIANT=' "$conf"; then
variant=$(grep '^XKBVARIANT=' "$conf" | cut -d= -f2 | tr -d '"')
sed -i "/^[[:space:]]*kb_options *=/i\ kb_variant = \"$variant\"," "$hyprlua"
fi
fi
source "$OMARCHY_INSTALL/user/all.sh"
omarchy-refresh-applications
xdg-settings set default-web-browser chromium.desktop
xdg-mime default HEY.desktop x-scheme-handler/mailto
if (( first_install )); then
mkdir -p "$state_dir/migrations/user"
for migration in "$OMARCHY_PATH"/migrations/user/*.sh; do
[[ -f $migration ]] && touch "$state_dir/migrations/user/$(basename "$migration")"
done
fi
touch "$marker"
echo "User finalization complete."
+126 -16
View File
@@ -1,25 +1,135 @@
#!/bin/bash
# omarchy:summary=Finish the installation of Omarchy with items that can only be done after logging in.
# omarchy:requires-sudo=true
# omarchy:summary=Finish first-login setup for Omarchy.
# omarchy:args=[--force]
set -e
FIRST_RUN_MODE=~/.local/state/omarchy/first-run.mode
usage() {
cat <<USAGE
Usage: omarchy-first-run [--force]
if [[ -f $FIRST_RUN_MODE ]]; then
rm -f "$FIRST_RUN_MODE"
Run first-login user setup and notification hooks. By default this only runs
once per user. Use --force to rerun the full sequence and refresh user setup.
USAGE
}
bash "$OMARCHY_PATH/install/first-run/recover-internal-monitor.sh"
bash "$OMARCHY_PATH/install/first-run/cleanup-reboot-sudoers.sh"
bash "$OMARCHY_PATH/install/first-run/firewall.sh"
bash "$OMARCHY_PATH/install/first-run/dns-resolver.sh"
bash "$OMARCHY_PATH/install/first-run/gnome-theme.sh"
bash "$OMARCHY_PATH/install/first-run/gdk-scale.sh"
bash "$OMARCHY_PATH/install/first-run/gtk-primary-paste.sh"
omarchy-hook-install post-update "$OMARCHY_PATH/install/first-run/install-voxtype.hook"
sudo /bin/rm -f /etc/sudoers.d/first-run
force=0
finalize_user_args=()
while (($#)); do
case "$1" in
--force)
force=1
finalize_user_args+=(--force)
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: $1" >&2
usage >&2
exit 1
;;
esac
done
bash "$OMARCHY_PATH/install/first-run/welcome.sh"
bash "$OMARCHY_PATH/install/first-run/wifi.sh"
omarchy-finalize-user "${finalize_user_args[@]}" || true
state_dir=~/.local/state/omarchy
mkdir -p "$state_dir"
FIRST_RUN_LOG="$state_dir/first-run.log"
first_run_failed=0
log_first_run() {
printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >>"$FIRST_RUN_LOG"
}
notification_server_ready() {
if command -v gdbus >/dev/null 2>&1; then
gdbus call --session \
--dest org.freedesktop.Notifications \
--object-path /org/freedesktop/Notifications \
--method org.freedesktop.Notifications.GetServerInformation >/dev/null 2>&1
elif command -v busctl >/dev/null 2>&1; then
busctl --user call \
org.freedesktop.Notifications \
/org/freedesktop/Notifications \
org.freedesktop.Notifications \
GetServerInformation >/dev/null 2>&1
else
return 0
fi
}
wait_for_notifications() {
command -v omarchy-shell >/dev/null || return 0
for _ in {1..100}; do
if omarchy-shell notifications ping >/dev/null 2>&1 && notification_server_ready; then
return 0
fi
sleep 0.1
done
log_first_run "Timed out waiting for notification service; continuing"
return 0
}
run_first_run_step() {
local name="$1"
shift
log_first_run "Starting: $name"
if "$@"; then
log_first_run "Completed: $name"
else
local status=$?
first_run_failed=1
log_first_run "Failed: $name (exit code: $status)"
fi
}
wait_for_notifications
MIGRATION_NOTIFY_WATCH_MARKER="$state_dir/user-migration-notify-watch-enabled"
if [[ ! -f $MIGRATION_NOTIFY_WATCH_MARKER || $force -eq 1 ]]; then
if systemctl --user enable --now omarchy-update-user-notify.path >/dev/null 2>&1; then
touch "$MIGRATION_NOTIFY_WATCH_MARKER"
fi
fi
run_first_run_step "notify about pending user migrations" omarchy-migrate-notify
USER_MARKER="$state_dir/first-run-user.done"
if [[ ! -f $USER_MARKER || $force -eq 1 ]]; then
run_first_run_step "install Voxtype post-update hook" \
omarchy-hook-install post-update "$OMARCHY_PATH/install/user/first-run/install-voxtype.hook"
run_first_run_step "enable user systemd units" \
bash "$OMARCHY_PATH/install/user/first-run/enable-user-units.sh"
run_first_run_step "set GNOME theme" \
bash "$OMARCHY_PATH/install/user/first-run/gnome-theme.sh"
run_first_run_step "set GTK primary paste" \
bash "$OMARCHY_PATH/install/user/first-run/gtk-primary-paste.sh"
wait_for_notifications
run_first_run_step "show welcome notification" \
bash "$OMARCHY_PATH/install/user/first-run/welcome.sh"
# The first-run notification scripts register action callbacks in background
# notify-send processes. Give the notification server a tick to ingest the
# welcome toast before queueing the Wi-Fi/update toasts.
sleep 0.3
run_first_run_step "show Wi-Fi/update notifications" \
bash "$OMARCHY_PATH/install/user/first-run/wifi.sh"
if (( first_run_failed == 0 )); then
touch "$USER_MARKER"
else
log_first_run "One or more first-run steps failed; first-run will retry next login"
fi
else
echo "First-run already complete (rerun with --force to refresh)."
fi
+73 -36
View File
@@ -4,50 +4,87 @@
# omarchy:args=<font-name>
# omarchy:examples=omarchy font list | omarchy font set "CaskaydiaMono Nerd Font"
font_name="$1"
usage() {
echo "Usage: omarchy-font-set <font-name>"
}
if [[ -n $font_name ]]; then
if fc-list | grep -iq "$font_name"; then
if [[ -f ~/.config/alacritty/alacritty.toml ]]; then
sed -i "s/family = \".*\"/family = \"$font_name\"/g" ~/.config/alacritty/alacritty.toml
fi
font_name="${1:-}"
omarchy_root="${OMARCHY_PATH:-/usr/share/omarchy}"
if [[ -f ~/.config/kitty/kitty.conf ]]; then
sed -i "s/^font_family .*/font_family $font_name/g" ~/.config/kitty/kitty.conf
pkill -USR1 kitty
fi
case "$font_name" in
-h|--help)
usage
exit 0
;;
"")
usage >&2
exit 1
;;
esac
if [[ -f ~/.config/ghostty/config ]]; then
sed -i "s/font-family = \".*\"/font-family = \"$font_name\"/g" ~/.config/ghostty/config
pkill -SIGUSR2 ghostty
fi
if ! fc-list | grep -Fqi -- "$font_name"; then
echo "Font '$font_name' not found."
exit 1
fi
if [[ -f ~/.config/foot/foot.ini ]]; then
sed -i "s/^font=.*/font=$font_name:size=9/g" ~/.config/foot/foot.ini
fi
if [[ -f ~/.config/alacritty/alacritty.toml ]]; then
sed -i "s/family = \".*\"/family = \"$font_name\"/g" ~/.config/alacritty/alacritty.toml
fi
# fontconfig is the canonical source of truth — the omarchy shell, Qt
# apps, and anything else that resolves "monospace" all read from here.
xmlstarlet ed -L \
-u '//match[@target="pattern"][test/string="monospace"]/edit[@name="family"]/string' \
-v "$font_name" \
~/.config/fontconfig/fonts.conf
if [[ -f ~/.config/kitty/kitty.conf ]]; then
sed -i "s/^font_family .*/font_family $font_name/g" ~/.config/kitty/kitty.conf
pkill -USR1 kitty
fi
omarchy-restart-shell
if [[ -f ~/.config/ghostty/config ]]; then
sed -i "s/font-family = \".*\"/font-family = \"$font_name\"/g" ~/.config/ghostty/config
pkill -SIGUSR2 ghostty
fi
if pgrep -x ghostty; then
omarchy-notification-send -g  "You must restart Ghostty to see font change"
fi
if [[ -f ~/.config/foot/foot.ini ]]; then
sed -i "s/^font=.*/font=$font_name:size=9/g" ~/.config/foot/foot.ini
fi
if pgrep -x foot; then
omarchy-notification-send -g  "You must restart Foot to see font change"
fi
omarchy-hook font-set "$font_name"
else
echo "Font '$font_name' not found."
# fontconfig is the canonical source of truth — the omarchy shell, Qt apps,
# and anything resolving "monospace" all read from here. The shipped default
# is package-owned; create a user override only when the user changes fonts.
fontconfig_file="$HOME/.config/fontconfig/fonts.conf"
if [[ ! -f $fontconfig_file ]]; then
fontconfig_default="$omarchy_root/default/fontconfig/conf.avail/50-omarchy.conf"
if [[ ! -f $fontconfig_default ]]; then
echo "Default fontconfig file not found: $fontconfig_default" >&2
exit 1
fi
else
echo "Usage: omarchy-font-set <font-name>"
mkdir -p "$(dirname "$fontconfig_file")"
cp "$fontconfig_default" "$fontconfig_file"
fi
# We own the markup in 50-omarchy.conf, so the monospace block is predictable:
# the <string>FAMILY</string> immediately after <string>monospace</string> is
# the family we're replacing.
tmp=$(mktemp)
if ! awk -v new_font="$font_name" '
in_mono && /<string>[^<]*<\/string>/ {
sub(/<string>[^<]*<\/string>/, "<string>" new_font "</string>")
in_mono = 0
}
/<string>monospace<\/string>/ { in_mono = 1 }
{ print }
' "$fontconfig_file" >"$tmp"; then
rm -f "$tmp"
echo "Failed to update $fontconfig_file" >&2
exit 1
fi
mv "$tmp" "$fontconfig_file"
omarchy-restart-shell
if pgrep -x ghostty; then
omarchy-notification-send -g "You must restart Ghostty to see font change"
fi
if pgrep -x foot; then
omarchy-notification-send -g "You must restart Foot to see font change"
fi
omarchy-hook font-set "$font_name"
+2 -6
View File
@@ -51,11 +51,7 @@ desktop_name="$game_name"
desktop_id=$(printf '%s' "$desktop_name" | tr '[:upper:]' '[:lower:]' | tr -cs '[:alnum:]' '-' | sed 's/^-//; s/-$//')
desktop_dir="$HOME/.local/share/applications"
desktop_file="$desktop_dir/$desktop_id.desktop"
icon_dir="$desktop_dir/icons"
icon_path="$icon_dir/Retro Gaming.png"
mkdir -p "$desktop_dir" "$icon_dir"
[[ -f $icon_path ]] || cp "$HOME/.local/share/omarchy/applications/icons/Retro Gaming.png" "$icon_path"
mkdir -p "$desktop_dir"
cat >"$desktop_file" <<EOF
[Desktop Entry]
@@ -65,7 +61,7 @@ Comment=Play $game_name with RetroArch
Exec=retroarch -L "$core_path" "$game_path"
Terminal=false
Type=Application
Icon=$icon_path
Icon=retro-gaming
StartupNotify=true
Categories=Game;Emulator;
EOF
+3 -4
View File
@@ -38,8 +38,9 @@ if [[ -f $MKINITCPIO_CONF ]] && grep -q "^HOOKS+=(resume)$" "$MKINITCPIO_CONF";
if [[ -n $RESUME_OFFSET ]]; then
echo "Fixing empty resume_offset ($RESUME_OFFSET)"
sudo sed -i "s/resume_offset=\"$/resume_offset=$RESUME_OFFSET\"/" "$RESUME_DROP_IN"
sudo sed -i "s/resume_offset=\"$/resume_offset=$RESUME_OFFSET\"/" /etc/default/limine
$NO_REBUILD || sudo limine-mkinitcpio
if ! $NO_REBUILD; then
sudo limine-mkinitcpio
fi
fi
fi
echo "Hibernation is already set up"
@@ -100,7 +101,6 @@ if [[ ! -f $RESUME_DROP_IN ]]; then
if [[ -n $RESUME_OFFSET ]]; then
sudo mkdir -p /etc/limine-entry-tool.d
echo "KERNEL_CMDLINE[default]+=\" resume=$RESUME_DEVICE resume_offset=$RESUME_OFFSET\"" | sudo tee "$RESUME_DROP_IN" >/dev/null
sudo tee -a /etc/default/limine < "$RESUME_DROP_IN" >/dev/null
else
echo "Warning: Could not determine resume offset for $SWAP_FILE" >&2
fi
@@ -113,7 +113,6 @@ if grep -q "\[s2idle\]" /sys/power/mem_sleep 2>/dev/null; then
echo "Enabling ACPI RTC alarm for s2idle suspend"
sudo mkdir -p /etc/limine-entry-tool.d
echo 'KERNEL_CMDLINE[default]+=" rtc_cmos.use_acpi_alarm=1"' | sudo tee "$LIMINE_DROP_IN" >/dev/null
sudo tee -a /etc/default/limine < "$LIMINE_DROP_IN" >/dev/null
fi
fi
+1 -1
View File
@@ -67,7 +67,7 @@ brave-origin)
setup_policy_directory /etc/brave/policies/managed
mkdir -p ~/.config
# FIXME: Use normal chromium flags when Brave Origin wrapper has been fixed
echo "--load-extension=~/.local/share/omarchy/default/chromium/extensions/copy-url,~/.local/share/omarchy/default/chromium/extensions/yt-dlp" > ~/.config/brave-origin-beta-flags.conf
echo "--load-extension=/usr/share/omarchy/default/chromium/extensions/copy-url,/usr/share/omarchy/default/chromium/extensions/yt-dlp" > ~/.config/brave-origin-beta-flags.conf
omarchy-install-chromium-ytdlp
omarchy-theme-set-browser
announce_browser_installed "Brave Origin"
+2 -5
View File
@@ -63,12 +63,9 @@ EOF
launched_installer=1
fi
mkdir -p "$HOME/.local/share/applications" "$HOME/.local/share/icons/hicolor/48x48/apps"
install -m 644 "$HOME/.local/share/omarchy/applications/battlenet.desktop" \
mkdir -p "$HOME/.local/share/applications"
install -m 644 "$OMARCHY_PATH/applications/battlenet.desktop" \
"$HOME/.local/share/applications/battlenet.desktop"
install -m 644 "$HOME/.local/share/omarchy/applications/icons/Battle.net.png" \
"$HOME/.local/share/icons/hicolor/48x48/apps/Battle.net.png"
gtk-update-icon-cache "$HOME/.local/share/icons/hicolor" &>/dev/null || true
update-desktop-database "$HOME/.local/share/applications" 2>/dev/null || true
if (( launched_installer )); then
+1 -5
View File
@@ -13,8 +13,6 @@ SUNSHINE_ADMIN_APP="Sunshine Admin"
SUNSHINE_ADMIN_URL="https://localhost:47990"
SUNSHINE_ADMIN_EXEC="omarchy-launch-webapp $SUNSHINE_ADMIN_URL --ignore-certificate-errors"
SUNSHINE_ICON_SOURCE="/usr/share/sunshine/web/images/logo-sunshine-45.png"
SUNSHINE_ICON_NAME="Sunshine Admin.png"
WEBAPP_ICON_DIR="$HOME/.local/share/applications/icons"
HYPR_AUTOSTART_FILE="$HOME/.config/hypr/autostart.lua"
HYPR_AUTOSTART_ENTRY='o.launch_on_start("sunshine")'
@@ -59,9 +57,7 @@ open_ufw_ports() {
}
install_admin_webapp() {
mkdir -p "$WEBAPP_ICON_DIR"
cp "$SUNSHINE_ICON_SOURCE" "$WEBAPP_ICON_DIR/$SUNSHINE_ICON_NAME"
omarchy-webapp-install "$SUNSHINE_ADMIN_APP" "$SUNSHINE_ADMIN_URL" "$SUNSHINE_ICON_NAME" "$SUNSHINE_ADMIN_EXEC"
omarchy-webapp-install "$SUNSHINE_ADMIN_APP" "$SUNSHINE_ADMIN_URL" "$SUNSHINE_ICON_SOURCE" "$SUNSHINE_ADMIN_EXEC"
}
enable_hyprland_autostart() {
+2 -2
View File
@@ -32,10 +32,10 @@ for m in $(hyprctl monitors -j | jq -r '.[] | .name'); do
case $terminal in
*Alacritty*)
hypr_exec "alacritty --class=org.omarchy.screensaver --config-file ~/.local/share/omarchy/default/alacritty/screensaver.toml -e omarchy-screensaver"
hypr_exec "alacritty --class=org.omarchy.screensaver --config-file $OMARCHY_PATH/default/alacritty/screensaver.toml -e omarchy-screensaver"
;;
*ghostty*)
hypr_exec "ghostty --class=org.omarchy.screensaver --config-file=~/.local/share/omarchy/default/ghostty/screensaver --font-size=18 -e omarchy-screensaver"
hypr_exec "ghostty --class=org.omarchy.screensaver --config-file=$OMARCHY_PATH/default/ghostty/screensaver --font-size=18 -e omarchy-screensaver"
;;
*foot*)
hypr_exec "foot --app-id=org.omarchy.screensaver --config=\"$OMARCHY_PATH/default/foot/screensaver.ini\" -e omarchy-screensaver"
+89 -20
View File
@@ -1,28 +1,97 @@
#!/bin/bash
# omarchy:summary=Run all pending migrations to bring the system in line with the installed version.
# omarchy:summary=Run pending Omarchy system and user migrations.
# omarchy:args=[--pending [all|system|user]]
STATE_DIR="$HOME/.local/state/omarchy/migrations"
mkdir -p "$STATE_DIR"
set -euo pipefail
# Skipped migrations are tracked separately
mkdir -p "$STATE_DIR/skipped"
mode="run"
pending_scope="all"
# Run any pending migrations
for file in $OMARCHY_PATH/migrations/*.sh; do
filename=$(basename "$file")
usage() {
echo "Usage: omarchy-migrate [--pending [all|system|user]]"
}
if [[ ! -f $STATE_DIR/$filename && ! -f $STATE_DIR/skipped/$filename ]]; then
echo -e "\e[32m\nRunning migration (${filename%.sh})\e[0m"
if bash $file; then
touch "$STATE_DIR/$filename"
else
if gum confirm "Migration ${filename%.sh} failed. Skip and continue?"; then
touch "$STATE_DIR/skipped/$filename"
else
exit 1
while (($#)); do
case "$1" in
--pending|--check)
mode="pending"
shift
if [[ ${1:-} == "all" || ${1:-} == "system" || ${1:-} == "user" ]]; then
pending_scope="$1"
shift
fi
fi
fi
;;
--pending=all|--pending=system|--pending=user)
mode="pending"
pending_scope="${1#--pending=}"
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done
pending_output=""
append_pending() {
local scope="$1"
local command="$2"
local output=""
local migration=""
if output=$("$command" --pending 2>/dev/null); then
while IFS= read -r migration; do
[[ -n $migration ]] || continue
pending_output+="$scope/$migration"$'\n'
done <<<"$output"
fi
}
if [[ $mode == "pending" ]]; then
case "$pending_scope" in
all)
append_pending system omarchy-migrate-system
append_pending user omarchy-migrate-user
;;
system)
append_pending system omarchy-migrate-system
;;
user)
append_pending user omarchy-migrate-user
;;
esac
if [[ -n $pending_output ]]; then
printf '%s' "$pending_output"
exit 0
else
exit 1
fi
fi
wait_for_pacman_transaction() {
local lock_file=/var/lib/pacman/db.lck
[[ -e $lock_file ]] || return 0
echo "Waiting for pacman transaction to finish before running Omarchy migrations..."
for _ in {1..900}; do
[[ -e $lock_file ]] || return 0
sleep 1
done
echo "Pacman transaction is still running; Omarchy migrations will retry on next login."
exit 0
}
wait_for_pacman_transaction
omarchy-migrate-system
omarchy-migrate-user
+35
View File
@@ -0,0 +1,35 @@
#!/bin/bash
# omarchy:summary=Notify the user when Omarchy has pending user migrations
set -euo pipefail
pending_migrations=$(omarchy-migrate --pending user 2>/dev/null) || exit 0
pending_count=$(printf '%s\n' "$pending_migrations" | sed '/^[[:space:]]*$/d' | wc -l)
if (( pending_count == 1 )); then
message="1 new Omarchy user migration is available. Click to run it in a terminal."
else
message="$pending_count new Omarchy user migrations are available. Click to run them in a terminal."
fi
notify_command=$(printf 'if [[ -n $(omarchy-notification-send -u critical -g  "Run Omarchy Migrations" %q -a) ]]; then omarchy-launch-floating-terminal-with-presentation omarchy-migrate; fi' "$message")
if command -v systemd-run >/dev/null 2>&1; then
unit="omarchy-migrations-notification-$(date +%Y%m%d%H%M%S)"
systemd-run --user --scope --unit="$unit" bash -lc "$notify_command" >/dev/null 2>&1 && exit 0
fi
print_pending_migrations() {
echo "Omarchy has pending user migrations. Run omarchy-migrate in a terminal to apply them:"
while IFS= read -r migration; do
[[ -n $migration ]] || continue
printf ' %s\n' "$migration"
done <<<"$pending_migrations"
}
if [[ -t 1 ]]; then
print_pending_migrations
else
print_pending_migrations >&2
fi
+74
View File
@@ -0,0 +1,74 @@
#!/bin/bash
# omarchy:summary=Run pending Omarchy system migrations as root.
# omarchy:args=[--pending]
# omarchy:requires-sudo=true
set -euo pipefail
mode="run"
while (($#)); do
case "$1" in
--pending|--check)
mode="pending"
shift
;;
-h|--help)
echo "Usage: omarchy-migrate-system [--pending]"
exit 0
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done
OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}"
STATE_DIR="${OMARCHY_SYSTEM_MIGRATION_STATE:-/var/lib/omarchy/migrations/system}"
MIGRATIONS_DIR="$OMARCHY_PATH/migrations/system"
pending_migrations() {
[[ -d $MIGRATIONS_DIR ]] || return 0
for file in "$MIGRATIONS_DIR"/*.sh; do
[[ -f $file ]] || continue
filename=$(basename "$file")
if [[ ! -f $STATE_DIR/$filename ]]; then
printf '%s\n' "$filename"
fi
done
}
if [[ $mode == "pending" ]]; then
pending_output=$(pending_migrations)
if [[ -n $pending_output ]]; then
printf '%s\n' "$pending_output"
exit 0
else
exit 1
fi
fi
if (( EUID != 0 )) && [[ -z ${OMARCHY_SYSTEM_MIGRATION_STATE:-} ]]; then
if ! "$0" --pending >/dev/null; then
exit 0
fi
exec sudo --preserve-env=OMARCHY_PATH "$0" "$@"
fi
mkdir -p "$STATE_DIR"
[[ -d $MIGRATIONS_DIR ]] || exit 0
for file in "$MIGRATIONS_DIR"/*.sh; do
[[ -f $file ]] || continue
filename=$(basename "$file")
if [[ ! -f $STATE_DIR/$filename ]]; then
echo -e "\e[32m\nRunning system migration (${filename%.sh})\e[0m"
OMARCHY_PATH="$OMARCHY_PATH" bash -euo pipefail "$file"
touch "$STATE_DIR/$filename"
fi
done
+65
View File
@@ -0,0 +1,65 @@
#!/bin/bash
# omarchy:summary=Run pending Omarchy migrations for the current user.
# omarchy:args=[--pending]
set -euo pipefail
mode="run"
while (($#)); do
case "$1" in
--pending|--check)
mode="pending"
shift
;;
-h|--help)
echo "Usage: omarchy-migrate-user [--pending]"
exit 0
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done
OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}"
STATE_DIR="${OMARCHY_USER_MIGRATION_STATE:-$HOME/.local/state/omarchy/migrations/user}"
MIGRATIONS_DIR="$OMARCHY_PATH/migrations/user"
pending_migrations() {
[[ -d $MIGRATIONS_DIR ]] || return 0
for file in "$MIGRATIONS_DIR"/*.sh; do
[[ -f $file ]] || continue
filename=$(basename "$file")
if [[ ! -f $STATE_DIR/$filename ]]; then
printf '%s\n' "$filename"
fi
done
}
if [[ $mode == "pending" ]]; then
pending_output=$(pending_migrations)
if [[ -n $pending_output ]]; then
printf '%s\n' "$pending_output"
exit 0
else
exit 1
fi
fi
mkdir -p "$STATE_DIR"
[[ -d $MIGRATIONS_DIR ]] || exit 0
for file in "$MIGRATIONS_DIR"/*.sh; do
[[ -f $file ]] || continue
filename=$(basename "$file")
if [[ ! -f $STATE_DIR/$filename ]]; then
echo -e "\e[32m\nRunning user migration (${filename%.sh})\e[0m"
OMARCHY_PATH="$OMARCHY_PATH" bash -euo pipefail "$file"
touch "$STATE_DIR/$filename"
fi
done
+5 -1
View File
@@ -6,7 +6,11 @@
# omarchy:requires-sudo=true
if omarchy-pkg-missing "$@"; then
sudo pacman -S --noconfirm --needed "$@" || exit 1
if (( EUID == 0 )); then
pacman -S --noconfirm --needed "$@" || exit 1
else
sudo pacman -S --noconfirm --needed "$@" || exit 1
fi
fi
for pkg in "$@"; do
+1 -1
View File
@@ -35,7 +35,7 @@ fi
staging_dir=$(mktemp -d)
trap 'rm -rf "$staging_dir"' EXIT
find ~/.local/share/omarchy/default/plymouth -maxdepth 1 -type f -exec cp -t "$staging_dir/" {} +
find $OMARCHY_PATH/default/plymouth -maxdepth 1 -type f -exec cp -t "$staging_dir/" {} +
cp "$logo_path" "$staging_dir/logo.png"
for asset in bullet.png entry.png lock.png; do
+1 -1
View File
@@ -5,7 +5,7 @@
theme_dir="/usr/share/plymouth/themes/omarchy"
sudo find ~/.local/share/omarchy/default/plymouth -maxdepth 1 -type f -exec cp -t "$theme_dir/" {} +
sudo find $OMARCHY_PATH/default/plymouth -maxdepth 1 -type f -exec cp -t "$theme_dir/" {} +
sudo plymouth-set-default-theme omarchy
if omarchy-cmd-present limine-mkinitcpio; then
+2 -2
View File
@@ -42,7 +42,7 @@ theme_dir="/usr/share/plymouth/themes/omarchy"
staging_dir=$(mktemp -d)
trap 'rm -rf "$staging_dir"' EXIT
find ~/.local/share/omarchy/default/plymouth -maxdepth 1 -type f -exec cp -t "$staging_dir/" {} +
find $OMARCHY_PATH/default/plymouth -maxdepth 1 -type f -exec cp -t "$staging_dir/" {} +
cp "$logo_path" "$staging_dir/logo.png"
sed -i \
@@ -65,7 +65,7 @@ fi
# Sync the SDDM login screen with the same colors and logo.
sddm_dir="/usr/share/sddm/themes/omarchy"
sddm_template="$HOME/.local/share/omarchy/default/sddm/omarchy/Main.qml"
sddm_template="$OMARCHY_PATH/default/sddm/omarchy/Main.qml"
sed \
-e "s/#1a1b26/#$bg_hex/g" \
+4 -10
View File
@@ -1,10 +1,6 @@
#!/bin/bash
# omarchy:summary=Ensure all default .desktop, web apps, TUIs, and mise wrappers are installed.
mkdir -p ~/.local/share/icons/hicolor/48x48/apps/
cp "$OMARCHY_PATH"/applications/icons/*.png ~/.local/share/icons/hicolor/48x48/apps/
gtk-update-icon-cache ~/.local/share/icons/hicolor &>/dev/null
# omarchy:summary=Ensure default application launchers and mise wrappers are installed.
# Copy .desktop declarations
mkdir -p ~/.local/share/applications
@@ -14,10 +10,8 @@ if omarchy-cmd-present alacritty; then
cp "$OMARCHY_PATH/default/alacritty/Alacritty.desktop" ~/.local/share/applications/
fi
# Refresh the webapps, TUIs, and mise wrappers
bash "$OMARCHY_PATH/install/packaging/icons.sh"
bash "$OMARCHY_PATH/install/packaging/webapps.sh"
bash "$OMARCHY_PATH/install/packaging/tuis.sh"
bash "$OMARCHY_PATH/install/packaging/mise.sh"
if [[ -f "$OMARCHY_PATH/install/user/mise.sh" ]]; then
bash "$OMARCHY_PATH/install/user/mise.sh"
fi
update-desktop-database ~/.local/share/applications
+13 -14
View File
@@ -1,37 +1,37 @@
#!/bin/bash
# omarchy:summary=Copies the named config from ~/.local/share/omarchy/config/X/Y/Z -> ~/.config/X/Y/Z.
# omarchy:summary=Copy a shipped user config from /etc/skel/.config into ~/.config (backs up your version).
# omarchy:args=<config-path>
config_file=$1
config_file=${1:-}
if [[ -z $config_file ]]; then
cat <<USAGE
Usage: $0 [config_file]
Must provide a file path from the .config directory to be refreshed.
To copy ~/.local/share/omarchy/config/hypr/hyprland.lua to ~/.config/hypr/hyprland.lua
Must provide a file path relative to .config to be refreshed.
To copy /etc/skel/.config/hypr/hyprland.lua to ~/.config/hypr/hyprland.lua:
$0 hypr/hyprland.lua
USAGE
exit 1
fi
# Backup the destination file (with timestamp) to avoid clobbering (Ex: hyprland.lua.bak.1753817951)
user_config_file="${HOME}/.config/$config_file"
default_config_file="$OMARCHY_PATH/config/$config_file"
default_config_file="/etc/skel/.config/$config_file"
backup_config_file="$user_config_file.bak.$(date +%s)"
if [[ ! -e $default_config_file ]]; then
echo "Not a shipped user config: $config_file" >&2
exit 1
fi
mkdir -p "$(dirname "$user_config_file")"
if [[ -f $user_config_file ]]; then
# Create preliminary backup
cp -f "$user_config_file" "$backup_config_file" 2>/dev/null
cp -f "$user_config_file" "$backup_config_file"
cp -f "$default_config_file" "$user_config_file"
# Replace config with new default
cp -f "$default_config_file" "$user_config_file" 2>/dev/null
# Compare and delete/inform accordingly
if cmp -s "$user_config_file" "$backup_config_file"; then
rm "$backup_config_file"
else
@@ -39,6 +39,5 @@ if [[ -f $user_config_file ]]; then
diff "$user_config_file" "$backup_config_file" || true
fi
else
# Config file did not exist already
cp -f "$default_config_file" "$user_config_file" 2>/dev/null
cp -f "$default_config_file" "$user_config_file"
fi
-5
View File
@@ -1,5 +0,0 @@
#!/bin/bash
# omarchy:summary=Overwrite the user config for fastfetch with the Omarchy default.
omarchy-refresh-config fastfetch/config.jsonc
+20 -2
View File
@@ -9,5 +9,23 @@ omarchy-refresh-config hypr/input.lua
omarchy-refresh-config hypr/looknfeel.lua
omarchy-refresh-config hypr/hyprland.lua
omarchy-refresh-config hypr/monitors.lua
bash "$OMARCHY_PATH/install/config/omarchy-toggles.sh"
bash "$OMARCHY_PATH/install/config/detect-keyboard-layout.sh"
mkdir -p ~/.local/state/omarchy/toggles/hypr
cp "$OMARCHY_PATH/default/hypr/toggles/flags.lua" ~/.local/state/omarchy/toggles/hypr/
conf=/etc/vconsole.conf
hyprlua="$HOME/.config/hypr/input.lua"
if [[ -f $conf && -f $hyprlua ]]; then
sed -i '/^[[:space:]]*kb_layout[[:space:]]*=/d' "$hyprlua"
sed -i '/^[[:space:]]*kb_variant[[:space:]]*=/d' "$hyprlua"
if grep -q '^XKBLAYOUT=' "$conf"; then
layout=$(grep '^XKBLAYOUT=' "$conf" | cut -d= -f2 | tr -d '"')
sed -i "/^[[:space:]]*kb_options *=/i\ kb_layout = \"$layout\"," "$hyprlua"
fi
if grep -q '^XKBVARIANT=' "$conf"; then
variant=$(grep '^XKBVARIANT=' "$conf" | cut -d= -f2 | tr -d '"')
sed -i "/^[[:space:]]*kb_options *=/i\ kb_variant = \"$variant\"," "$hyprlua"
fi
fi
+1 -1
View File
@@ -11,7 +11,7 @@ echo "Resetting limine config"
sudo mv /boot/limine.conf /boot/limine.conf.bak
sudo cp ~/.local/share/omarchy/default/limine/limine.conf /boot/limine.conf
sudo cp $OMARCHY_PATH/default/limine/limine.conf /boot/limine.conf
sudo limine-update
sudo limine-snapper-sync
+1 -1
View File
@@ -23,4 +23,4 @@ sudo cp -f "$OMARCHY_PATH/default/pacman/mirrorlist-$channel" /etc/pacman.d/mirr
omarchy-hook pre-refresh-pacman
# Reset all package DBs and then update
sudo pacman -Syyuu --noconfirm
sudo env OMARCHY_UPDATE_PACMAN=1 pacman -Syyuu --noconfirm
+1 -1
View File
@@ -3,7 +3,7 @@
# omarchy:summary=Overwrite the user config for the Plymouth drive decryption and boot sequence with the Omarchy default and rebuild it.
# omarchy:requires-sudo=true
sudo cp -r ~/.local/share/omarchy/default/plymouth/* /usr/share/plymouth/themes/omarchy/
sudo cp -r $OMARCHY_PATH/default/plymouth/* /usr/share/plymouth/themes/omarchy/
sudo plymouth-set-default-theme omarchy
if command -v limine-mkinitcpio &>/dev/null; then
+2 -5
View File
@@ -5,12 +5,9 @@
set -e
# Attempt to reinstall all default Omarchy packages and reset all the default configs.
echo -e "This will reinstall all default Omarchy packages and reset default configs.\nWarning: user config changes will be overwritten.\n"
echo -e "This will reinstall all the default Omarchy packages and reset all default configs.\nWarning: All user changes to configs will be lost.\n"
if gum confirm "Are you sure you want to reinstall and lose all config changes?"; then
omarchy-reinstall-git
if gum confirm "Are you sure you want to reinstall and lose config changes?"; then
omarchy-reinstall-pkgs
omarchy-reinstall-configs
+15 -11
View File
@@ -1,24 +1,28 @@
#!/bin/bash
# omarchy:summary=Reset all Omarchy user configs to the defaults
# omarchy:requires-sudo=true
# omarchy:summary=Reset Omarchy user configs and shipped defaults in $HOME (destructive)
set -e
# Overwrite all user configs with the Omarchy defaults.
set -euo pipefail
if (( EUID == 0 )); then
echo "Error: This script should not be run as root"
exit 1
fi
echo "Resetting all Omarchy configs"
cp -R ~/.local/share/omarchy/config/* ~/.config/
cp ~/.local/share/omarchy/default/bashrc ~/.bashrc
echo '[[ -f ~/.bashrc ]] && . ~/.bashrc' | tee ~/.bash_profile >/dev/null
echo "Resetting Omarchy user configs to shipped defaults..."
$(bash $OMARCHY_PATH/install/config/theme.sh)
# /etc/skel is the same tree useradd -m copies to seed a fresh user's $HOME.
# Replaying it over an existing user resyncs every package-shipped user
# default in one pass: .bashrc, .config/**, .local/share/applications,
# nautilus-python extensions, branding, hypr toggles, and migration markers.
# Trailing dot copies dotfiles; the shell wouldn't glob them with /etc/skel/*.
cp -af /etc/skel/. ~/
omarchy-refresh-limine
omarchy-refresh-plymouth
omarchy-nvim-setup
if omarchy-cmd-present omarchy-nvim-refresh; then
omarchy-nvim-refresh
elif omarchy-cmd-present omarchy-nvim-setup; then
omarchy-nvim-setup --force
fi
-11
View File
@@ -1,11 +0,0 @@
#!/bin/bash
# omarchy:summary=Reinstall the stable Omarchy source directory from git
set -e
# Reinstall the Omarchy configuration directory from the git source.
git clone --depth=1 --branch master "https://github.com/basecamp/omarchy.git" ~/.local/share/omarchy-new >/dev/null
mv $OMARCHY_PATH ~/.local/share/omarchy-old
mv ~/.local/share/omarchy-new $OMARCHY_PATH
+2 -2
View File
@@ -11,8 +11,8 @@ set -e
omarchy-refresh-pacman
# Downgrade any packages to the stable setup
sudo pacman -Suu --noconfirm
sudo env OMARCHY_UPDATE_PACMAN=1 pacman -Suu --noconfirm
# Ensure all packages are installed
mapfile -t packages < <(grep -v '^#' "$OMARCHY_PATH/install/omarchy-base.packages" | grep -v '^$')
sudo pacman -Syu --noconfirm --needed "${packages[@]}"
sudo env OMARCHY_UPDATE_PACMAN=1 pacman -Syu --noconfirm --needed "${packages[@]}"
-2
View File
@@ -12,9 +12,7 @@ sleep 1
rm -rf "$PREFIX"
rm -f "$HOME/.local/share/applications/battlenet.desktop"
rm -f "$HOME/.local/share/icons/hicolor/48x48/apps/Battle.net.png"
rm -f "$HOME/.cache/omarchy/Battle.net-Setup.exe"
gtk-update-icon-cache "$HOME/.local/share/icons/hicolor" &>/dev/null || true
update-desktop-database "$HOME/.local/share/applications" 2>/dev/null || true
echo
-1
View File
@@ -24,7 +24,6 @@ if gum confirm "Are you sure you want to remove all preinstalled web apps, TUI w
spotify \
libreoffice-fresh \
1password \
1password-beta \
1password-cli \
xournalpp \
signal-desktop \
+14 -2
View File
@@ -3,9 +3,21 @@
# omarchy:summary=Restart the Omarchy shell
# omarchy:examples=omarchy restart shell
CONFIG_DIR="$OMARCHY_PATH/shell"
omarchy_root="${OMARCHY_PATH:-/usr/share/omarchy}"
if [[ ! -f $omarchy_root/shell/shell.qml && -f /usr/share/omarchy/shell/shell.qml ]]; then
omarchy_root=/usr/share/omarchy
fi
if [[ $(omarchy-shell lock isLocked 2>/dev/null || true) == "true" ]]; then
CONFIG_DIR="$omarchy_root/shell"
[[ -f $CONFIG_DIR/shell.qml ]] || { echo "Omarchy shell config not found: $CONFIG_DIR" >&2; exit 1; }
export OMARCHY_PATH="$omarchy_root"
export PATH="$omarchy_root/bin:/usr/local/bin:/usr/bin:/bin:$PATH"
omarchy_shell_bin=/usr/bin/omarchy-shell
[[ -x $omarchy_shell_bin ]] || omarchy_shell_bin=omarchy-shell
if [[ $("$omarchy_shell_bin" lock isLocked 2>/dev/null || true) == "true" ]]; then
echo "Refusing to restart Omarchy shell while the session is locked." >&2
exit 1
fi
+61
View File
@@ -0,0 +1,61 @@
#!/bin/bash
# omarchy:summary=Apply Omarchy hardware-specific packages and system configuration
# omarchy:group=setup
# omarchy:requires-sudo=true
# omarchy:examples=omarchy setup hardware --install-user dhh
set -euo pipefail
usage() {
cat <<USAGE
Usage: omarchy setup hardware --install-user USER
Runs idempotent hardware detection/setup for the installed machine. This is
called by omarchy-setup-system during ISO finalization and can be rerun later
for diagnostics or after hardware/package updates.
USAGE
}
install_user="${OMARCHY_INSTALL_USER:-}"
while (($#)); do
case "$1" in
--install-user)
install_user="${2:-}"
shift 2
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: $1" >&2
usage >&2
exit 1
;;
esac
done
if (( EUID != 0 )); then
echo "Error: omarchy-setup-hardware must run as root" >&2
exit 1
fi
if [[ -z $install_user || $install_user == "root" ]]; then
echo "Error: --install-user must name the target non-root user" >&2
exit 1
fi
if ! getent passwd "$install_user" >/dev/null; then
echo "Error: user '$install_user' does not exist" >&2
exit 1
fi
export OMARCHY_INSTALL_USER="$install_user"
export OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}"
export OMARCHY_INSTALL="${OMARCHY_INSTALL:-$OMARCHY_PATH/install}"
export OMARCHY_INSTALL_LOG_FILE="${OMARCHY_INSTALL_LOG_FILE:-/var/log/omarchy-install.log}"
export PATH="$OMARCHY_PATH/bin:$PATH"
source "$OMARCHY_INSTALL/helpers/logging.sh"
source "$OMARCHY_INSTALL/hardware/all.sh"
+7 -2
View File
@@ -7,7 +7,7 @@
set -e
target_user=${SUDO_USER:-}
target_user=${OMARCHY_INSTALL_USER:-${SUDO_USER:-}}
if [[ -z $target_user && -n ${PKEXEC_UID:-} ]]; then
target_user=$(getent passwd "$PKEXEC_UID" | cut -d: -f1)
fi
@@ -59,4 +59,9 @@ else
fi
omarchy-shell lock status >/dev/null 2>&1 && echo "Lock screen authentication configured."
# omarchy-shell can't reach a running shell during chroot install. The echo
# is just confirmation, so swallow the failure rather than letting it become
# the script's exit code.
if omarchy-shell lock status >/dev/null 2>&1; then
echo "Lock screen authentication configured."
fi
+92
View File
@@ -0,0 +1,92 @@
#!/bin/bash
# omarchy:summary=Apply Omarchy system setup in the installed target
# omarchy:group=setup
# omarchy:requires-sudo=true
# omarchy:examples=omarchy setup system --install-user dhh --first-install
set -euo pipefail
usage() {
cat <<USAGE
Usage: omarchy setup system --install-user USER [--first-install|--upgrade]
Runs root-owned Omarchy system setup. The ISO calls this in the target chroot
after packages are installed and the target user exists. It also calls
omarchy-setup-hardware, so hardware setup cannot be accidentally skipped.
USAGE
}
install_user="${OMARCHY_INSTALL_USER:-}"
first_install=0
upgrade=0
while (($#)); do
case "$1" in
--install-user)
install_user="${2:-}"
shift 2
;;
--first-install)
first_install=1
shift
;;
--upgrade)
upgrade=1
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: $1" >&2
usage >&2
exit 1
;;
esac
done
if (( EUID != 0 )); then
echo "Error: omarchy-setup-system must run as root" >&2
exit 1
fi
if [[ -z $install_user || $install_user == "root" ]]; then
echo "Error: --install-user must name the target non-root user" >&2
exit 1
fi
if ! getent passwd "$install_user" >/dev/null; then
echo "Error: user '$install_user' does not exist" >&2
exit 1
fi
export OMARCHY_INSTALL_USER="$install_user"
export OMARCHY_FIRST_INSTALL="$first_install"
export OMARCHY_UPGRADE="$upgrade"
export OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}"
export OMARCHY_INSTALL="${OMARCHY_INSTALL:-$OMARCHY_PATH/install}"
export OMARCHY_INSTALL_LOG_FILE="${OMARCHY_INSTALL_LOG_FILE:-/var/log/omarchy-install.log}"
export PATH="$OMARCHY_PATH/bin:$PATH"
source "$OMARCHY_INSTALL/helpers/logging.sh"
start_install_log
run_logged "$OMARCHY_INSTALL/config/theme-system.sh"
run_logged "$OMARCHY_INSTALL/config/increase-lockout-limit.sh"
run_logged "$OMARCHY_INSTALL/config/lockscreen-pam.sh"
run_logged "$OMARCHY_INSTALL/config/fix-powerprofilesctl-shebang.sh"
run_logged "$OMARCHY_INSTALL/config/docker.sh"
run_logged "$OMARCHY_INSTALL/config/enable-services.sh"
run_logged "$OMARCHY_INSTALL/config/firewall.sh"
omarchy-setup-hardware --install-user "$install_user"
run_logged "$OMARCHY_INSTALL/login/sddm.sh"
run_logged "$OMARCHY_INSTALL/post-install/pacman.sh"
run_logged "$OMARCHY_INSTALL/post-install/udev.sh"
run_logged "$OMARCHY_INSTALL/post-install/localdb.sh"
stop_install_log
+1 -1
View File
@@ -4,6 +4,6 @@
clear
echo -e "\033[32m"
cat <~/.local/share/omarchy/logo.txt
cat <$OMARCHY_PATH/logo.txt
echo -e "\033[0m"
echo
+8 -3
View File
@@ -7,11 +7,13 @@
monitor_command='exec dbus-monitor --system "type='\''signal'\'',sender='\''org.freedesktop.login1'\'',interface='\''org.freedesktop.login1.Manager'\'',member='\''PrepareForSleep'\''"'
consume_sleep_events() {
local line
local line sleep_lock
sleep_lock=$(command -v omarchy-system-sleep-lock || true)
sleep_lock=${sleep_lock:-/usr/bin/omarchy-system-sleep-lock}
while IFS= read -r line; do
if [[ $line == *"boolean true"* ]]; then
"$OMARCHY_PATH/bin/omarchy-system-sleep-lock"
"$sleep_lock"
exit 0
fi
done
@@ -22,9 +24,12 @@ if [[ ${1:-} == "--consume" ]]; then
exit 0
fi
sleep_monitor=$(command -v omarchy-system-sleep-monitor || true)
sleep_monitor=${sleep_monitor:-/usr/bin/omarchy-system-sleep-monitor}
exec systemd-inhibit \
--what=sleep \
--mode=delay \
--who=Omarchy \
--why="Lock screen before suspend" \
bash -lc "$monitor_command | \"$OMARCHY_PATH/bin/omarchy-system-sleep-monitor\" --consume"
bash -lc "$monitor_command | \"$sleep_monitor\" --consume"
+43 -19
View File
@@ -56,21 +56,18 @@ snapshot_current_background() {
snapshot_background_path "$current_background" "previous"
}
set_theme_background() {
choose_theme_background() {
local backgrounds=()
local current_background index new_background next_index new_background_snapshot
local current_background index next_index i
CHOSEN_THEME_BACKGROUND=""
mapfile -d '' -t backgrounds < <(
find -L "$HOME/.config/omarchy/backgrounds/$THEME_NAME/" "$CURRENT_THEME_PATH/backgrounds/" -maxdepth 1 -type f \
\( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -o -iname '*.gif' -o -iname '*.bmp' -o -iname '*.webp' \) \
-print0 2>/dev/null | sort -z
)
if (( ${#backgrounds[@]} == 0 )); then
omarchy-notification-send "No background was found for theme" -t 2000
shell_ipc shell applyTheme "$colors_payload" "$shell_payload" || true
return
fi
(( ${#backgrounds[@]} > 0 )) || return 1
current_background=$(readlink "$CURRENT_BACKGROUND_LINK" 2>/dev/null || true)
index=-1
@@ -82,12 +79,28 @@ set_theme_background() {
done
if (( index == -1 )); then
new_background="${backgrounds[0]}"
CHOSEN_THEME_BACKGROUND="${backgrounds[0]}"
else
next_index=$(((index + 1) % ${#backgrounds[@]}))
new_background="${backgrounds[$next_index]}"
CHOSEN_THEME_BACKGROUND="${backgrounds[$next_index]}"
fi
}
set_theme_background_link() {
choose_theme_background || return 1
ln -nsf "$CHOSEN_THEME_BACKGROUND" "$CURRENT_BACKGROUND_LINK"
}
set_theme_background() {
local new_background new_background_snapshot
if ! choose_theme_background; then
omarchy-notification-send "No background was found for theme" -t 2000
shell_ipc shell applyTheme "$colors_payload" "$shell_payload" || true
return
fi
new_background="$CHOSEN_THEME_BACKGROUND"
new_background_snapshot=$(snapshot_background_path "$new_background" "next")
if [[ -f $OLD_BACKGROUND_SNAPSHOT && -f $new_background_snapshot ]]; then
@@ -110,6 +123,10 @@ set_theme_background() {
}
THEME_NAME=$(echo "$1" | sed -E 's/<[^>]+>//g' | tr '[:upper:]' '[:lower:]' | tr ' ' '-')
THEME_HEADLESS=0
if [[ ${OMARCHY_THEME_HEADLESS:-} == "1" || ${OMARCHY_THEME_OFFLINE:-} == "1" ]]; then
THEME_HEADLESS=1
fi
if [[ ! -d $OMARCHY_THEMES_PATH/$THEME_NAME ]] && [[ ! -d $USER_THEMES_PATH/$THEME_NAME ]]; then
echo "Theme '$THEME_NAME' does not exist"
@@ -139,7 +156,7 @@ fi
omarchy-theme-set-templates
OLD_BACKGROUND_SNAPSHOT=""
if [[ $OMARCHY_THEME_SKIP_BACKGROUND != "1" ]]; then
if [[ $THEME_HEADLESS != "1" && $OMARCHY_THEME_SKIP_BACKGROUND != "1" ]]; then
OLD_BACKGROUND_SNAPSHOT=$(snapshot_current_background)
fi
@@ -154,7 +171,12 @@ echo "$THEME_NAME" >"$HOME/.config/omarchy/current/theme.name"
# the theme hooks run.
colors_payload=$([[ -f $CURRENT_THEME_PATH/colors.toml ]] && base64 -w 0 "$CURRENT_THEME_PATH/colors.toml")
shell_payload=$([[ -f $CURRENT_THEME_PATH/shell.toml ]] && base64 -w 0 "$CURRENT_THEME_PATH/shell.toml")
if [[ $OMARCHY_THEME_SKIP_BACKGROUND == "1" ]]; then
if [[ $THEME_HEADLESS == "1" ]]; then
# No shell/session bus exists during ISO chroot finalization, but the first
# real login still needs a current background symlink for omarchy-shell to
# render.
[[ $OMARCHY_THEME_SKIP_BACKGROUND == "1" ]] || set_theme_background_link || true
elif [[ $OMARCHY_THEME_SKIP_BACKGROUND == "1" ]]; then
shell_ipc shell applyTheme "$colors_payload" "$shell_payload" || true
else
set_theme_background
@@ -181,13 +203,15 @@ post_theme_commands=(
omarchy-theme-set-keyboard
)
run_parallel "${post_theme_commands[@]}"
if [[ $THEME_HEADLESS != "1" ]]; then
run_parallel "${post_theme_commands[@]}"
# Call hook on theme set
omarchy-hook theme-set "$THEME_NAME" >/dev/null
# Call hook on theme set
omarchy-hook theme-set "$THEME_NAME" >/dev/null
# Warm selector caches after the theme is applied. The shell hot-reloads theme
# colors/backgrounds, so keep the running instance alive and preload the picker
# rows/selection to avoid first-open carousel settling after a theme change.
omarchy-theme-switcher --preload >/dev/null 2>&1
omarchy-theme-bg-cache >/dev/null 2>&1 &
# Warm selector caches after the theme is applied. The shell hot-reloads theme
# colors/backgrounds, so keep the running instance alive and preload the picker
# rows/selection to avoid first-open carousel settling after a theme change.
omarchy-theme-switcher --preload >/dev/null 2>&1
omarchy-theme-bg-cache >/dev/null 2>&1 &
fi
+7
View File
@@ -3,6 +3,13 @@
# omarchy:summary=Apply the current theme to GNOME color mode and icon settings
# omarchy:hidden=true
# gsettings needs a user DBus session. During ISO installs this command can be
# reached from arch-chroot while applying the initial Omarchy theme; defer until
# the user has a real session instead of emitting dconf warnings.
if [[ -z ${DBUS_SESSION_BUS_ADDRESS:-} ]]; then
exit 0
fi
THEME_DIR=~/.config/omarchy/current/theme
COLORS_FILE="$THEME_DIR/colors.toml"
+48 -12
View File
@@ -1,40 +1,76 @@
#!/bin/bash
# omarchy:summary=Create a desktop launcher for a terminal UI app
# omarchy:args=[name command window-style icon-url]
# omarchy:args=[name command window-style icon-url-or-name]
set -e
ICON_DIR="$HOME/.local/share/icons/hicolor/256x256/apps"
safe_icon_name() {
printf '%s\n' "$1" \
| tr '[:upper:]' '[:lower:]' \
| sed 's/[^[:alnum:]]\+/-/g; s/^-//; s/-$//'
}
icon_name_from_ref() {
local ref="$1"
local name
name=$(basename "$ref")
if [[ $name == *.* ]]; then
safe_icon_name "${name%.*}"
else
printf '%s\n' "$name"
fi
}
install_user_icon() {
local source="$1"
local name="$2"
local ext="${source##*.}"
[[ $ext == "$source" ]] && ext="png"
mkdir -p "$ICON_DIR"
cp "$source" "$ICON_DIR/$name.$ext"
gtk-update-icon-cache "$HOME/.local/share/icons/hicolor" &>/dev/null || true
printf '%s\n' "$name"
}
if (( $# != 4 )); then
echo -e "\e[32mLet's create a TUI shortcut you can start with the app launcher.\n\e[0m"
APP_NAME=$(gum input --prompt "Name> " --placeholder "My TUI")
APP_EXEC=$(gum input --prompt "Launch Command> " --placeholder "lazydocker or bash -c 'dust; read -n 1 -s'")
WINDOW_STYLE=$(gum choose --header "Window style" float tile)
ICON_URL=$(gum input --prompt "Icon URL> " --placeholder "See https://dashboardicons.com (must use PNG or SVG!)")
ICON_REF=$(gum input --prompt "Icon URL/name> " --placeholder "See https://dashboardicons.com or enter an installed icon name")
else
APP_NAME="$1"
APP_EXEC="$2"
WINDOW_STYLE="$3"
ICON_URL="$4"
ICON_REF="$4"
fi
if [[ -z $APP_NAME || -z $APP_EXEC || -z $ICON_URL ]]; then
echo "You must set app name, app command, and icon URL!"
if [[ -z $APP_NAME || -z $APP_EXEC || -z $ICON_REF ]]; then
echo "You must set app name, app command, and icon URL/name!"
exit 1
fi
ICON_DIR="$HOME/.local/share/applications/icons"
DESKTOP_FILE="$HOME/.local/share/applications/$APP_NAME.desktop"
mkdir -p "$(dirname "$DESKTOP_FILE")"
if [[ ! $ICON_URL =~ ^https?:// ]] && [[ -f $ICON_URL ]]; then
ICON_PATH="$ICON_URL"
else
ICON_PATH="$ICON_DIR/$APP_NAME.png"
if [[ $ICON_REF =~ ^https?:// ]]; then
ICON_VALUE=$(safe_icon_name "$APP_NAME")
mkdir -p "$ICON_DIR"
if ! curl -sL -o "$ICON_PATH" "$ICON_URL"; then
if ! curl -sL -o "$ICON_DIR/$ICON_VALUE.png" "$ICON_REF"; then
echo "Error: Failed to download icon."
exit 1
fi
gtk-update-icon-cache "$HOME/.local/share/icons/hicolor" &>/dev/null || true
elif [[ -f $ICON_REF ]]; then
ICON_VALUE=$(install_user_icon "$ICON_REF" "$(safe_icon_name "$APP_NAME")")
else
# Bundled Omarchy icons are package-owned under /usr/share/icons/hicolor.
ICON_VALUE=$(icon_name_from_ref "$ICON_REF")
fi
if [[ $WINDOW_STYLE == "float" ]]; then
@@ -51,7 +87,7 @@ Comment=$APP_NAME
Exec=xdg-terminal-exec --app-id=$APP_CLASS -e $APP_EXEC
Terminal=false
Type=Application
Icon=$ICON_PATH
Icon=$ICON_VALUE
StartupNotify=true
EOF
+4 -2
View File
@@ -5,7 +5,8 @@
set -e
ICON_DIR="$HOME/.local/share/applications/icons"
ICON_DIR="$HOME/.local/share/icons/hicolor/256x256/apps"
OLD_ICON_DIR="$HOME/.local/share/applications/icons"
DESKTOP_DIR="$HOME/.local/share/applications/"
if (( $# == 0 )); then
@@ -32,6 +33,7 @@ if [[ -z $APP_NAME ]]; then
exit 1
fi
icon_name=$(printf '%s\n' "$APP_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^[:alnum:]]\+/-/g; s/^-//; s/-$//')
rm -f "$DESKTOP_DIR/$APP_NAME.desktop"
rm -f "$ICON_DIR/$APP_NAME.png"
rm -f "$ICON_DIR/$icon_name.png" "$ICON_DIR/$APP_NAME.png" "$OLD_ICON_DIR/$APP_NAME.png"
omarchy-notification-send -g  "TUI removed" "$APP_NAME"
+4 -2
View File
@@ -5,7 +5,8 @@
set -e
APP_DIR="${1:-$HOME/.local/share/applications}"
ICON_DIR="$HOME/.local/share/applications/icons"
ICON_DIR="$HOME/.local/share/icons/hicolor/256x256/apps"
OLD_ICON_DIR="$HOME/.local/share/applications/icons"
echo "Scanning for TUIs in $APP_DIR..."
@@ -23,9 +24,10 @@ fi
for file in "${tui_desktop_files[@]}"; do
app_name=$(basename "$file" .desktop)
icon_name=$(printf '%s\n' "$app_name" | tr '[:upper:]' '[:lower:]' | sed 's/[^[:alnum:]]\+/-/g; s/^-//; s/-$//')
echo "Removing TUI: $app_name"
rm -f "$file"
rm -f "$ICON_DIR/$app_name.png"
rm -f "$ICON_DIR/$icon_name.png" "$ICON_DIR/$app_name.png" "$OLD_ICON_DIR/$app_name.png"
done
if command -v update-desktop-database &>/dev/null; then
+89 -6
View File
@@ -7,17 +7,100 @@
set -e
# Run the update inside a PTY so pacman/yay keep showing download progress
# while still logging the full session for later analysis.
if [[ -z $OMARCHY_UPDATE_LOGGED ]]; then
if [[ -z ${OMARCHY_UPDATE_LOGGED:-} ]]; then
script_command=$(printf '%q ' "$0" "$@")
exec env OMARCHY_UPDATE_LOGGED=1 script -qefc "$script_command" "/tmp/omarchy-update.log"
fi
acquire_update_lock() {
local lock_dir="${XDG_RUNTIME_DIR:-/tmp}"
local lock_path="$lock_dir/omarchy-update.lock"
local lock_fd_path=""
mkdir -p "$lock_dir" 2>/dev/null || true
if [[ -n ${OMARCHY_UPDATE_LOCK_FD:-} && -e /proc/$$/fd/$OMARCHY_UPDATE_LOCK_FD ]]; then
lock_fd_path=$(readlink -f "/proc/$$/fd/$OMARCHY_UPDATE_LOCK_FD" 2>/dev/null || true)
if [[ $lock_fd_path == "$(readlink -m "$lock_path")" ]] && flock -n "$OMARCHY_UPDATE_LOCK_FD"; then
return 0
fi
fi
exec {OMARCHY_UPDATE_LOCK_FD}>"$lock_path"
if ! flock -n "$OMARCHY_UPDATE_LOCK_FD"; then
echo "An Omarchy update is already running."
exit 1
fi
export OMARCHY_UPDATE_LOCK_FD
}
update_disabled_idle=0
sleep_inhibit_pid=""
disable_sleep_for_update() {
command -v systemd-inhibit >/dev/null 2>&1 || return 0
systemd-inhibit \
--what=sleep:idle \
--who=omarchy-update \
--why="Omarchy update in progress" \
--mode=block \
sleep infinity >/dev/null 2>&1 &
sleep_inhibit_pid=$!
}
disable_idle_for_update() {
local stay_awake_state="$HOME/.local/state/omarchy/indicators/stay-awake"
if [[ ! -f $stay_awake_state ]]; then
omarchy-toggle-idle stay-awake >/dev/null 2>&1 || true
update_disabled_idle=1
fi
}
restore_update_inhibitors() {
if (( update_disabled_idle )); then
omarchy-toggle-idle allow-idle >/dev/null 2>&1 || true
fi
if [[ -n $sleep_inhibit_pid ]]; then
kill "$sleep_inhibit_pid" >/dev/null 2>&1 || true
wait "$sleep_inhibit_pid" >/dev/null 2>&1 || true
fi
}
run_update_pipeline() {
disable_sleep_for_update
disable_idle_for_update
omarchy-update-keyring
omarchy-update-system-pkgs
omarchy-migrate
omarchy-hook post-update
omarchy-update-aur-pkgs
omarchy-update-mise
omarchy-update-orphan-pkgs
omarchy-update-analyze-logs
# Re-check after updates so the status bar reflects any remaining updates.
# This clears the state when everything is current, so a separate reset command
# is not needed.
if omarchy-update-available >/dev/null; then
omarchy-shell -q omarchy.system-update refresh
else
omarchy-shell -q omarchy.system-update clear
fi
omarchy-update-restart
}
acquire_update_lock
trap restore_update_inhibitors EXIT
trap 'echo ""; echo -e "\033[0;31mSomething went wrong during the update!\n\nPlease review the output above carefully, correct the error, and retry the update.\n\nIf you need assistance, get help from the community at https://omarchy.org/discord\033[0m"' ERR
if [[ $1 == "-y" ]] || omarchy-update-confirm; then
if [[ ${1:-} == "-y" ]] || omarchy-update-confirm; then
omarchy-snapshot create || (($? == 127))
omarchy-update-git
omarchy-update-perform
run_update_pipeline
fi
+112 -17
View File
@@ -1,24 +1,119 @@
#!/bin/bash
# omarchy:summary=Get remote tag
# omarchy:summary=Check whether system or AUR packages have available updates.
latest_tag=$(git -C "$OMARCHY_PATH" ls-remote --tags origin | grep -v "{}" | awk '{print $2}' | sed 's#refs/tags/##' | sort -V | tail -n 1)
if [[ -z $latest_tag ]]; then
echo "Error: Could not retrieve latest tag."
exit 1
fi
set -euo pipefail
# Get local tag
current_tag=$(git -C "$OMARCHY_PATH" describe --tags $(git -C "$OMARCHY_PATH" rev-list --tags --max-count=1))
if [[ -z $current_tag ]]; then
echo "Error: Could not retrieve current tag."
exit 1
fi
CHECK_TIMEOUT="${OMARCHY_UPDATE_CHECK_TIMEOUT:-60}"
STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/omarchy/updates"
TMP_PARENT="${TMPDIR:-/tmp}"
if [[ $current_tag != $latest_tag ]]; then
echo "Omarchy update available ($latest_tag)"
exit 0
mkdir -p "$STATE_DIR"
tmp_dir=$(mktemp -d "$TMP_PARENT/omarchy-update-available.XXXXXX")
trap 'rm -rf "$tmp_dir"' EXIT
packages_raw="$tmp_dir/packages.raw"
packages_tmp="$tmp_dir/packages"
aur_raw="$tmp_dir/aur.raw"
aur_tmp="$tmp_dir/aur"
errors_tmp="$tmp_dir/errors"
packages_file="$STATE_DIR/packages"
aur_file="$STATE_DIR/aur"
available_file="$STATE_DIR/available"
checked_at_file="$STATE_DIR/checked-at"
error_file="$STATE_DIR/error"
: >"$packages_raw"
: >"$packages_tmp"
: >"$aur_raw"
: >"$aur_tmp"
: >"$errors_tmp"
strip_update_output() {
local source="$1"
local destination="$2"
sed -E 's/\x1B\[[0-9;]*m//g' "$source" | sed '/^[[:space:]]*$/d' >"$destination"
}
check_system_packages() {
local status=0
if command -v checkupdates >/dev/null 2>&1 && command -v fakeroot >/dev/null 2>&1; then
CHECKUPDATES_DB="$tmp_dir/checkupdates-db" timeout "$CHECK_TIMEOUT" checkupdates --nocolor >"$packages_raw" 2>"$tmp_dir/checkupdates.err" || status=$?
case "$status" in
0|2)
;;
124)
echo "System package update check timed out" >>"$errors_tmp"
;;
*)
echo "System package update check failed" >>"$errors_tmp"
sed '/^[[:space:]]*$/d' "$tmp_dir/checkupdates.err" >>"$errors_tmp" || true
;;
esac
elif command -v pacman >/dev/null 2>&1; then
# Fallback for systems that have not picked up pacman-contrib/fakeroot yet.
# This only reports updates already known to the local sync database.
pacman -Qu --color never >"$packages_raw" 2>/dev/null || true
else
echo "pacman is not available" >>"$errors_tmp"
fi
strip_update_output "$packages_raw" "$packages_tmp"
}
check_aur_packages() {
local status=0
command -v pacman >/dev/null 2>&1 || return 0
command -v yay >/dev/null 2>&1 || return 0
pacman -Qem >/dev/null 2>&1 || return 0
timeout "$CHECK_TIMEOUT" yay --color never -Qua >"$aur_raw" 2>"$tmp_dir/yay.err" || status=$?
case "$status" in
0|1)
;;
124)
echo "AUR package update check timed out" >>"$errors_tmp"
;;
*)
echo "AUR package update check failed" >>"$errors_tmp"
sed '/^[[:space:]]*$/d' "$tmp_dir/yay.err" >>"$errors_tmp" || true
;;
esac
strip_update_output "$aur_raw" "$aur_tmp"
grep -vw '\[ignored\]$' "$aur_tmp" >"$aur_tmp.filtered" || true
mv "$aur_tmp.filtered" "$aur_tmp"
}
check_system_packages
check_aur_packages
cp "$packages_tmp" "$packages_file"
cp "$aur_tmp" "$aur_file"
cat "$packages_tmp" "$aur_tmp" >"$available_file"
date --iso-8601=seconds >"$checked_at_file"
if [[ -s $errors_tmp ]]; then
cp "$errors_tmp" "$error_file"
else
echo "Omarchy is up to date ($current_tag)"
exit 1
rm -f "$error_file"
fi
if [[ -s $available_file ]]; then
cat "$available_file"
exit 0
fi
if [[ -s $error_file ]]; then
cat "$error_file" >&2
fi
echo "System is up to date"
exit 1
-6
View File
@@ -1,6 +0,0 @@
#!/bin/bash
# omarchy:summary=Ensure the status bar icon offering the available update is removed
omarchy-shell -q SystemUpdate refresh
exit 0
-36
View File
@@ -1,36 +0,0 @@
#!/bin/bash
# omarchy:summary=Switch Omarchy branches and update from the selected branch
# omarchy:args=<branch>
set -e
if (($# == 0)); then
echo "Usage: omarchy-update-branch [master|dev]"
exit 1
fi
branch="$1"
# Snapshot before switching branch
omarchy-snapshot create || (( $? == 127 ))
if ! git -C "$OMARCHY_PATH" diff --quiet || ! git -C "$OMARCHY_PATH" diff --cached --quiet; then
stashed=true
git -C "$OMARCHY_PATH" stash push -u -m "Autostash before switching to $branch"
else
stashed=false
fi
# Switch branches
git -C "$OMARCHY_PATH" switch "$branch"
# Reapply stash if we made one
if [[ $stashed == "true" ]]; then
if ! git -C "$OMARCHY_PATH" stash pop; then
echo "⚠️ Conflicts when applying stash — stash kept"
fi
fi
# Update the system from the new branch
omarchy-update-perform
+1 -1
View File
@@ -8,7 +8,7 @@ gum style --border normal --padding "1 2" \
"• You cannot stop the update once you start!" \
"• Make sure you're connected to power or have a full battery" \
"" \
"What's new: https://github.com/basecamp/omarchy/releases"
"What's new: https://github.com/basecamp/omarchy/releases/latest"
echo
-18
View File
@@ -1,18 +0,0 @@
#!/bin/bash
# omarchy:summary=Pull the latest Omarchy git changes
set -e
echo -e "\e[32mUpdate Omarchy\e[0m"
omarchy-update-time
# Suppress Hyprland config errors while git updates default config files mid-pull
hyprctl keyword debug:suppress_errors true &>/dev/null || true
hyprctl eval 'hl.config({ debug = { suppress_errors = true } })' &>/dev/null || true
git -C $OMARCHY_PATH pull --autostash
git -C $OMARCHY_PATH --no-pager diff --check || git -C $OMARCHY_PATH reset --merge
hyprctl reload &>/dev/null || true
+23 -7
View File
@@ -1,13 +1,29 @@
#!/bin/bash
# omarchy:summary=Remove orphaned system packages after updates
# omarchy:summary=Review and optionally remove orphaned system packages after updates
# omarchy:requires-sudo=true
orphans=$(pacman -Qtdq || true)
if [[ -n $orphans ]]; then
echo -e "\e[32m\nRemove orphan system packages\e[0m"
for pkg in $orphans; do
sudo pacman -Rs --noconfirm "$pkg" || true
done
set -e
mapfile -t orphans < <(pacman -Qtdq 2>/dev/null || true)
(( ${#orphans[@]} )) || exit 0
echo -e "\e[32m\nOrphan system packages\e[0m"
printf ' %s\n' "${orphans[@]}"
echo
if [[ ! -t 0 || ! -t 1 ]]; then
echo "${#orphans[@]} orphaned package(s) found. Re-run omarchy-update-orphan-pkgs in a terminal to review/remove them."
echo
exit 0
fi
if ! gum confirm --default=false "Remove ${#orphans[@]} orphaned package(s)?"; then
echo "Keeping orphaned packages."
echo
exit 0
fi
echo -e "\e[32m\nRemoving orphan system packages\e[0m"
sudo pacman -Rns "${orphans[@]}"
echo
+64
View File
@@ -0,0 +1,64 @@
#!/bin/bash
# omarchy:summary=Prevent direct pacman system upgrades from bypassing omarchy update.
# omarchy:hidden=true
set -euo pipefail
if [[ ${OMARCHY_UPDATE_PACMAN:-} == "1" || ${OMARCHY_ALLOW_DIRECT_PACMAN:-} == "1" ]]; then
exit 0
fi
pacman_args=()
if [[ -n ${OMARCHY_PACMAN_CMDLINE:-} ]]; then
read -r -a pacman_args <<<"$OMARCHY_PACMAN_CMDLINE"
elif [[ -r /proc/$PPID/cmdline ]]; then
mapfile -d '' -t pacman_args <"/proc/$PPID/cmdline" || true
fi
is_system_upgrade=0
has_sync=0
has_sysupgrade=0
for arg in "${pacman_args[@]}"; do
case "$arg" in
--sync)
has_sync=1
;;
--sysupgrade)
has_sysupgrade=1
;;
--*)
;;
-*)
[[ $arg == *S* ]] && has_sync=1
[[ $arg == *u* ]] && has_sysupgrade=1
;;
esac
done
if (( has_sync && has_sysupgrade )); then
is_system_upgrade=1
fi
(( is_system_upgrade )) || exit 0
cat >&2 <<'MESSAGE'
Woah partner...
This looks like a direct pacman system upgrade. Omarchy updates should normally
run through:
omarchy update
That path handles the update transcript, snapshot, keyrings, package upgrade,
migrations, post-update hooks, shell update state, and restart checks together.
If you really meant to bypass Omarchy for this transaction, rerun pacman with:
sudo env OMARCHY_ALLOW_DIRECT_PACMAN=1 pacman -Syu
MESSAGE
exit 1
+3 -22
View File
@@ -1,26 +1,7 @@
#!/bin/bash
# omarchy:summary=Run the full Omarchy update pipeline
# omarchy:summary=Compatibility wrapper for omarchy-update -y.
# omarchy:hidden=true
# omarchy:requires-sudo=true
set -e
# Ensure screensaver/sleep doesn't set in during updates
hyprctl dispatch 'hl.dsp.window.tag({ tag = "+noidle" })' &>/dev/null || hyprctl dispatch tagwindow +noidle &>/dev/null || true
# Perform all update steps
omarchy-update-keyring
omarchy-update-available-reset
omarchy-update-system-pkgs
omarchy-migrate
omarchy-update-aur-pkgs
omarchy-update-mise
omarchy-update-orphan-pkgs
omarchy-hook post-update
omarchy-update-analyze-logs
omarchy-update-restart
# Re-enable screensaver/sleep after updates
hyprctl dispatch 'hl.dsp.window.tag({ tag = "-noidle" })' &>/dev/null || hyprctl dispatch tagwindow -- -noidle &>/dev/null || true
exec omarchy-update -y
+22 -1
View File
@@ -6,4 +6,25 @@
set -e
echo -e "\e[32m\nUpdate system packages\e[0m"
sudo pacman -Syyu --noconfirm
# Transition --overwrite: previous script-installed Omarchy wrote these paths
# as unowned files; pacman would refuse the omarchy-settings upgrade on first
# encounter. Drop each entry once the transition release is the baseline.
sudo env OMARCHY_UPDATE_PACMAN=1 pacman -Syu --noconfirm \
--overwrite '/etc/docker/daemon.json' \
--overwrite '/etc/gnupg/dirmngr.conf' \
--overwrite '/etc/modprobe.d/omarchy-usb-autosuspend.conf' \
--overwrite '/etc/sudoers.d/omarchy-asdcontrol' \
--overwrite '/etc/sudoers.d/omarchy-passwd-tries' \
--overwrite '/etc/sudoers.d/omarchy-tzupdate' \
--overwrite '/etc/sysctl.d/90-omarchy-file-watchers.conf' \
--overwrite '/etc/sysctl.d/99-omarchy-sysctl.conf' \
--overwrite '/etc/systemd/logind.conf.d/10-ignore-power-button.conf' \
--overwrite '/etc/systemd/resolved.conf.d/10-disable-multicast.conf' \
--overwrite '/etc/systemd/resolved.conf.d/20-docker-dns.conf' \
--overwrite '/etc/systemd/system.conf.d/10-faster-shutdown.conf' \
--overwrite '/etc/systemd/system/user@.service.d/10-faster-shutdown.conf' \
--overwrite '/etc/systemd/system/docker.service.d/no-block-boot.conf' \
--overwrite '/etc/systemd/system/plocate-updatedb.service.d/ac-only.conf' \
--overwrite '/usr/lib/systemd/system-sleep/unmount-fuse' \
--overwrite '/usr/share/plymouth/themes/omarchy/*'
+6
View File
@@ -0,0 +1,6 @@
#!/bin/bash
# omarchy:summary=Compatibility wrapper for omarchy-migrate-notify.
# omarchy:hidden=true
exec omarchy-migrate-notify "$@"
-4
View File
@@ -1,4 +0,0 @@
#!/bin/bash
# omarchy:summary=No-op now that omarchy-update-perform is responsible for idle management.
# omarchy:hidden=true
+2167
View File
File diff suppressed because it is too large Load Diff
+44 -7
View File
@@ -28,7 +28,7 @@ else
echo "========================================="
echo "SYSTEM INFORMATION"
echo "========================================="
echo "Hostname: $(hostname)"
echo "Hostname: $(uname -n)"
echo "Kernel: $(uname -r)"
echo "Date: $(date)"
echo ""
@@ -39,14 +39,53 @@ else
} >"$SYSTEM_INFO"
fi
same_or_prefix_log() {
local a="$1" b="$2" size_a size_b min_size
[[ -s $a && -s $b ]] || return 1
cmp -s "$a" "$b" && return 0
size_a=$(stat -c '%s' "$a" 2>/dev/null) || return 1
size_b=$(stat -c '%s' "$b" 2>/dev/null) || return 1
if (( size_a < size_b )); then
min_size=$size_a
else
min_size=$size_b
fi
(( min_size > 0 )) || return 1
cmp -n "$min_size" "$a" "$b" >/dev/null 2>&1
}
case "$LOG_TYPE" in
install)
# In the live ISO before reboot, the target system is mounted at /mnt so the
# omarchy install log lives at /mnt/var/log/omarchy-install.log. On the
# installed system it's at /var/log/omarchy-install.log. Prefer whichever
# exists, with /mnt taking precedence (only present in the ISO context, and
# there it's the right one).
ARCHINSTALL_LOG="/var/log/archinstall/install.log"
OMARCHY_LOG="/var/log/omarchy-install.log"
LIVE_OMARCHY_LOG="/var/log/omarchy-install.log"
TARGET_OMARCHY_LOG="/mnt/var/log/omarchy-install.log"
# Combine system info with logs
cat "$SYSTEM_INFO" >"$TEMP_LOG"
cat $ARCHINSTALL_LOG $OMARCHY_LOG >>"$TEMP_LOG" 2>/dev/null
if [[ -s $ARCHINSTALL_LOG ]]; then
printf '\n========================================\nARCHINSTALL SUBSYSTEM LOG (%s)\n========================================\n\n' "$ARCHINSTALL_LOG" >>"$TEMP_LOG"
cat "$ARCHINSTALL_LOG" >>"$TEMP_LOG"
fi
if [[ -s $LIVE_OMARCHY_LOG ]]; then
printf '\n========================================\nOMARCHY INSTALL LOG (%s)\n========================================\n\n' "$LIVE_OMARCHY_LOG" >>"$TEMP_LOG"
cat "$LIVE_OMARCHY_LOG" >>"$TEMP_LOG"
fi
if [[ -s $TARGET_OMARCHY_LOG ]] && ! same_or_prefix_log "$LIVE_OMARCHY_LOG" "$TARGET_OMARCHY_LOG"; then
printf '\n========================================\nTARGET OMARCHY INSTALL LOG (%s)\n========================================\n\n' "$TARGET_OMARCHY_LOG" >>"$TEMP_LOG"
cat "$TARGET_OMARCHY_LOG" >>"$TEMP_LOG"
fi
if [[ ! -s $LIVE_OMARCHY_LOG && ! -s $TARGET_OMARCHY_LOG ]]; then
echo "Warning: omarchy install log not found (looked at /var/log and /mnt/var/log)" >&2
fi
if [[ ! -s $TEMP_LOG ]]; then
echo "Error: No install logs found"
@@ -113,15 +152,13 @@ esac
echo ""
URL=$(curl -sF "file=@$TEMP_LOG" -Fexpires=24 https://logs.omarchy.org)
URL=$(curl -sf -F "file=@$TEMP_LOG" -Fexpires=24 https://logs.omarchy.org/)
if (( $? == 0 )) && [[ -n $URL ]]; then
echo "✓ Log uploaded successfully!"
echo "Share this URL:"
echo ""
echo " $URL"
echo ""
echo "This link will expire in 24 hours."
else
echo "Error: Failed to upload log file"
exit 1
+19 -1
View File
@@ -2,4 +2,22 @@
# omarchy:summary=Print the installed Omarchy version
cat $OMARCHY_PATH/version
omarchy_path=${OMARCHY_PATH:-/usr/share/omarchy}
omarchy_path=${omarchy_path%/}
if [[ $omarchy_path != "/usr/share/omarchy" ]]; then
hash=$(git -C "$omarchy_path" rev-parse --short HEAD 2>/dev/null || true)
if [[ -n $hash ]]; then
echo "dev ($hash)"
else
echo "dev"
fi
exit 0
fi
version=$(pacman -Q omarchy 2>/dev/null | awk '{ print $2 }')
[[ -n $version ]] || exit 1
echo "$version"
+15 -2
View File
@@ -1,5 +1,18 @@
#!/bin/bash
# omarchy:summary=Print the current Omarchy git branch
# omarchy:summary=Print the active Omarchy dev-link git branch
# omarchy:hidden=true
echo $(git -C "$OMARCHY_PATH" rev-parse --abbrev-ref HEAD)
omarchy_path=${OMARCHY_PATH:-/usr/share/omarchy}
omarchy_path=${omarchy_path%/}
[[ $omarchy_path != "/usr/share/omarchy" ]] || exit 1
branch=$(git -C "$omarchy_path" branch --show-current 2>/dev/null || true)
if [[ -z $branch ]]; then
hash=$(git -C "$omarchy_path" rev-parse --short HEAD 2>/dev/null || true)
[[ -n $hash ]] || exit 1
branch="detached@$hash"
fi
echo "$branch"
+48 -12
View File
@@ -1,11 +1,41 @@
#!/bin/bash
# omarchy:summary=Create a desktop launcher for a web app
# omarchy:args=[name url icon [custom-exec] [mime-types]]
# omarchy:args=[name url icon-url-or-name [custom-exec] [mime-types]]
set -e
ICON_DIR="$HOME/.local/share/applications/icons"
ICON_DIR="$HOME/.local/share/icons/hicolor/256x256/apps"
safe_icon_name() {
printf '%s\n' "$1" \
| tr '[:upper:]' '[:lower:]' \
| sed 's/[^[:alnum:]]\+/-/g; s/^-//; s/-$//'
}
icon_name_from_ref() {
local ref="$1"
local name
name=$(basename "$ref")
if [[ $name == *.* ]]; then
safe_icon_name "${name%.*}"
else
printf '%s\n' "$name"
fi
}
install_user_icon() {
local source="$1"
local name="$2"
local ext="${source##*.}"
[[ $ext == "$source" ]] && ext="png"
mkdir -p "$ICON_DIR"
cp "$source" "$ICON_DIR/$name.$ext"
gtk-update-icon-cache "$HOME/.local/share/icons/hicolor" &>/dev/null || true
printf '%s\n' "$name"
}
if (( $# < 3 )); then
echo -e "\e[32mLet's create a new web app you can start with the app launcher.\n\e[0m"
@@ -18,10 +48,12 @@ if (( $# < 3 )); then
# Try to fetch favicon automatically first.
FAVICON_URL="https://www.google.com/s2/favicons?domain=${APP_URL}&sz=128"
mkdir -p "$ICON_DIR"
if curl -fsSL -o "$ICON_DIR/$APP_NAME.png" "$FAVICON_URL" && [[ -s $ICON_DIR/$APP_NAME.png ]]; then
ICON_REF="$APP_NAME.png"
ICON_VALUE=$(safe_icon_name "$APP_NAME")
if curl -fsSL -o "$ICON_DIR/$ICON_VALUE.png" "$FAVICON_URL" && [[ -s $ICON_DIR/$ICON_VALUE.png ]]; then
gtk-update-icon-cache "$HOME/.local/share/icons/hicolor" &>/dev/null || true
ICON_REF="$ICON_VALUE"
else
ICON_REF=$(gum input --prompt "Icon URL> " --placeholder "Could not fetch favicon automatically. Enter PNG icon URL (see https://dashboardicons.com)")
ICON_REF=$(gum input --prompt "Icon URL/name> " --placeholder "Could not fetch favicon automatically. Enter PNG icon URL or icon name")
fi
CUSTOM_EXEC=""
@@ -45,21 +77,24 @@ if [[ -z $APP_NAME || -z $APP_URL ]]; then
exit 1
fi
# Resolve icon from URL or from a local icon name.
mkdir -p "$ICON_DIR"
if [[ -z $ICON_REF ]]; then
ICON_REF="https://www.google.com/s2/favicons?domain=${APP_URL}&sz=128"
fi
if [[ $ICON_REF =~ ^https?:// ]]; then
ICON_PATH="$ICON_DIR/$APP_NAME.png"
if ! curl -fsSL -o "$ICON_PATH" "$ICON_REF" || [[ ! -s $ICON_PATH ]]; then
ICON_VALUE=$(safe_icon_name "$APP_NAME")
mkdir -p "$ICON_DIR"
if ! curl -fsSL -o "$ICON_DIR/$ICON_VALUE.png" "$ICON_REF" || [[ ! -s $ICON_DIR/$ICON_VALUE.png ]]; then
echo "Error: Failed to download icon."
exit 1
fi
gtk-update-icon-cache "$HOME/.local/share/icons/hicolor" &>/dev/null || true
elif [[ -f $ICON_REF ]]; then
ICON_VALUE=$(install_user_icon "$ICON_REF" "$(safe_icon_name "$APP_NAME")")
else
ICON_PATH="$ICON_DIR/$ICON_REF"
# Bundled Omarchy icons are package-owned under /usr/share/icons/hicolor.
# Accept either "HEY" or the historical "HEY.png" argument form.
ICON_VALUE=$(icon_name_from_ref "$ICON_REF")
fi
# Use custom exec if provided, otherwise default behavior
@@ -67,6 +102,7 @@ EXEC_COMMAND="${CUSTOM_EXEC:-omarchy-launch-webapp $APP_URL}"
# Create application .desktop file
DESKTOP_FILE="$HOME/.local/share/applications/$APP_NAME.desktop"
mkdir -p "$(dirname "$DESKTOP_FILE")"
cat >"$DESKTOP_FILE" <<EOF
[Desktop Entry]
@@ -76,7 +112,7 @@ Comment=$APP_NAME
Exec=$EXEC_COMMAND
Terminal=false
Type=Application
Icon=$ICON_PATH
Icon=$ICON_VALUE
StartupNotify=true
EOF
+4 -2
View File
@@ -5,7 +5,8 @@
set -e
ICON_DIR="$HOME/.local/share/applications/icons"
ICON_DIR="$HOME/.local/share/icons/hicolor/256x256/apps"
OLD_ICON_DIR="$HOME/.local/share/applications/icons"
DESKTOP_DIR="$HOME/.local/share/applications/"
if (( $# == 0 )); then
@@ -32,8 +33,9 @@ if [[ -z $APP_NAME ]]; then
exit 1
fi
icon_name=$(printf '%s\n' "$APP_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^[:alnum:]]\+/-/g; s/^-//; s/-$//')
rm -f "$DESKTOP_DIR/$APP_NAME.desktop"
rm -f "$ICON_DIR/$APP_NAME.png"
rm -f "$ICON_DIR/$icon_name.png" "$ICON_DIR/$APP_NAME.png" "$OLD_ICON_DIR/$APP_NAME.png"
omarchy-notification-send -g  "Web app removed" "$APP_NAME"
update-desktop-database "$DESKTOP_DIR" &>/dev/null
+4 -2
View File
@@ -5,7 +5,8 @@
set -e
APP_DIR="${1:-$HOME/.local/share/applications}"
ICON_DIR="$HOME/.local/share/applications/icons"
ICON_DIR="$HOME/.local/share/icons/hicolor/256x256/apps"
OLD_ICON_DIR="$HOME/.local/share/applications/icons"
echo "Scanning for web apps in $APP_DIR..."
@@ -23,9 +24,10 @@ fi
for file in "${webapp_desktop_files[@]}"; do
app_name=$(basename "$file" .desktop)
icon_name=$(printf '%s\n' "$app_name" | tr '[:upper:]' '[:lower:]' | sed 's/[^[:alnum:]]\+/-/g; s/^-//; s/-$//')
echo "Removing web app: $app_name"
rm -f "$file"
rm -f "$ICON_DIR/$app_name.png"
rm -f "$ICON_DIR/$icon_name.png" "$ICON_DIR/$app_name.png" "$OLD_ICON_DIR/$app_name.png"
done
if command -v update-desktop-database &>/dev/null; then
+1
View File
@@ -3,6 +3,7 @@
# omarchy:summary=Set Wi-Fi power save mode on wireless interfaces
# omarchy:args=<on|off>
shopt -s nullglob
for iface in /sys/class/net/*/wireless; do
iface="$(basename "$(dirname "$iface")")"
iw dev "$iface" set power_save "$1" 2>/dev/null
+2 -7
View File
@@ -44,19 +44,14 @@ install_windows() {
mkdir -p "$HOME/.windows"
mkdir -p "$HOME/.config/windows"
mkdir -p "$HOME/.local/share/applications/icons"
# Install Windows VM icon and desktop file
if [[ -f $OMARCHY_PATH/applications/icons/windows.png ]]; then
cp "$OMARCHY_PATH/applications/icons/windows.png" "$HOME/.local/share/applications/icons/windows.png"
fi
mkdir -p "$HOME/.local/share/applications"
cat << EOF | tee "$HOME/.local/share/applications/windows-vm.desktop" > /dev/null
[Desktop Entry]
Name=Windows
Comment=Start Windows VM via Docker and connect with RDP
Exec=uwsm app -- omarchy-windows-vm launch
Icon=$HOME/.local/share/applications/icons/windows.png
Icon=windows
Terminal=false
Type=Application
Categories=System;Virtualization;
-50
View File
@@ -1,50 +0,0 @@
#!/bin/bash
# Set install mode to online since boot.sh is used for curl installations
export OMARCHY_ONLINE_INSTALL=true
ansi_art=' ▄▄▄
▄█████▄ ▄███████████▄ ▄███████ ▄███████ ▄███████ ▄█ █▄ ▄█ █▄
███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███
███ ███ ███ ███ ███ ███ ███ ███ ███ ███ █▀ ███ ███ ███ ███
███ ███ ███ ███ ███ ▄███▄▄▄███ ▄███▄▄▄██▀ ███ ▄███▄▄▄███▄ ███▄▄▄███
███ ███ ███ ███ ███ ▀███▀▀▀███ ▀███▀▀▀▀ ███ ▀▀███▀▀▀███ ▀▀▀▀▀▀███
███ ███ ███ ███ ███ ███ ███ ██████████ ███ █▄ ███ ███ ▄██ ███
███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███ ███
▀█████▀ ▀█ ███ █▀ ███ █▀ ███ ███ ███████▀ ███ █▀ ▀█████▀
███ █▀ '
clear
echo -e "\n$ansi_art\n"
# Use custom branch if instructed, otherwise default to master
OMARCHY_REF="${OMARCHY_REF:-master}"
# Set mirror based on branch
if [[ $OMARCHY_REF == "dev" ]]; then
export OMARCHY_MIRROR=edge
echo 'Server = https://mirror.omarchy.org/$repo/os/$arch' | sudo tee /etc/pacman.d/mirrorlist >/dev/null
elif [[ $OMARCHY_REF == "rc" ]]; then
export OMARCHY_MIRROR=rc
echo 'Server = https://rc-mirror.omarchy.org/$repo/os/$arch' | sudo tee /etc/pacman.d/mirrorlist >/dev/null
else
export OMARCHY_MIRROR=stable
echo 'Server = https://stable-mirror.omarchy.org/$repo/os/$arch' | sudo tee /etc/pacman.d/mirrorlist >/dev/null
fi
sudo pacman -Syu --noconfirm --needed git
# Use custom repo if specified, otherwise default to basecamp/omarchy
OMARCHY_REPO="${OMARCHY_REPO:-basecamp/omarchy}"
echo -e "\nCloning Omarchy from: https://github.com/${OMARCHY_REPO}.git"
rm -rf ~/.local/share/omarchy/
git clone "https://github.com/${OMARCHY_REPO}.git" ~/.local/share/omarchy >/dev/null
echo -e "\e[32mUsing branch: $OMARCHY_REF\e[0m"
cd ~/.local/share/omarchy
git fetch origin "${OMARCHY_REF}" && git checkout "${OMARCHY_REF}"
cd -
echo -e "\nInstallation starting..."
source ~/.local/share/omarchy/install.sh
+1 -1
View File
@@ -1,4 +1,4 @@
--ozone-platform=wayland
--ozone-platform-hint=wayland
--enable-features=TouchpadOverscrollHistoryNavigation
--load-extension=~/.local/share/omarchy/default/chromium/extensions/copy-url,~/.local/share/omarchy/default/chromium/extensions/yt-dlp
--load-extension=/usr/share/omarchy/default/chromium/extensions/copy-url,/usr/share/omarchy/default/chromium/extensions/yt-dlp
+8 -1
View File
@@ -1,9 +1,16 @@
-- Learn how to configure Hyprland: https://wiki.hypr.land/Configuring/Start/
-- Drop cached omarchy modules so hyprctl reload re-reads them from disk.
for k in pairs(package.loaded) do
if k:match("^default%.hypr") or k:match("^hypr%.") then
package.loaded[k] = nil
end
end
-- Load user modules from ~/.config and Omarchy defaults from $OMARCHY_PATH.
package.path = os.getenv("HOME")
.. "/.config/?.lua;"
.. (os.getenv("OMARCHY_PATH") or (os.getenv("HOME") .. "/.local/share/omarchy"))
.. (os.getenv("OMARCHY_PATH") or "/usr/share/omarchy")
.. "/?.lua;"
.. package.path
-11
View File
@@ -1,11 +0,0 @@
# Changes require a restart to take effect.
# Ensure Omarchy bins are in the path
export OMARCHY_PATH=$HOME/.local/share/omarchy
export PATH=$OMARCHY_PATH/bin:$PATH:$HOME/.local/bin
# Set default terminal and editor
source ~/.config/uwsm/default
# Activate mise if present on the system
omarchy-cmd-present mise && eval "$(mise activate bash --shims)"
+2 -2
View File
@@ -6,9 +6,9 @@
<property name="pressureMultiplier" value="1"/>
<property name="zoomGesturesEnabled" value="true"/>
<property name="selectedToolbar" value="Portrait"/>
<property name="lastSavePath" value="/home/dhh/Downloads"/>
<property name="lastSavePath" value=""/>
<property name="lastOpenPath" value=""/>
<property name="lastImagePath" value="/home/dhh/Dropbox/Images"/>
<property name="lastImagePath" value=""/>
<property name="edgePanSpeed" value="20"/>
<property name="edgePanMaxMult" value="5"/>
<property name="zoomStep" value="10"/>
+49
View File
@@ -0,0 +1,49 @@
[Default Applications]
inode/directory=org.gnome.Nautilus.desktop
image/png=imv.desktop
image/jpeg=imv.desktop
image/gif=imv.desktop
image/webp=imv.desktop
image/bmp=imv.desktop
image/tiff=imv.desktop
application/pdf=org.gnome.Evince.desktop
x-scheme-handler/http=chromium.desktop
x-scheme-handler/https=chromium.desktop
x-scheme-handler/mailto=HEY.desktop
video/mp4=mpv.desktop
video/x-msvideo=mpv.desktop
video/x-matroska=mpv.desktop
video/x-flv=mpv.desktop
video/x-ms-wmv=mpv.desktop
video/mpeg=mpv.desktop
video/ogg=mpv.desktop
video/webm=mpv.desktop
video/quicktime=mpv.desktop
video/3gpp=mpv.desktop
video/3gpp2=mpv.desktop
video/x-ms-asf=mpv.desktop
video/x-ogm+ogg=mpv.desktop
video/x-theora+ogg=mpv.desktop
application/ogg=mpv.desktop
text/plain=nvim.desktop
text/english=nvim.desktop
text/x-makefile=nvim.desktop
text/x-c++hdr=nvim.desktop
text/x-c++src=nvim.desktop
text/x-chdr=nvim.desktop
text/x-csrc=nvim.desktop
text/x-java=nvim.desktop
text/x-moc=nvim.desktop
text/x-pascal=nvim.desktop
text/x-tcl=nvim.desktop
text/x-tex=nvim.desktop
application/x-shellscript=nvim.desktop
text/x-c=nvim.desktop
text/x-c++=nvim.desktop
application/xml=nvim.desktop
text/xml=nvim.desktop
+28
View File
@@ -0,0 +1,28 @@
# Single source of truth for OMARCHY_PATH + PATH adjustments. Sourced by:
# /etc/profile.d/omarchy.sh (system login shells)
# /etc/skel/.bashrc (interactive shells)
# /usr/share/uwsm/env.d/10-omarchy (Hyprland session via uwsm)
# /usr/share/omarchy/default/bash/envs (bash rc chain; SSH/non-login)
# /etc/omarchy.conf is written by omarchy-dev-link and reset by
# omarchy-dev-unlink. When absent, force the packaged default instead of
# preserving a stale inherited value.
if [ -f /etc/omarchy.conf ]; then
. /etc/omarchy.conf
: "${OMARCHY_PATH:=/usr/share/omarchy}"
else
OMARCHY_PATH=/usr/share/omarchy
fi
export OMARCHY_PATH
# Only prepend in dev-link mode. On a production install, the binaries are
# already on PATH as /usr/bin/omarchy-* via the omarchy package — prepending
# /usr/share/omarchy/bin would just be noise. omarchy-dev-unlink strips its
# checkout bin/ from the active PATH explicitly, so we don't dedupe here.
if [ "$OMARCHY_PATH" != /usr/share/omarchy ]; then
case ":$PATH:" in
*":${OMARCHY_PATH%/}/bin:"*) ;;
*) PATH="${OMARCHY_PATH%/}/bin:$PATH" ;;
esac
export PATH
fi

Some files were not shown because too many files have changed in this diff Show More