Compare commits

...
284 Commits
Author SHA1 Message Date
Ryan Hughes d63fdd2a23 Avoid transient Hyprland binding module errors 2026-06-16 01:27:43 -04:00
Ryan Hughes 2fdc6f0573 Move stock Hyprland bindings into defaults 2026-06-16 01:25:04 -04:00
Ryan Hughes fd5063dc30 Fix notification popup placement 2026-06-16 01:25:04 -04:00
Ryan Hughes 2a7602a084 Complete upgrade-to-4 update flow 2026-06-15 11:27:54 -04:00
Ryan Hughes 227240d280 Collapse inactive indicator spacing 2026-06-14 21:12:42 -04:00
Ryan Hughes 8d490d525e Select Codex icon by surface background 2026-06-14 20:14:09 -04:00
Ryan Hughes e0eaf8eea8 Use light Codex icon on light themes 2026-06-14 20:09:29 -04:00
Ryan Hughes d8cff94711 Fix model usage layout on vertical bar 2026-06-14 17:40:00 -04:00
Ryan Hughes 4bfa5a6949 Switch default editor to tensaku so we can move things 2026-06-12 22:27:20 -04:00
Ryan Hughes c582e7133a Unify Omarchy migrations 2026-06-12 13:49:46 -04:00
Ryan Hughes 04b0fab64d Remove old test repo 2026-06-12 02:16:01 -04:00
Ryan Hughes fec52e53d2 Cleanup hyprland conf 2026-06-12 02:15:51 -04:00
Ryan Hughes b1e585fec5 Fix nvim theme location 2026-06-12 02:15:22 -04:00
Ryan Hughes 221fb296fc Simplify theme palette tokens 2026-06-11 02:08:02 -04:00
Ryan Hughes 4b2a15b6ea Avoid polkit prompts from shell network status 2026-06-10 13:10:03 -04:00
Ryan Hughes cd0b78cd0f Restore lock surface after shell restart 2026-06-10 12:17:35 -04:00
Ryan Hughes 15614cd4d3 Rename live dev channel to edge 2026-06-10 11:18:36 -04:00
Ryan Hughes c1b9788506 Fix channels 2026-06-09 23:55:58 -04:00
Ryan Hughes 0f5e81143e Move current theme state to local state 2026-06-09 19:48:37 -04:00
Ryan Hughes 29c4a20a86 Fix Claude weekly usage display 2026-06-09 18:11:47 -04:00
Ryan Hughes 7d30407a23 Namespace Discord icon 2026-06-09 15:21:52 -04:00
Ryan Hughes bce9fef4e3 Streamline Hyprland reload guard 2026-06-09 15:13:23 -04:00
Ryan Hughes f79a231cc7 Pause Hyprland reloads during settings updates 2026-06-09 14:20:36 -04:00
Ryan Hughes 9b8c9fd537 Update Omarchy channel switcher 2026-06-09 13:05:30 -04:00
Ryan Hughes 22a42e073a Infer edge channel on --dev 2026-06-09 10:22:55 -04:00
Ryan Hughes 64581ec289 Remove hot link / unlink bits 2026-06-08 12:03:40 -04:00
David Heinemeier Hansson 38bb61b685 Overly defensive 2026-06-08 17:48:09 +02:00
David Heinemeier Hansson 73d47390c4 Improve Bluetooth panel connected devices 2026-06-08 17:20:59 +02:00
David Heinemeier Hansson 42a0b25e01 Merge branch 'omarchy-shell' into quattro 2026-06-08 16:56:51 +02:00
David Heinemeier Hansson 8e65151fb8 Show the whole disk 2026-06-08 16:44:17 +02:00
David Heinemeier Hansson baff7f8080 Make user for now 2026-06-08 16:41:56 +02:00
David Heinemeier Hansson 01bdd06e10 No more elephant 2026-06-08 16:40:54 +02:00
David Heinemeier Hansson cbc7c8f30a Use dua 2026-06-08 16:38:17 +02:00
David Heinemeier Hansson 8807a9c889 Merge branch 'dev' into quattro 2026-06-08 16:36:51 +02:00
Carmine PaolinoandGitHub 9cf1852525 Use dua for disk usage (#6052) 2026-06-08 16:36:05 +02:00
David Heinemeier Hansson 6cec42d97d Merge branch 'omarchy-4' into quattro 2026-06-08 16:28:52 +02:00
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
David Heinemeier Hansson ae7365f937 Fix repeated fingerprint setup 2026-05-27 21:20:39 +02:00
Jason ZimdarsandGitHub 8075b8b0dc Update Basecamp logo asset for version 5 release (#5769)
* Update Basecamp logo asset for version 5 release

* Final Basecamp 5 logo asset
2026-05-25 23:36:54 +02:00
David Heinemeier Hansson 9a5e80f2be Fix compatibility of old tiling.conf with HL 0.55+
Closes #5973
2026-05-25 14:50:56 +02:00
Ryan Hughes f9e41548c1 Bump version 2026-05-23 18:27:38 -04:00
961d4241f0 Install mpv MPRIS support (#5937)
* Install mpv MPRIS support

* omarchy-pkg-add already checks if installed

---------

Co-authored-by: David Heinemeier Hansson <david@hey.com>
2026-05-23 20:49:00 +02:00
David Heinemeier Hansson ea25179b7c Fix HL 0.55 compatible unified clipboard hotkeys 2026-05-23 20:05:46 +02:00
Ryan Hughes b4939c8ccb Fail hard if we don't get the right branch 2026-05-23 02:04:14 -04:00
Ryan Hughes 703581cee2 Fix logs uploading 2026-05-22 12:04:45 -04:00
JisnuandGitHub 9c8f6cf2cb fix: remove pseudotile and fix -1 gradient colors for Hyprland 0.55.x (#5922) 2026-05-21 08:21:42 +02:00
Ryan HughesandGitHub 82f99928d0 Bump version from 3.8.0 to 3.8.1 2026-05-14 13:23:48 -04:00
Ryan HughesandGitHub 6b5baf06ad Merge pull request #5816 from basecamp/fix-reinstall-git-default-branch
Pin omarchy-reinstall-git to master branch
2026-05-14 13:22:35 -04:00
Ryan Hughes 32a82dd15b Pin omarchy-reinstall-git to master branch
GitHub's default branch on basecamp/omarchy is no longer master, so
a plain clone pulls the development branch. Pass --branch master so
reinstalls always land on stable regardless of repo default.
2026-05-14 13:18:46 -04:00
David Heinemeier Hansson b2d95ee24b libretro-vice is now an explosion of minor pkgs 2026-05-10 16:47:29 +02:00
David Heinemeier HanssonandGitHub 7f6abcd743 Merge pull request #5628 from basecamp/rc
Omarchy 3.8.0
2026-05-09 17:20:48 +02:00
David Heinemeier Hansson 44a0123058 Merge branch 'dev' into rc 2026-05-09 16:21:52 +02:00
David Heinemeier Hansson dde76059a8 Merge branch 'dev' into rc 2026-05-09 08:30:09 +02:00
David Heinemeier Hansson 8f43960b8f Merge branch 'dev' into rc 2026-05-08 22:31:44 +02:00
David Heinemeier Hansson 27b598a6e5 Fix guidance 2026-05-08 22:07:38 +02:00
David Heinemeier Hansson 6f281d888f Merge branch 'dev' into rc 2026-05-08 22:06:23 +02:00
David Heinemeier Hansson a865ecc875 Merge branch 'dev' into rc 2026-05-08 22:04:46 +02:00
David Heinemeier Hansson b2ffc1ffa9 Merge branch 'dev' into rc 2026-05-08 21:53:15 +02:00
David Heinemeier Hansson 2a1c1980b4 Merge branch 'dev' into rc 2026-05-08 21:44:27 +02:00
David Heinemeier Hansson d0000ea8cf Merge branch 'dev' into rc 2026-05-08 21:34:52 +02:00
David Heinemeier Hansson cff80ff699 Merge branch 'dev' into rc 2026-05-08 21:16:50 +02:00
David Heinemeier Hansson c8c395b231 Merge branch 'dev' into rc 2026-05-08 21:09:42 +02:00
David Heinemeier Hansson f2f65fdfb2 Merge branch 'dev' into rc 2026-05-07 17:02:13 +02:00
David Heinemeier Hansson 74f319bb6f Merge branch 'dev' into rc 2026-05-07 16:18:28 +02:00
David Heinemeier Hansson 98e9bc6d05 Merge branch 'dev' into rc 2026-05-07 16:16:06 +02:00
David Heinemeier Hansson 121a1e088a Merge branch 'dev' into rc 2026-05-07 16:15:15 +02:00
David Heinemeier Hansson 71e303d2aa Merge branch 'dev' into rc 2026-05-07 15:12:31 +02:00
David Heinemeier Hansson 3a240c7838 Add note about correct perms for migrations 2026-05-07 15:09:53 +02:00
David Heinemeier Hansson c9d1cdce76 Merge branch 'dev' into rc 2026-05-07 15:04:15 +02:00
David Heinemeier Hansson d8a9186326 Merge branch 'dev' into rc 2026-05-07 15:02:25 +02:00
David Heinemeier Hansson 38326c77fc Merge branch 'dev' into rc 2026-05-07 14:54:53 +02:00
David Heinemeier Hansson 66492e57a7 Merge branch 'dev' into rc 2026-05-07 11:23:17 +02:00
David Heinemeier Hansson b6ad01a0fc Merge branch 'dev' into rc 2026-05-07 09:06:25 +02:00
David Heinemeier Hansson cd4fadd502 Merge branch 'dev' into rc 2026-05-06 21:05:41 +02:00
David Heinemeier Hansson d4ffa9e39d Just focus on the window rules 2026-05-06 21:05:24 +02:00
David Heinemeier Hansson dc8ad1dace Use proper .desktop files 2026-05-06 21:03:43 +02:00
David Heinemeier Hansson c80d060321 Merge branch 'dev' into rc 2026-05-06 20:37:36 +02:00
David Heinemeier HanssonandGitHub d827b90a4d Merge branch 'master' into rc 2026-05-06 17:16:10 +02:00
David Heinemeier Hansson e22b70f380 Merge branch 'dev' into rc 2026-05-06 16:52:49 +02:00
David Heinemeier Hansson d59ad099a9 Merge branch 'dev' into rc 2026-05-06 16:52:16 +02:00
Ryan Hughes a3aedb0c4d Version bump 2026-05-04 19:46:42 -04:00
Ryan Hughes 0a5cd43aac Add migration to handle lingering panel_replay addition 2026-05-04 19:46:00 -04:00
David Heinemeier HanssonandGitHub 9aa3858794 Merge pull request #5467 from basecamp/rc
Omarchy 3.7.0
2026-05-04 15:44:57 +02:00
David Heinemeier Hansson 648d8339d2 Merge branch 'dev' into rc 2026-05-04 15:42:37 +02:00
David Heinemeier Hansson 7138044bd2 Merge branch 'dev' into rc 2026-05-04 15:33:23 +02:00
David Heinemeier Hansson 86a38c4a98 Merge branch 'dev' into rc 2026-05-04 14:43:07 +02:00
David Heinemeier Hansson 516882a43c Merge branch 'dev' into rc 2026-05-04 13:57:18 +02:00
David Heinemeier Hansson e3d3ee4044 Merge branch 'dev' into rc 2026-05-04 13:23:37 +02:00
David Heinemeier Hansson 48a771bdac Merge branch 'dev' into rc 2026-05-04 12:38:16 +02:00
David Heinemeier Hansson 03750b31c1 Merge branch 'dev' into rc 2026-05-04 12:23:41 +02:00
David Heinemeier Hansson a6280eed26 Merge branch 'dev' into rc 2026-05-04 11:36:24 +02:00
David Heinemeier Hansson f4a0249ff3 Merge branch 'dev' into rc 2026-05-04 11:18:30 +02:00
David Heinemeier Hansson 011243f4fa Merge branch 'dev' into rc 2026-05-04 10:52:16 +02:00
David Heinemeier Hansson e7f45386d4 Merge branch 'dev' into rc 2026-05-04 10:38:50 +02:00
David Heinemeier Hansson cb3fcf4f60 Merge branch 'dev' into rc 2026-05-04 07:55:06 +02:00
David Heinemeier Hansson d7e3c0dcde Merge branch 'dev' into rc 2026-05-03 22:53:51 +02:00
David Heinemeier Hansson 0edff316da Merge branch 'dev' into rc 2026-05-03 22:02:43 +02:00
David Heinemeier Hansson 774acbf5af Merge branch 'dev' into rc 2026-05-03 19:38:02 +02:00
David Heinemeier Hansson fddaa5e869 Merge branch 'dev' into rc 2026-05-03 13:42:26 +02:00
David Heinemeier Hansson f1a4e9f6e8 Merge branch 'dev' into rc 2026-05-03 13:38:42 +02:00
David Heinemeier Hansson 5cf34963d7 Merge branch 'dev' into rc 2026-05-03 12:47:41 +02:00
David Heinemeier Hansson d40e314d4f Merge branch 'dev' into rc 2026-05-03 12:05:52 +02:00
David Heinemeier Hansson dc249dba95 Merge branch 'dev' into rc 2026-05-03 11:57:19 +02:00
David Heinemeier Hansson 4a7ade9c52 Merge branch 'dev' into rc 2026-05-02 16:43:10 +02:00
David Heinemeier Hansson 06fd369318 Merge branch 'dev' into rc 2026-05-02 14:47:48 +02:00
David Heinemeier Hansson ea7979a057 No quoting needed for bash 5 2026-05-02 13:47:55 +02:00
David Heinemeier Hansson 60966d4553 Merge branch 'dev' into rc 2026-05-02 13:34:38 +02:00
David Heinemeier Hansson 211acd6f9f Merge branch 'dev' into rc 2026-05-02 12:13:33 +02:00
David Heinemeier Hansson 1351cc6442 Merge branch 'dev' into rc 2026-05-02 11:47:54 +02:00
Ryan HughesandGitHub 59b16e7f0f Merge pull request #5541 from dotsilva/dev
fix: "Bistream" typo to "Bitstream"
2026-05-01 23:30:20 -04:00
Bruno da Silva ff23d01fce FIX: Bistream typo to Bitstream in three places 2026-05-01 21:24:41 -03:00
David Heinemeier Hansson a4ab555516 Merge branch 'dev' into rc 2026-05-01 18:33:06 +02:00
David Heinemeier Hansson 1eaddf97ea Quiet down so we don't get useless output spam 2026-05-01 18:27:20 +02:00
David Heinemeier Hansson 8537f41a9d Merge branch 'dev' into rc 2026-05-01 18:22:57 +02:00
David Heinemeier Hansson cf16a6a1a6 Merge branch 'dev' into rc 2026-05-01 14:15:08 +02:00
David Heinemeier Hansson 3d9a875104 Merge branch 'dev' into rc 2026-05-01 11:27:23 +02:00
David Heinemeier Hansson 0b35365f6b Merge branch 'dev' into rc 2026-05-01 11:24:23 +02:00
David Heinemeier Hansson 58c350c171 Merge branch 'dev' into rc 2026-04-30 22:23:48 +02:00
David Heinemeier Hansson efd34a2eea Merge branch 'dev' into rc 2026-04-30 21:45:16 +02:00
David Heinemeier Hansson 0c972657c2 Merge branch 'dev' into rc 2026-04-30 18:32:37 +02:00
David Heinemeier Hansson fa5d054173 Merge branch 'dev' into rc 2026-04-30 18:07:02 +02:00
David Heinemeier Hansson cd7c38c8aa Merge branch 'dev' into rc 2026-04-30 09:40:17 +02:00
David Heinemeier Hansson 9eb0f0e805 Merge branch 'dev' into rc 2026-04-29 20:19:48 +02:00
David Heinemeier Hansson b77f900420 Merge branch 'dev' into rc 2026-04-29 15:49:48 +02:00
David Heinemeier Hansson 1770494fa2 Merge branch 'dev' into rc 2026-04-29 11:23:41 +02:00
David Heinemeier Hansson 53d073da7c Merge branch 'dev' into rc 2026-04-28 09:37:27 +02:00
David Heinemeier Hansson 2fab15c0a7 Merge branch 'dev' into rc 2026-04-27 15:00:25 +02:00
David Heinemeier Hansson 4127c749fb Proper fix for using device dark mode in Chrome 2026-04-24 10:16:31 +02:00
David Heinemeier HanssonandGitHub bc9777c0b8 Merge pull request #5388 from basecamp/rc
Omarchy 3.6.0
2026-04-23 15:12:57 +02:00
David Heinemeier Hansson add6a3c506 Merge branch 'dev' into rc 2026-04-23 14:39:27 +02:00
David Heinemeier Hansson 7dc086bb47 Merge branch 'dev' into rc 2026-04-23 13:03:33 +02:00
David Heinemeier Hansson 8346eea614 Merge branch 'dev' into rc 2026-04-23 12:48:31 +02:00
David Heinemeier Hansson 1abc92aadd Merge branch 'dev' into rc 2026-04-23 11:57:26 +02:00
141edc262f Quote OMARCHY_PATH in migration source command
Agent-Logs-Url: https://github.com/basecamp/omarchy/sessions/36fb96d5-70fd-4365-9550-e7ff5f8735d1

Co-authored-by: dhh <2741+dhh@users.noreply.github.com>
2026-04-22 20:31:31 +00:00
David Heinemeier Hansson 12494bcd8f Merge branch 'dev' into rc 2026-04-22 22:18:40 +02:00
David Heinemeier Hansson 577cd1e8ab Merge branch 'dev' into rc 2026-04-22 21:28:28 +02:00
David Heinemeier Hansson 2f5be43407 Merge branch 'dev' into rc 2026-04-22 20:11:29 +02:00
David Heinemeier Hansson 77c9bca045 Merge branch 'dev' into rc 2026-04-22 16:33:50 +02:00
David Heinemeier Hansson 2537edb1e6 Merge branch 'dev' into rc 2026-04-22 16:31:09 +02:00
David Heinemeier HanssonandGitHub 236a34b23c Merge pull request #5280 from basecamp/rc
Omarchy 3.5.1
2026-04-16 16:12:03 +02:00
David Heinemeier Hansson 2c4b4488c0 Merge branch 'dev' into rc 2026-04-16 16:03:49 +02:00
David Heinemeier Hansson 8f7d64ba78 Merge branch 'dev' into rc 2026-04-16 15:34:24 +02:00
David Heinemeier Hansson 9ece3318ec Merge branch 'dev' into rc 2026-04-16 15:24:11 +02:00
David Heinemeier Hansson d51a3f6b37 Merge branch 'dev' into rc 2026-04-15 18:16:27 +02:00
David Heinemeier Hansson cdb8628502 Merge branch 'dev' into rc 2026-04-15 16:21:03 +02:00
David Heinemeier Hansson b919a5541a Merge branch 'dev' into rc 2026-04-15 16:17:19 +02:00
David Heinemeier Hansson 4ee44c36a6 Merge branch 'dev' into rc 2026-04-15 15:55:55 +02:00
David Heinemeier Hansson d71ddf022a Merge branch 'dev' into rc 2026-04-15 15:02:11 +02:00
David Heinemeier Hansson cd511f77b9 Merge branch 'dev' into rc 2026-04-15 14:36:44 +02:00
David Heinemeier Hansson e6b105d0b2 Merge branch 'dev' into rc 2026-04-15 13:52:05 +02:00
David Heinemeier Hansson 2554fe8555 Merge branch 'dev' into rc 2026-04-15 12:34:23 +02:00
David Heinemeier Hansson feda8b7231 Merge branch 'dev' into rc 2026-04-15 12:11:18 +02:00
David Heinemeier Hansson 46eb5568d9 Merge branch 'dev' into rc 2026-04-15 11:56:00 +02:00
David Heinemeier Hansson 33c92f554b Merge branch 'dev' into rc 2026-04-15 11:49:29 +02:00
David Heinemeier Hansson 997011e985 Merge branch 'dev' into rc 2026-04-13 16:00:11 -07:00
David Heinemeier Hansson 0e126b7916 Merge branch 'dev' into rc 2026-04-13 15:59:23 -07:00
David Heinemeier Hansson f81b3c842d Merge branch 'dev' into rc 2026-04-11 20:48:42 -04:00
David Heinemeier Hansson ecbd912b09 Merge branch 'dev' into rc 2026-04-11 18:02:01 -04:00
David Heinemeier HanssonandGitHub 76d09b29b7 Merge pull request #5192 from basecamp/rc
Omarchy 3.5.0
2026-04-03 19:16:29 +02:00
David Heinemeier Hansson f18dfdd101 Merge branch 'dev' into rc 2026-04-03 11:36:14 +02:00
David Heinemeier Hansson e4757abb80 Merge branch 'dev' into rc 2026-04-03 10:57:18 +02:00
David Heinemeier Hansson fc1cb1a751 Merge branch 'dev' into rc 2026-04-02 18:06:32 +02:00
David Heinemeier Hansson 50d3579d66 Don't use the names here since they break the all-themes setup in omarchy-nvim 2026-04-02 18:04:55 +02:00
David Heinemeier Hansson b72a831bf5 Merge branch 'dev' into rc 2026-04-02 17:39:10 +02:00
David Heinemeier Hansson e2b6b5ed5a Merge branch 'dev' into rc 2026-04-02 17:23:41 +02:00
David Heinemeier Hansson e5bcec53d1 Merge branch 'dev' into rc 2026-04-02 16:07:23 +02:00
David Heinemeier Hansson 1b07638732 Merge branch 'dev' into rc 2026-04-02 16:06:29 +02:00
David Heinemeier Hansson 4a3355e767 Merge branch 'dev' into rc 2026-04-01 18:16:31 +02:00
David Heinemeier Hansson 3b8ab81781 Merge branch 'dev' into rc 2026-03-08 18:29:04 +01:00
David Heinemeier Hansson da0bb37a19 Merge branch 'dev' into rc 2026-03-08 17:54:04 +01:00
692 changed files with 9581 additions and 5743 deletions
+4
View File
@@ -0,0 +1,4 @@
# Python bytecode (orchestrator)
__pycache__/
*.pyc
+22 -17
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,13 +99,13 @@ 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
- `config/` - default configs copied to `~/.config/`
- `default/themed/*.tpl` - templates with `{{ variable }}` placeholders for theme colors
- `themes/*/colors.toml` - theme color definitions (accent, background, foreground, red/green/yellow/blue/magenta/cyan and bright_* variants)
- `themes/*/colors.toml` - theme color definitions (accent, bg, fg, red/green/yellow/blue/magenta/cyan and bright_* variants)
# Tests
@@ -170,19 +171,23 @@ 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 per-user and run through `omarchy-migrate` during `omarchy update` or from the migration notification. Put migrations directly under `migrations/<timestamp>.sh`. Pending state is per-user under `~/.local/state/omarchy/migrations/`, so every user gets a chance to run every migration. Migrations run as the user; privileged work should invoke the appropriate helper or privilege prompt, and no-op when another user already applied it.
To create a new migration, run `omarchy-dev-add-migration --no-edit`.
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=omarchy-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 "dua i /"
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
Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 147 KiB

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

+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
+2 -10
View File
@@ -16,7 +16,7 @@ fi
pkill slurp && exit 0
SCREENSHOT_EDITOR="${OMARCHY_SCREENSHOT_EDITOR:-satty}"
SCREENSHOT_EDITOR="${OMARCHY_SCREENSHOT_EDITOR:-tensaku-edit}"
# Parse --editor flag from any position
ARGS=()
@@ -31,15 +31,7 @@ set -- "${ARGS[@]}"
open_editor() {
local filepath="$1"
if [[ $SCREENSHOT_EDITOR == "satty" ]]; then
satty --filename "$filepath" \
--output-filename "$filepath" \
--actions-on-enter save-to-clipboard \
--save-after-copy \
--copy-command 'wl-copy --type image/png'
else
$SCREENSHOT_EDITOR "$filepath"
fi
"$SCREENSHOT_EDITOR" "$filepath"
}
MODE="${1:-smart}"
+33
View File
@@ -0,0 +1,33 @@
#!/bin/bash
# omarchy:summary=Print the active Omarchy package channel
set -euo pipefail
conf=${OMARCHY_CONFIG_FILE:-/etc/omarchy.conf}
omarchy_path=${OMARCHY_PATH:-/usr/share/omarchy}
if [[ -r $conf ]]; then
configured_path=$(bash -c 'source "$1"; printf "%s\n" "${OMARCHY_PATH:-}"' bash "$conf" 2>/dev/null || true)
[[ -n $configured_path ]] && omarchy_path="$configured_path"
fi
channel=$(omarchy-version-channel 2>/dev/null | awk '{ print $1 }')
if pacman -Q omarchy-dev omarchy-settings-dev >/dev/null 2>&1; then
case "$channel" in
rc) echo rc ;;
edge)
if [[ $omarchy_path == "/usr/share/omarchy" ]]; then
echo dev
else
echo edge
fi
;;
*) echo unknown ;;
esac
elif pacman -Q omarchy omarchy-settings >/dev/null 2>&1 && [[ $channel == "stable" ]]; then
echo stable
else
echo unknown
fi
+114 -13
View File
@@ -1,22 +1,123 @@
#!/bin/bash
# omarchy:summary=Set the Omarchy channel, which dictates what git branch and package repository is used.
# omarchy:args=<stable|rc|edge|dev>
# omarchy:summary=Set the Omarchy package channel.
# omarchy:args=<stable|rc|dev|edge>
# omarchy:requires-sudo=true
if (($# == 0)); then
echo "Usage: omarchy-channel-set [stable|rc|edge|dev]"
exit 1
else
channel="$1"
fi
set -euo pipefail
usage() { echo "Usage: omarchy-channel-set [stable|rc|dev|edge]"; }
fail() { echo "Error: $*" >&2; exit 1; }
confirm_edge() {
cat <<'WARNING'
Edge links Omarchy directly to a mutable source checkout.
This disables package-based protections for the Omarchy code path, including
normal package updates and package-backed snapshot restores. You'll be
responsible for pulling, fixing, and restoring that checkout yourself.
WARNING
if omarchy-cmd-present gum; then
gum confirm --default=false "Enable Edge anyway?"
else
local answer=""
read -r -p "Enable Edge anyway? [y/N] " answer
[[ $answer == "y" || $answer == "Y" || $answer == "yes" || $answer == "YES" ]]
fi
}
choose_edge_checkout() {
local default_path="$HOME/Work/omarchy"
local path="${OMARCHY_EDGE_PATH:-}"
if [[ -z $path ]]; then
if omarchy-cmd-present gum; then
path=$(gum input --value "$default_path" --placeholder "$default_path" --header "Where should Edge checkout live? Existing non-checkout paths will not be overwritten.") || exit 1
else
read -r -p "Edge checkout path [$default_path]: " path
fi
fi
path="${path:-$default_path}"
case "$path" in
"~") path="$HOME" ;;
"~/"*) path="$HOME/${path#~/}" ;;
/*) ;;
*) path="$PWD/$path" ;;
esac
if [[ -e $path && ! -d $path/.git ]]; then
fail "$path already exists and is not a git checkout. Choose an empty path or an existing Omarchy checkout."
fi
if [[ -d $path/.git && ( ! -d $path/bin || ! -d $path/default || ! -d $path/shell ) ]]; then
fail "$path is a git checkout, but it does not look like Omarchy."
fi
printf '%s\n' "$path"
}
sync_edge_checkout() {
local checkout="$1"
if [[ -d $checkout/.git ]]; then
echo "Updating Edge checkout at $checkout"
git -C "$checkout" fetch origin quattro
git -C "$checkout" checkout quattro 2>/dev/null || git -C "$checkout" checkout --track origin/quattro
git -C "$checkout" pull --ff-only origin quattro
else
mkdir -p "$(dirname -- "$checkout")"
git clone --branch quattro --single-branch https://github.com/basecamp/omarchy.git "$checkout"
fi
omarchy-dev-link "$checkout"
}
(( $# > 0 )) || { usage; exit 1; }
edge_checkout=""
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)
pacman_channel=stable
packages=(omarchy omarchy-settings)
;;
rc)
pacman_channel=rc
packages=(omarchy-dev omarchy-settings-dev)
;;
dev)
pacman_channel=edge
packages=(omarchy-dev omarchy-settings-dev)
;;
edge|source)
confirm_edge || { echo "Cancelled."; exit 0; }
edge_checkout=$(choose_edge_checkout)
pacman_channel=edge
packages=(omarchy-dev omarchy-settings-dev)
;;
*)
echo "Unknown channel: $channel" >&2
usage >&2
exit 1
;;
esac
omarchy-refresh-pacman "$pacman_channel"
# --ask 4 accepts omarchy <-> omarchy-dev replacement prompts without file overwrites.
sudo env OMARCHY_UPDATE_PACMAN=1 pacman -S --needed --noconfirm --ask 4 "${packages[@]}"
if [[ -z $edge_checkout ]] && omarchy-cmd-present omarchy-dev-unlink; then
omarchy-dev-unlink
export OMARCHY_PATH=/usr/share/omarchy
fi
omarchy-update -y
if [[ -n $edge_checkout ]]; then
sync_edge_checkout "$edge_checkout"
fi
+1 -1
View File
@@ -29,7 +29,7 @@ open_image() {
local path="$1"
[[ -r $path ]] || exit 1
exec satty --filename "$path" --output-filename "$path"
exec tensaku-edit "$path"
}
open_text() {
+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" ;;
+35 -7
View File
@@ -1,13 +1,41 @@
#!/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=[--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
no_edit=0
while (($#)); do
case "$1" in
--no-edit)
no_edit=1
shift
;;
system|user)
echo "omarchy-dev-add-migration: migration scopes are no longer used; creating a regular migration." >&2
shift
;;
-h|--help)
echo "Usage: omarchy-dev-add-migration [--no-edit]"
exit 0
;;
*)
echo "Unknown option: $1" >&2
echo "Usage: omarchy-dev-add-migration [--no-edit]" >&2
exit 1
;;
esac
done
cd "${OMARCHY_PATH:-$(pwd)}"
mkdir -p migrations
migration_file="migrations/$(git log -1 --format=%cd --date=unix).sh"
touch "$migration_file"
if (( ! no_edit )); then
nvim "$migration_file"
fi
echo $migration_file
printf '%s\n' "$PWD/$migration_file"
+61
View File
@@ -0,0 +1,61 @@
#!/bin/bash
# omarchy:summary=Point Omarchy at a local checkout after reboot
# omarchy:group=dev
# omarchy:args=<path-to-checkout>
# omarchy:examples=omarchy dev link ~/Work/omarchy/omarchy-installer
set -euo pipefail
if (( EUID == 0 )); then
echo "Error: run omarchy-dev-link as your user, not under sudo." >&2
exit 1
fi
if (( $# != 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>
after reboot. This intentionally does not rewrite the running Hyprland,
systemd, shell, or app-launcher environment; reboot to make every layer agree.
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
omarchy_conf_quote() {
local value="$1"
value=${value//\\/\\\\}
value=${value//\"/\\\"}
value=${value//\$/\\\$}
value=${value//\`/\\\`}
printf '"%s"' "$value"
}
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
{
printf 'export OMARCHY_PATH='
omarchy_conf_quote "$target"
printf '\n'
} | sudo tee /etc/omarchy.conf >/dev/null
echo "Pointed Omarchy at $target"
echo
echo "Reboot to activate the linked checkout in Hyprland, app launchers, and new shells."
echo "Run 'omarchy dev unlink' and reboot 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
+42
View File
@@ -0,0 +1,42 @@
#!/bin/bash
# omarchy:summary=Show the current Omarchy dev-link state
# omarchy:group=dev
set -euo pipefail
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: configured"
echo " /etc/omarchy.conf -> OMARCHY_PATH=$configured"
echo " status: reboot required before all session layers use this checkout"
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 [[ ${OMARCHY_PATH:-$default_target} != "$configured" ]]; then
echo
echo "Note: the running session does not match /etc/omarchy.conf. Reboot to settle it."
fi
+453
View File
@@ -0,0 +1,453 @@
#!/bin/bash
# omarchy:summary=Preview an Omarchy theme palette in the terminal
# omarchy:args=[theme-name|theme-dir|colors.toml] [--no-color] [--no-osc|--osc]
# omarchy:examples=omarchy dev theme-preview | omarchy dev theme-preview tokyo-night | omarchy dev theme-preview themes/gruvbox/colors.toml --no-color --no-osc
set -o pipefail
CURRENT_THEME_PATH="$HOME/.local/state/omarchy/current/theme"
USER_THEMES_PATH="$HOME/.config/omarchy/themes"
OMARCHY_THEMES_PATH="$OMARCHY_PATH/themes"
COLOR_OUTPUT=1
APPLY_OSC="auto"
THEME_REF=""
declare -A COLORS
usage() {
cat <<'USAGE'
Usage: omarchy-dev-theme-preview [theme-name|theme-dir|colors.toml] [--no-color] [--no-osc]
Preview a theme palette in the terminal. Without an argument, previews the
current theme from ~/.local/state/omarchy/current/theme/colors.toml.
When stdout is a terminal and color output is enabled, the preview also applies
that theme's OSC palette to the current terminal only. Use --no-osc to suppress
that, or --osc to force it even when stdout is not detected as a terminal.
USAGE
}
for arg in "$@"; do
case "$arg" in
--no-color | --plain)
COLOR_OUTPUT=0
APPLY_OSC="never"
;;
--no-osc)
APPLY_OSC="never"
;;
--osc | --apply-osc | --terminal)
APPLY_OSC="always"
;;
-h | --help)
usage
exit 0
;;
*)
if [[ -n $THEME_REF ]]; then
usage >&2
exit 1
fi
THEME_REF="$arg"
;;
esac
done
if [[ -n ${NO_COLOR:-} ]]; then
COLOR_OUTPUT=0
fi
normalize_theme_name() {
printf '%s' "$1" | sed -E 's/<[^>]+>//g' | tr '[:upper:]' '[:lower:]' | tr ' ' '-'
}
resolve_colors_file() {
local ref="$1"
local theme_name
if [[ -z $ref ]]; then
printf '%s/colors.toml' "$CURRENT_THEME_PATH"
elif [[ -f $ref ]]; then
printf '%s' "$ref"
elif [[ -d $ref && -f $ref/colors.toml ]]; then
printf '%s/colors.toml' "$ref"
else
theme_name=$(normalize_theme_name "$ref")
if [[ -f $USER_THEMES_PATH/$theme_name/colors.toml ]]; then
printf '%s/colors.toml' "$USER_THEMES_PATH/$theme_name"
elif [[ -f $OMARCHY_THEMES_PATH/$theme_name/colors.toml ]]; then
printf '%s/colors.toml' "$OMARCHY_THEMES_PATH/$theme_name"
else
return 1
fi
fi
}
clean_toml_value() {
local value="$1"
value="${value#*[\"\']}"
value="${value%%[\"\']*}"
printf '%s' "$value"
}
load_colors() {
local colors_file="$1"
local key value
while IFS='=' read -r key value; do
key="${key//[\"\' ]/}"
[[ $key && $key != \#* ]] || continue
value=$(clean_toml_value "$value")
COLORS[$key]="$value"
done <"$colors_file"
# Legacy semantic names win when present so older themes keep their intended
# primary text/background colors even if they also had dimmer fg/bg slots.
[[ ${COLORS[background]} ]] && COLORS[bg]="${COLORS[background]}"
[[ ${COLORS[foreground]} ]] && COLORS[fg]="${COLORS[foreground]}"
[[ ${COLORS[bg]} ]] || COLORS[bg]="${COLORS[color0]}"
[[ ${COLORS[fg]} ]] || COLORS[fg]="${COLORS[color7]}"
[[ ${COLORS[light_fg]} ]] || COLORS[light_fg]="${COLORS[color7]:-${COLORS[fg]}}"
[[ ${COLORS[bright_fg]} ]] || COLORS[bright_fg]="${COLORS[color15]:-${COLORS[fg]}}"
[[ ${COLORS[selection_background]} ]] || COLORS[selection_background]="${COLORS[selection]}"
[[ ${COLORS[selection_foreground]} ]] || COLORS[selection_foreground]="${COLORS[bright_fg]}"
if hex_valid "${COLORS[bg]}"; then
[[ ${COLORS[dark_bg]} ]] || COLORS[dark_bg]=$(mix_hex "${COLORS[bg]}" "#000000" 1 4)
[[ ${COLORS[darker_bg]} ]] || COLORS[darker_bg]=$(mix_hex "${COLORS[bg]}" "#000000" 1 2)
fi
}
hex_parts() {
local hex="${1#\#}"
printf '%d %d %d' "0x${hex:0:2}" "0x${hex:2:2}" "0x${hex:4:2}"
}
hex_valid() {
[[ $1 =~ ^#[0-9A-Fa-f]{6}$ ]]
}
luma_sum() {
local r g b
read -r r g b < <(hex_parts "$1")
printf '%d' $((r * 2126 + g * 7152 + b * 722))
}
contrast_ratio() {
local fg="$1"
local bg="$2"
awk -v fg="${fg#\#}" -v bg="${bg#\#}" '
function hex_value(char) { return index("0123456789abcdef", tolower(char)) - 1 }
function hex_pair(hex, idx) { return hex_value(substr(hex, idx, 1)) * 16 + hex_value(substr(hex, idx + 1, 1)) }
function channel(hex, idx) { return hex_pair(hex, idx) / 255 }
function linear(c) { return c <= 0.03928 ? c / 12.92 : ((c + 0.055) / 1.055) ^ 2.4 }
function lum(hex) {
return 0.2126 * linear(channel(hex, 1)) + 0.7152 * linear(channel(hex, 3)) + 0.0722 * linear(channel(hex, 5))
}
BEGIN {
a = lum(fg)
b = lum(bg)
if (a < b) { tmp = a; a = b; b = tmp }
printf "%.2f", (a + 0.05) / (b + 0.05)
}
'
}
ansi_bg() {
local r g b
read -r r g b < <(hex_parts "$1")
printf '\033[48;2;%d;%d;%dm' "$r" "$g" "$b"
}
ansi_fg() {
local r g b
read -r r g b < <(hex_parts "$1")
printf '\033[38;2;%d;%d;%dm' "$r" "$g" "$b"
}
reset_ansi() {
printf '\033[0m'
}
apply_terminal_osc() {
case "$APPLY_OSC" in
never)
return
;;
auto)
[[ -t 1 ]] && (( COLOR_OUTPUT )) || return
;;
always)
;;
esac
if [[ -x $OMARCHY_PATH/bin/omarchy-theme-osc ]]; then
"$OMARCHY_PATH/bin/omarchy-theme-osc" "$colors_file" || true
else
omarchy-theme-osc "$colors_file" || true
fi
}
swatch() {
local hex="$1"
local width="${2:-18}"
local i
if (( COLOR_OUTPUT )) && hex_valid "$hex"; then
ansi_bg "$hex"
for (( i = 0; i < width; i++ )); do
printf ' '
done
reset_ansi
else
for (( i = 0; i < width; i++ )); do
printf '#'
done
fi
}
print_color_row() {
local key="$1"
local hex="${COLORS[$key]}"
[[ -n $hex ]] || return
printf ' %-22s %-9s ' "$key" "$hex"
swatch "$hex" 20
printf '\n'
}
paint_segment() {
local text="$1"
local fg="$2"
local bg="${3:-${COLORS[bg]}}"
if (( COLOR_OUTPUT )) && hex_valid "$fg" && hex_valid "$bg"; then
ansi_bg "$bg"
ansi_fg "$fg"
printf '%s' "$text"
reset_ansi
else
printf '%s' "$text"
fi
}
print_group() {
local title="$1"
shift
local key
printf '\n%s\n' "$title"
for key in "$@"; do
print_color_row "$key"
done
}
print_selection_sample() {
local bg="${COLORS[bg]}"
local fg="${COLORS[fg]}"
local selection_bg="${COLORS[selection_background]}"
local selection_fg="${COLORS[selection_foreground]}"
[[ -n $bg && -n $fg && -n $selection_bg && -n $selection_fg ]] || return
printf '\nSelection sample\n '
if (( COLOR_OUTPUT )) && hex_valid "$bg" && hex_valid "$fg" && hex_valid "$selection_bg" && hex_valid "$selection_fg"; then
ansi_bg "$bg"
ansi_fg "$fg"
printf ' This is some '
ansi_bg "$selection_bg"
ansi_fg "$selection_fg"
printf 'selected text'
ansi_bg "$bg"
ansi_fg "$fg"
printf ' in a sentence '
reset_ansi
printf '\n'
else
printf 'This is some [selected text] in a sentence\n'
fi
}
print_practical_samples() {
printf '\nTerminal/UI samples\n'
printf ' '
paint_segment ' normal text ' "${COLORS[fg]}"
paint_segment ' muted/comment ' "${COLORS[muted]}"
paint_segment ' accent/link ' "${COLORS[accent]}"
paint_segment ' error ' "${COLORS[red]}"
paint_segment ' warning ' "${COLORS[yellow]}"
paint_segment ' success ' "${COLORS[green]}"
printf '\n '
paint_segment ' $ omarchy theme-preview ' "${COLORS[green]}"
paint_segment ' # comment ' "${COLORS[muted]}"
paint_segment ' "string" ' "${COLORS[green]}"
paint_segment ' function() ' "${COLORS[blue]}"
paint_segment ' --flag ' "${COLORS[magenta]}"
printf '\n '
paint_segment ' unselected menu row ' "${COLORS[fg]}"
printf '\n '
paint_segment ' selected menu row ' "${COLORS[selection_foreground]}" "${COLORS[selection_background]}"
printf '\n '
paint_segment ' status/inverse ' "${COLORS[bg]}" "${COLORS[fg]}"
paint_segment ' inactive surface ' "${COLORS[fg]}" "${COLORS[lighter_bg]}"
paint_segment ' urgent ' "${COLORS[bg]}" "${COLORS[red]}"
printf '\n'
}
print_palette_strip() {
local title="$1"
shift
local key hex
printf ' %-12s ' "$title"
for key in "$@"; do
hex="${COLORS[$key]}"
if [[ -n $hex ]]; then
swatch "$hex" 4
printf ' '
fi
done
printf '\n'
}
print_ansi_palette() {
printf '\nANSI palette strips\n'
print_palette_strip normal bg red green yellow blue magenta cyan fg
print_palette_strip bright muted bright_red bright_green bright_yellow bright_blue bright_magenta bright_cyan bright_fg
}
mix_hex() {
local start="$1"
local end="$2"
local index="$3"
local max_index="$4"
local sr sg sb er eg eb r g b
read -r sr sg sb < <(hex_parts "$start")
read -r er eg eb < <(hex_parts "$end")
if (( max_index == 0 )); then
printf '%s' "$start"
return
fi
r=$(((sr * (max_index - index) + er * index + max_index / 2) / max_index))
g=$(((sg * (max_index - index) + eg * index + max_index / 2) / max_index))
b=$(((sb * (max_index - index) + eb * index + max_index / 2) / max_index))
printf '#%02x%02x%02x' "$r" "$g" "$b"
}
print_gradient() {
local start_key="$1"
local end_key="$2"
local start="${COLORS[$start_key]}"
local end="${COLORS[$end_key]}"
local steps=24
local i hex
[[ -n $start && -n $end ]] || return
hex_valid "$start" && hex_valid "$end" || return
printf '\n%s -> %s gradient\n' "$start_key" "$end_key"
printf ' %s ' "$start"
for (( i = 0; i < steps; i++ )); do
hex=$(mix_hex "$start" "$end" "$i" "$((steps - 1))")
if (( COLOR_OUTPUT )); then
ansi_bg "$hex"
printf ' '
reset_ansi
else
printf '%s ' "$hex"
fi
done
printf ' %s\n' "$end"
}
print_neutral_ramp() {
local mode="$1"
local direction sort_flag key hex score entry
local -a keys entries sorted
keys=(darker_bg dark_bg bg lighter_bg selection muted dark_fg fg light_fg bright_fg)
if [[ $mode == "light" ]]; then
direction="lightest -> darkest"
sort_flag="-rn"
else
direction="darkest -> lightest"
sort_flag="-n"
fi
for key in "${keys[@]}"; do
hex="${COLORS[$key]}"
[[ -n $hex ]] || continue
hex_valid "$hex" || continue
score=$(luma_sum "$hex")
entries+=("$score $key")
done
(( ${#entries[@]} > 0 )) || return
mapfile -t sorted < <(printf '%s\n' "${entries[@]}" | sort "$sort_flag")
printf '\nNeutral ramp (%s)\n' "$direction"
for entry in "${sorted[@]}"; do
key="${entry#* }"
print_color_row "$key"
done
}
colors_file=$(resolve_colors_file "$THEME_REF") || {
echo "Theme not found: $THEME_REF" >&2
exit 1
}
if [[ ! -f $colors_file ]]; then
echo "Missing colors.toml: $colors_file" >&2
exit 1
fi
load_colors "$colors_file"
mode="${COLORS[mode]}"
if [[ -z $mode && ${COLORS[bg]} =~ ^#[0-9A-Fa-f]{6}$ ]]; then
if (( $(luma_sum "${COLORS[bg]}") > 1275000 )); then
mode="light"
else
mode="dark"
fi
fi
[[ -n $mode ]] || mode="dark"
theme_label="$THEME_REF"
if [[ -z $theme_label ]]; then
if [[ -f $HOME/.local/state/omarchy/current/theme.name ]]; then
theme_label=$(<"$HOME/.local/state/omarchy/current/theme.name")
else
theme_label="current"
fi
fi
apply_terminal_osc
printf 'Theme: %s\n' "$theme_label"
printf 'File: %s\n' "$colors_file"
printf 'Mode: %s\n' "$mode"
if [[ ${COLORS[fg]} =~ ^#[0-9A-Fa-f]{6}$ && ${COLORS[bg]} =~ ^#[0-9A-Fa-f]{6}$ ]]; then
printf 'fg/bg contrast: %s:1\n' "$(contrast_ratio "${COLORS[fg]}" "${COLORS[bg]}")"
fi
print_gradient bg bright_fg
print_neutral_ramp "$mode"
print_group "Foundation" bg fg accent selection
print_selection_sample
print_practical_samples
print_ansi_palette
print_group "Normal colors" red yellow orange green cyan blue magenta brown
print_group "Bright colors" bright_red bright_yellow bright_green bright_cyan bright_blue bright_magenta bright_fg
+30
View File
@@ -0,0 +1,30 @@
#!/bin/bash
# omarchy:summary=Restore Omarchy to the package install after reboot
# omarchy:group=dev
set -euo pipefail
if (( EUID == 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 so OMARCHY_PATH resolves to /usr/share/omarchy
after reboot. This intentionally does not rewrite the running Hyprland,
systemd, shell, or app-launcher environment; reboot to make every layer agree.
USAGE
exit 0
fi
default_target="/usr/share/omarchy"
printf 'export OMARCHY_PATH="%s"\n' "$default_target" | sudo tee /etc/omarchy.conf >/dev/null
echo "Set /etc/omarchy.conf -> OMARCHY_PATH=$default_target"
echo
echo "Reboot to restore the package install in Hyprland, app launchers, and new shells."
+117
View File
@@ -0,0 +1,117 @@
#!/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),
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
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
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"
for migration in "$OMARCHY_PATH"/migrations/*.sh; do
[[ -f $migration ]] && touch "$state_dir/migrations/$(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 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
+110
View File
@@ -0,0 +1,110 @@
#!/bin/bash
# omarchy:summary=Pause or resume Hyprland config auto-reload around package transactions.
# omarchy:hidden=true
set -euo pipefail
command="${1:-}"
case "$command" in
pause | resume) ;;
*)
echo "Usage: omarchy-hyprland-reload-guard pause|resume" >&2
exit 1
;;
esac
run_root="${OMARCHY_HYPRLAND_RELOAD_GUARD_RUN_ROOT:-/run/user}"
state_dir="${OMARCHY_HYPRLAND_RELOAD_GUARD_STATE_DIR:-/run/omarchy/hyprland-reload-guard}"
hyprctl_bin="${HYPRCTL:-/usr/bin/hyprctl}"
hyprctl_instance() {
local runtime_dir="$1"
local signature="$2"
shift 2
XDG_RUNTIME_DIR="$runtime_dir" "$hyprctl_bin" --instance "$signature" "$@"
}
option_bool() {
local runtime_dir="$1"
local signature="$2"
local option="$3"
hyprctl_instance "$runtime_dir" "$signature" -j getoption "$option" 2>/dev/null | jq -r '.bool'
}
instances() {
local instance_dir signature hypr_dir runtime_dir uid
[[ -d $run_root ]] || return 0
for instance_dir in "$run_root"/*/hypr/*; do
[[ -d $instance_dir ]] || continue
signature="${instance_dir##*/}"
hypr_dir="${instance_dir%/*}"
runtime_dir="${hypr_dir%/*}"
uid="${runtime_dir##*/}"
[[ $uid =~ ^[0-9]+$ ]] || continue
printf '%s\t%s\n' "$runtime_dir" "$signature"
done
}
pause_instance() {
local runtime_dir="$1"
local signature="$2"
local disable_autoreload suppress_errors state_file="$state_dir/$signature"
mkdir -p "$state_dir"
if [[ ! -f $state_file ]]; then
disable_autoreload=$(option_bool "$runtime_dir" "$signature" misc.disable_autoreload) || return 0
suppress_errors=$(option_bool "$runtime_dir" "$signature" debug.suppress_errors) || return 0
printf '%s\t%s\t%s\n' "$runtime_dir" "$disable_autoreload" "$suppress_errors" >"$state_file"
fi
hyprctl_instance "$runtime_dir" "$signature" eval \
'hl.config({ misc = { disable_autoreload = true }, debug = { suppress_errors = true } })' \
>/dev/null 2>&1 || true
}
resume_instance() {
local state_file="$1"
local signature="${state_file##*/}"
local runtime_dir disable_autoreload suppress_errors
IFS=$'\t' read -r runtime_dir disable_autoreload suppress_errors <"$state_file" || return 0
if [[ -d $runtime_dir ]]; then
hyprctl_instance "$runtime_dir" "$signature" eval \
"hl.config({ debug = { suppress_errors = $suppress_errors } })" \
>/dev/null 2>&1 || true
hyprctl_instance "$runtime_dir" "$signature" reload >/dev/null 2>&1 || true
hyprctl_instance "$runtime_dir" "$signature" eval \
"hl.config({ misc = { disable_autoreload = $disable_autoreload }, debug = { suppress_errors = $suppress_errors } })" \
>/dev/null 2>&1 || true
fi
rm -f "$state_file"
}
case "$command" in
pause)
while IFS=$'\t' read -r runtime_dir signature; do
pause_instance "$runtime_dir" "$signature"
done < <(instances)
;;
resume)
[[ -d $state_dir ]] || exit 0
for state_file in "$state_dir"/*; do
[[ -f $state_file ]] || continue
resume_instance "$state_file"
done
rmdir "$state_dir" 2>/dev/null || true
;;
esac
+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 -2
View File
@@ -8,7 +8,7 @@ omarchy-pkg-add helix
mkdir -p ~/.config/helix/themes
# Symlink the rendered Omarchy theme so Helix tracks the active theme
ln -sf ~/.config/omarchy/current/theme/helix.toml ~/.config/helix/themes/omarchy.toml
ln -sf "$HOME/.local/state/omarchy/current/theme/helix.toml" ~/.config/helix/themes/omarchy.toml
# Only seed a config.toml if the user does not already have one
if [[ ! -f ~/.config/helix/config.toml ]]; then
@@ -18,7 +18,7 @@ EOF
fi
# Ensure the symlink target exists for users whose current theme predates this template
if [[ ! -e ~/.config/omarchy/current/theme/helix.toml ]]; then
if [[ ! -e $HOME/.local/state/omarchy/current/theme/helix.toml ]]; then
omarchy-theme-refresh
fi
+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"
+90 -21
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 migrations.
# omarchy:args=[--pending]
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"
# Run any pending migrations
for file in $OMARCHY_PATH/migrations/*.sh; do
filename=$(basename "$file")
usage() {
echo "Usage: omarchy-migrate [--pending]"
}
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
fi
fi
fi
while (($#)); do
case "$1" in
--pending|--check)
mode="pending"
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: $1" >&2
exit 1
;;
esac
done
OMARCHY_PATH="${OMARCHY_PATH:-/usr/share/omarchy}"
STATE_DIR="${OMARCHY_MIGRATION_STATE:-$HOME/.local/state/omarchy/migrations}"
MIGRATIONS_DIR="$OMARCHY_PATH/migrations"
migration_entries() {
[[ -d $MIGRATIONS_DIR ]] || return 0
local file filename
for file in "$MIGRATIONS_DIR"/*.sh; do
[[ -f $file ]] || continue
filename=$(basename "$file")
printf '%s\t%s\t%s\n' "$filename" "$file" "$STATE_DIR/$filename"
done
}
pending_migrations() {
local name file marker
while IFS=$'\t' read -r name file marker; do
[[ -n $name ]] || continue
if [[ ! -f $marker ]]; then
printf '%s\n' "$name"
fi
done < <(migration_entries)
}
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
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
mkdir -p "$STATE_DIR"
[[ -d $MIGRATIONS_DIR ]] || exit 0
while IFS=$'\t' read -r name file marker; do
[[ -n $name ]] || continue
if [[ ! -f $marker ]]; then
echo -e "\e[32m\nRunning migration (${name%.sh})\e[0m"
OMARCHY_PATH="$OMARCHY_PATH" bash -euo pipefail "$file"
mkdir -p "$(dirname "$marker")"
touch "$marker"
fi
done < <(migration_entries)
+35
View File
@@ -0,0 +1,35 @@
#!/bin/bash
# omarchy:summary=Notify the user when Omarchy has pending migrations
set -euo pipefail
pending_migrations=$(omarchy-migrate --pending 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 migration is available. Click to run it in a terminal."
else
message="$pending_count new Omarchy 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 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
+1 -1
View File
@@ -37,7 +37,7 @@ print_status() {
nm=$(nmcli -t -f GENERAL.STATE,GENERAL.CONNECTION dev show "$device" 2>/dev/null)
state=$(awk -F: '$1 == "GENERAL.STATE" { print $2; exit }' <<<"$nm")
ssid=$(awk -F: '$1 == "GENERAL.CONNECTION" { print $2; exit }' <<<"$nm")
signal=$(nmcli -t -f IN-USE,SIGNAL dev wifi list ifname "$device" 2>/dev/null | awk -F: '$1 == "*" { print $2; exit }')
signal=$(nmcli -t -f IN-USE,SIGNAL dev wifi list ifname "$device" --rescan no 2>/dev/null | awk -F: '$1 == "*" { print $2; exit }')
freq=$(iw dev "$device" link 2>/dev/null | awk '/freq:/ { print $2; exit }')
if [[ $state != 100* ]]; then
+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
+2 -2
View File
@@ -2,7 +2,7 @@
# omarchy:summary=Preview a Plymouth boot screen with custom colors and logo
# omarchy:args=<background-hex> <text-hex> <path-to-logo.png> <output-path>
# omarchy:examples=omarchy plymouth preview '#1d2021' '#ebdbb2' ~/.config/omarchy/current/theme/plymouth/logo.png /tmp/plymouth-preview.png
# omarchy:examples=omarchy plymouth preview '#1d2021' '#ebdbb2' ~/.local/state/omarchy/current/theme/plymouth/logo.png /tmp/plymouth-preview.png
# Render a Plymouth login-screen preview PNG by compositing the staged omarchy
# theme assets (recolored with the given text color) onto the background.
@@ -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
+3 -3
View File
@@ -2,7 +2,7 @@
# omarchy:summary=Set the Plymouth boot theme colors and logo
# omarchy:args=<background-hex> <text-hex> <path-to-logo.png>
# omarchy:examples=omarchy plymouth set '#1d2021' '#ebdbb2' ~/.config/omarchy/current/theme/plymouth/logo.png
# omarchy:examples=omarchy plymouth set '#1d2021' '#ebdbb2' ~/.local/state/omarchy/current/theme/plymouth/logo.png
# omarchy:requires-sudo=true
# Configure the Plymouth boot theme with a custom background color, text color, and logo.
@@ -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" \
+33 -2
View File
@@ -20,7 +20,38 @@ else
theme_dir="$OMARCHY_PATH/themes/$theme"
fi
bg=$(awk -F'"' '/^background/{print $2}' "$theme_dir/colors.toml")
text=$(awk -F'"' '/^foreground/{print $2}' "$theme_dir/colors.toml")
theme_color() {
local key="$1"
local fallback="$2"
awk -F= -v key="$key" -v fallback="$fallback" '
function clean(raw) {
gsub(/^[[:space:]]+|[[:space:]]+$/, "", raw)
if (raw ~ /^"/) {
sub(/^"/, "", raw)
sub(/".*$/, "", raw)
}
return raw
}
{
field = $1
gsub(/^[[:space:]]+|[[:space:]]+$/, "", field)
if (field == key) {
print clean($2)
found = 1
exit
}
if (field == fallback) fallback_value = clean($2)
}
END {
if (!found && fallback_value != "") print fallback_value
}
' "$theme_dir/colors.toml"
}
bg=$(theme_color background bg)
text=$(theme_color foreground fg)
exec omarchy-plymouth-set "$bg" "$text" "$theme_dir/unlock.png"
+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
+3 -2
View File
@@ -9,5 +9,6 @@ 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/
+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
+2 -3
View File
@@ -8,8 +8,8 @@ if gum confirm "Are you sure you want to remove all preinstalled web apps, TUI w
omarchy-webapp-remove-all
omarchy-tui-remove-all
[[ -f ~/.config/hypr/bindings.lua ]] && cp ~/.config/hypr/bindings.lua ~/.config/hypr/bindings.lua.bak
cp "$OMARCHY_PATH/default/hypr/plain-bindings.lua" ~/.config/hypr/bindings.lua
mkdir -p ~/.local/state/omarchy
touch ~/.local/state/omarchy/preinstalls-removed
hyprctl reload
# Remove mise stubs
@@ -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 \
+168 -3
View File
@@ -3,13 +3,178 @@
# 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
import_env_from_pid() {
local pid=$1 entry key
[[ -r /proc/$pid/environ ]] || return 1
while IFS= read -r -d '' entry; do
key=${entry%%=*}
case $key in
DBUS_SESSION_BUS_ADDRESS | DISPLAY | HYPRLAND_INSTANCE_SIGNATURE | LANG | LC_ALL | LC_CTYPE | QT_QPA_PLATFORM | WAYLAND_DISPLAY | XDG_CURRENT_DESKTOP | XDG_RUNTIME_DIR | XDG_SESSION_TYPE)
[[ -n ${!key:-} ]] || export "$entry"
;;
esac
done <"/proc/$pid/environ"
}
import_graphical_session_env() {
local current_user hypr_dir pid wayland_socket x11_socket
current_user=${USER:-$(id -un)}
for pid in $(pgrep -xu "$current_user" quickshell 2>/dev/null || true); do
import_env_from_pid "$pid" || true
done
for pid in $(pgrep -u "$UID" -f '/omarchy-hyprland-monitor-watch($| )' 2>/dev/null || true); do
import_env_from_pid "$pid" || true
done
if [[ -z ${XDG_RUNTIME_DIR:-} && -d /run/user/$UID ]]; then
export XDG_RUNTIME_DIR="/run/user/$UID"
fi
if [[ -z ${WAYLAND_DISPLAY:-} && -n ${XDG_RUNTIME_DIR:-} ]]; then
for wayland_socket in "$XDG_RUNTIME_DIR"/wayland-*; do
[[ -S $wayland_socket ]] || continue
export WAYLAND_DISPLAY=${wayland_socket##*/}
break
done
fi
if [[ -z ${DISPLAY:-} ]]; then
for x11_socket in /tmp/.X11-unix/X*; do
[[ -S $x11_socket ]] || continue
export DISPLAY=:${x11_socket##*X}
break
done
fi
if [[ -z ${HYPRLAND_INSTANCE_SIGNATURE:-} && -n ${XDG_RUNTIME_DIR:-} && -d $XDG_RUNTIME_DIR/hypr ]]; then
hypr_dir=$(find "$XDG_RUNTIME_DIR/hypr" -mindepth 1 -maxdepth 1 -type d -printf '%T@ %p\n' 2>/dev/null | sort -n | tail -n 1 | cut -d' ' -f2-)
[[ -n $hypr_dir ]] && export HYPRLAND_INSTANCE_SIGNATURE=${hypr_dir##*/}
fi
if [[ -z ${LANG:-} || $LANG == "C" || $LANG == "POSIX" ]]; then
if locale -a 2>/dev/null | grep -qxF "C.utf8"; then
export LANG="C.utf8"
else
export LANG="C.UTF-8"
fi
fi
if [[ -z ${QT_QPA_PLATFORM:-} ]]; then
export QT_QPA_PLATFORM="wayland;xcb"
fi
if [[ -z ${DBUS_SESSION_BUS_ADDRESS:-} && -n ${XDG_RUNTIME_DIR:-} && -S $XDG_RUNTIME_DIR/bus ]]; then
export DBUS_SESSION_BUS_ADDRESS="unix:path=$XDG_RUNTIME_DIR/bus"
fi
}
require_graphical_session_env() {
local missing=()
[[ -n ${XDG_RUNTIME_DIR:-} ]] || missing+=(XDG_RUNTIME_DIR)
[[ -n ${WAYLAND_DISPLAY:-} || -n ${DISPLAY:-} ]] || missing+=(WAYLAND_DISPLAY)
if [[ -n ${XDG_RUNTIME_DIR:-} && -d $XDG_RUNTIME_DIR/hypr && -z ${HYPRLAND_INSTANCE_SIGNATURE:-} ]]; then
missing+=(HYPRLAND_INSTANCE_SIGNATURE)
fi
if (( ${#missing[@]} > 0 )); then
printf 'Refusing to restart Omarchy shell; missing graphical session environment: %s\n' "${missing[*]}" >&2
exit 1
fi
}
hyprland_session_locked() {
local monitors
if monitors=$(hyprctl -j monitors 2>/dev/null); then
[[ $monitors == *'"LOCK"'* ]] && return 0
fi
monitors=$(hyprctl monitors 2>/dev/null) || return 1
[[ $monitors == *"session lock"* ]]
}
shell_quote() {
printf "'"
printf "%s" "$1" | sed "s/'/'\\\\''/g"
printf "'"
}
lua_quote() {
local value=$1
value=${value//\\/\\\\}
value=${value//\"/\\\"}
value=${value//$'\n'/\\n}
printf '"%s"' "$value"
}
launch_shell() {
local launch_command
launch_command="env OMARCHY_PATH=$(shell_quote "$omarchy_root") PATH=$(shell_quote "$PATH") quickshell -n -p $(shell_quote "$CONFIG_DIR")"
if [[ -n ${HYPRLAND_INSTANCE_SIGNATURE:-} ]] && omarchy-cmd-present hyprctl; then
if hyprctl dispatch "hl.dsp.exec_cmd($(lua_quote "$launch_command"))" >/dev/null 2>&1; then
return 0
fi
if hyprctl dispatch exec "$launch_command" >/dev/null 2>&1; then
return 0
fi
fi
setsid quickshell -n -p "$CONFIG_DIR" >/dev/null 2>&1 &
}
restore_hyprland_session_lock() {
local attempt
for (( attempt = 0; attempt < 50; attempt++ )); do
if "$omarchy_shell_bin" shell ping >/dev/null 2>&1; then
"$omarchy_shell_bin" lock lock >/dev/null 2>&1 || true
return 0
fi
sleep 0.1
done
echo "Omarchy shell restarted while Hyprland was session-locked, but lock IPC did not become ready." >&2
}
import_graphical_session_env
require_graphical_session_env
hyprland_was_session_locked=0
hyprland_session_locked && hyprland_was_session_locked=1
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
pkill -x quickshell 2>/dev/null || true
sleep 0.2
setsid quickshell -n -p "$CONFIG_DIR" >/dev/null 2>&1 &
launch_shell
if (( hyprland_was_session_locked )); then
restore_hyprland_session_lock
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
+5 -5
View File
@@ -57,12 +57,12 @@ echo -e "\e[32mSetting up fingerprint scanner for authentication.\n\e[0m"
# Install required packages
echo "Installing required packages..."
installed_libfprint=$(pacman -Qq libfprint 2>/dev/null || true)
# libfprint-git provides+conflicts libfprint; pacman -S --noconfirm
# defaults the conflict prompt to N and aborts. Pre-remove libfprint
# with -Rdd so the install goes silent. -Rdd (not omarchy-pkg-drop's
# -Rns) is required because fprintd requires libfprint; the dep is
# re-satisfied immediately by libfprint-git's provides=libfprint.
if omarchy-pkg-present libfprint; then
# defaults the conflict prompt to N and aborts. Pre-remove the exact
# libfprint package, but not an installed provider like libfprint-git.
if [[ $installed_libfprint == "libfprint" ]]; then
sudo pacman -Rdd --noconfirm libfprint
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
@@ -75,7 +75,7 @@ valid_hex "$background_color" || fallback
omarchy-cmd-present magick || fallback
if [[ -z $background_path ]]; then
background_path=$(readlink -f "$HOME/.config/omarchy/current/background" 2>/dev/null || true)
background_path=$(readlink -f "$HOME/.local/state/omarchy/current/background" 2>/dev/null || true)
fi
[[ -f $background_path ]] || fallback
+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"
+2 -2
View File
@@ -2,9 +2,9 @@
# omarchy:summary=Cache background switcher thumbnails for the current theme
theme_name=$(cat "$HOME/.config/omarchy/current/theme.name" 2>/dev/null)
theme_name=$(cat "$HOME/.local/state/omarchy/current/theme.name" 2>/dev/null)
omarchy-menu-images \
--cache-only \
"$HOME/.config/omarchy/current/theme/backgrounds" \
"$HOME/.local/state/omarchy/current/theme/backgrounds" \
"$HOME/.config/omarchy/backgrounds/$theme_name"
+1 -1
View File
@@ -3,7 +3,7 @@
# omarchy:summary=Show current background
# omarchy:examples=omarchy theme bg current
BACKGROUND_PATH=$(readlink -f "$HOME/.config/omarchy/current/background" 2>/dev/null)
BACKGROUND_PATH=$(readlink -f "$HOME/.local/state/omarchy/current/background" 2>/dev/null)
if [[ -n $BACKGROUND_PATH ]]; then
basename -- "$BACKGROUND_PATH" | perl -pe 's/\.[^.]+$//; s/^\d+-//; s/-/ /g; s/\b(\w)/\U$1/g'
+1 -1
View File
@@ -2,7 +2,7 @@
# omarchy:summary=Open the current theme's user background folder
CURRENT_THEME_NAME=$(cat "$HOME/.config/omarchy/current/theme.name")
CURRENT_THEME_NAME=$(cat "$HOME/.local/state/omarchy/current/theme.name")
THEME_USER_BACKGROUNDS="$HOME/.config/omarchy/backgrounds/$CURRENT_THEME_NAME"
mkdir -p "$THEME_USER_BACKGROUNDS"
+3 -3
View File
@@ -3,10 +3,10 @@
# omarchy:summary=Cycle to the next background for the current theme
# omarchy:examples=omarchy theme bg next
THEME_NAME=$(cat "$HOME/.config/omarchy/current/theme.name" 2>/dev/null)
THEME_BACKGROUNDS_PATH="$HOME/.config/omarchy/current/theme/backgrounds/"
THEME_NAME=$(cat "$HOME/.local/state/omarchy/current/theme.name" 2>/dev/null)
THEME_BACKGROUNDS_PATH="$HOME/.local/state/omarchy/current/theme/backgrounds/"
USER_BACKGROUNDS_PATH="$HOME/.config/omarchy/backgrounds/$THEME_NAME/"
CURRENT_BACKGROUND_LINK="$HOME/.config/omarchy/current/background"
CURRENT_BACKGROUND_LINK="$HOME/.local/state/omarchy/current/background"
mapfile -d '' -t BACKGROUNDS < <(
find -L "$USER_BACKGROUNDS_PATH" "$THEME_BACKGROUNDS_PATH" -maxdepth 1 -type f \
+1 -1
View File
@@ -10,7 +10,7 @@ if [[ -z $1 ]]; then
fi
BACKGROUND="$(realpath "$1")"
CURRENT_BACKGROUND_LINK="$HOME/.config/omarchy/current/background"
CURRENT_BACKGROUND_LINK="$HOME/.local/state/omarchy/current/background"
if [[ ! -f $BACKGROUND ]]; then
echo "File does not exist: $BACKGROUND" >&2
+3 -3
View File
@@ -5,10 +5,10 @@
# omarchy:name=bg-switcher
# omarchy:aliases=omarchy background
theme_name=$(cat "$HOME/.config/omarchy/current/theme.name" 2>/dev/null)
current_background=$(readlink -f "$HOME/.config/omarchy/current/background" 2>/dev/null)
theme_name=$(cat "$HOME/.local/state/omarchy/current/theme.name" 2>/dev/null)
current_background=$(readlink -f "$HOME/.local/state/omarchy/current/background" 2>/dev/null)
omarchy-menu-images \
--selected "$current_background" \
"$HOME/.config/omarchy/current/theme/backgrounds" \
"$HOME/.local/state/omarchy/current/theme/backgrounds" \
"$HOME/.config/omarchy/backgrounds/$theme_name"
+6 -20
View File
@@ -154,13 +154,6 @@ if [[ -z $foreground ]]; then
foreground=$(extract_color_in_section "colors" "primary.foreground")
fi
# Extract cursor color (from [colors.cursor] section)
cursor=$(extract_color_in_section "colors.cursor" "cursor")
if [[ -z $cursor ]]; then
cursor=$(extract_color_in_section "colors" "cursor.cursor")
fi
# Extract selection colors
selection_background=$(extract_color_in_section "colors.selection" "background")
@@ -168,29 +161,22 @@ if [[ -z $selection_background ]]; then
selection_background=$(extract_color_in_section "colors" "selection.background")
fi
selection_foreground=$(extract_color_in_section "colors.selection" "text")
if [[ -z $selection_foreground ]]; then
selection_foreground=$(extract_color_in_section "colors" "selection.text")
fi
# Apply defaults
background=${background:-$color0}
foreground=${foreground:-$color7}
cursor=${cursor:-$foreground}
color0=$background
color7=$foreground
selection_background=${selection_background:-$foreground}
selection_foreground=${selection_foreground:-$background}
accent=$color4
mkdir -p "$THEME_SOURCE"
cat > "$COLORS_OUTPUT" <<EOF
accent = "$accent"
cursor = "$cursor"
foreground = "$foreground"
background = "$background"
selection_foreground = "$selection_foreground"
selection_background = "$selection_background"
selection = "$selection_background"
bg = "$background"
fg = "$foreground"
color0 = "$color0"
color1 = "$color1"
+1 -1
View File
@@ -3,7 +3,7 @@
# omarchy:summary=Show current theme
# omarchy:examples=omarchy theme current
THEME_NAME_PATH="$HOME/.config/omarchy/current/theme.name"
THEME_NAME_PATH="$HOME/.local/state/omarchy/current/theme.name"
if [[ -f $THEME_NAME_PATH ]]; then
cat $THEME_NAME_PATH | sed -E 's/(^|-)([a-z])/\1\u\2/g; s/-/ /g'
+16 -1
View File
@@ -3,7 +3,7 @@
# omarchy:summary=Print OSC sequences for an Omarchy color theme
# omarchy:hidden=true
theme="${1:-$HOME/.config/omarchy/current/theme/colors.toml}"
theme="${1:-$HOME/.local/state/omarchy/current/theme/colors.toml}"
[[ -f $theme ]] || exit 0
@@ -33,6 +33,13 @@ awk -F= '
}
END {
if (colors["background"] != "") colors["bg"] = colors["background"]
if (colors["foreground"] != "") colors["fg"] = colors["foreground"]
if (colors["bg"] != "") colors["background"] = colors["bg"]
if (colors["fg"] != "") colors["foreground"] = colors["fg"]
if (colors["bg"] != "") colors["color0"] = colors["bg"]
if (colors["fg"] != "") colors["color7"] = colors["fg"]
alias_color("color0", "bg")
alias_color("color0", "background")
alias_color("color1", "red")
@@ -63,6 +70,14 @@ awk -F= '
alias_color("color14", "cyan")
alias_color("color15", "bright_fg")
alias_color("color15", "foreground")
alias_color("light_fg", "color7")
alias_color("light_fg", "fg")
alias_color("bright_fg", "color15")
alias_color("bright_fg", "fg")
if (colors["bright_fg"] != "") colors["cursor"] = colors["bright_fg"]
if (colors["selection_background"] == "" && colors["selection"] != "") colors["selection_background"] = colors["selection"]
if (colors["selection_foreground"] == "") colors["selection_foreground"] = colors["bright_fg"]
if (colors["foreground"] != "") printf "\033]10;%s\007", colors["foreground"]
if (colors["background"] != "") printf "\033]11;%s\007", colors["background"]
+1 -1
View File
@@ -2,7 +2,7 @@
# omarchy:summary=Refresh the current theme from its templates.
THEME_NAME_PATH="$HOME/.config/omarchy/current/theme.name"
THEME_NAME_PATH="$HOME/.local/state/omarchy/current/theme.name"
if [[ -f $THEME_NAME_PATH ]]; then
OMARCHY_THEME_SKIP_BACKGROUND=1 omarchy-theme-set "$(cat $THEME_NAME_PATH)"
-1
View File
@@ -19,7 +19,6 @@ else
fi
THEMES_DIR="$HOME/.config/omarchy/themes"
CURRENT_DIR="$HOME/.config/omarchy/current"
THEME_PATH="$THEMES_DIR/$THEME_NAME"
# Ensure a theme was set
+47 -23
View File
@@ -9,9 +9,9 @@ if [[ -z $1 ]]; then
exit 1
fi
CURRENT_THEME_PATH="$HOME/.config/omarchy/current/theme"
NEXT_THEME_PATH="$HOME/.config/omarchy/current/next-theme"
CURRENT_BACKGROUND_LINK="$HOME/.config/omarchy/current/background"
CURRENT_THEME_PATH="$HOME/.local/state/omarchy/current/theme"
NEXT_THEME_PATH="$HOME/.local/state/omarchy/current/next-theme"
CURRENT_BACKGROUND_LINK="$HOME/.local/state/omarchy/current/background"
BACKGROUND_TRANSITION_CACHE="$HOME/.cache/omarchy/background-transitions"
THEME_SET_LOCK="${XDG_RUNTIME_DIR:-/tmp}/omarchy-theme-set.lock"
USER_THEMES_PATH="$HOME/.config/omarchy/themes"
@@ -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
@@ -148,13 +165,18 @@ rm -rf "$CURRENT_THEME_PATH"
mv "$NEXT_THEME_PATH" "$CURRENT_THEME_PATH"
# Store theme name for reference
echo "$THEME_NAME" >"$HOME/.config/omarchy/current/theme.name"
echo "$THEME_NAME" >"$HOME/.local/state/omarchy/current/theme.name"
# Make the running shell pick up the new palette immediately while the rest of
# 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
+1 -1
View File
@@ -3,7 +3,7 @@
# omarchy:summary=Apply the current theme color to Chromium, Chrome, Edge, and Brave
# omarchy:hidden=true
CHROMIUM_THEME=~/.config/omarchy/current/theme/chromium.theme
CHROMIUM_THEME=$HOME/.local/state/omarchy/current/theme/chromium.theme
if [[ -f $CHROMIUM_THEME ]]; then
THEME_RGB_COLOR=$(<$CHROMIUM_THEME)
+1 -1
View File
@@ -3,7 +3,7 @@
# omarchy:summary=Apply current Omarchy theme colors to running Foot terminals
# omarchy:hidden=true
colors_toml=~/.config/omarchy/current/theme/colors.toml
colors_toml=$HOME/.local/state/omarchy/current/theme/colors.toml
if [[ ! -f $colors_toml ]] || ! pgrep -x foot >/dev/null; then
exit 0
+9 -2
View File
@@ -3,7 +3,14 @@
# omarchy:summary=Apply the current theme to GNOME color mode and icon settings
# omarchy:hidden=true
THEME_DIR=~/.config/omarchy/current/theme
# 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=$HOME/.local/state/omarchy/current/theme
COLORS_FILE="$THEME_DIR/colors.toml"
# In-tree light themes now declare `mode = "light"` in colors.toml instead of
@@ -43,7 +50,7 @@ else
fi
# Change gnome icon theme color
GNOME_ICONS_THEME=~/.config/omarchy/current/theme/icons.theme
GNOME_ICONS_THEME=$HOME/.local/state/omarchy/current/theme/icons.theme
if [[ -f $GNOME_ICONS_THEME ]]; then
gsettings set org.gnome.desktop.interface icon-theme "$(<$GNOME_ICONS_THEME)"
else
+1 -1
View File
@@ -3,7 +3,7 @@
# omarchy:summary=Apply the current theme keyboard color to ASUS ROG keyboards
# omarchy:hidden=true
ASUSCTL_THEME=~/.config/omarchy/current/theme/keyboard.rgb
ASUSCTL_THEME=$HOME/.local/state/omarchy/current/theme/keyboard.rgb
if omarchy-cmd-present asusctl; then
asusctl aura effect static -c $(sed 's/^#//' $ASUSCTL_THEME)
+1 -1
View File
@@ -3,7 +3,7 @@
# omarchy:summary=Apply the current theme keyboard color to Framework Laptop 16 keyboards
# omarchy:hidden=true
FRAMEWORK16_THEME=~/.config/omarchy/current/theme/keyboard.rgb
FRAMEWORK16_THEME=$HOME/.local/state/omarchy/current/theme/keyboard.rgb
if omarchy-cmd-present qmk_hid && [[ -f $FRAMEWORK16_THEME ]]; then
hex=$(cat "$FRAMEWORK16_THEME")
+1 -1
View File
@@ -3,7 +3,7 @@
# omarchy:summary=Sync Omarchy theme to all Obsidian vaults
# omarchy:hidden=true
CURRENT_THEME_DIR="$HOME/.config/omarchy/current/theme"
CURRENT_THEME_DIR="$HOME/.local/state/omarchy/current/theme"
[[ -f $CURRENT_THEME_DIR/obsidian.css ]] || exit 0
+1 -1
View File
@@ -6,7 +6,7 @@
set -euo pipefail
CURRENT_THEME_PATH="$HOME/.config/omarchy/current/theme"
CURRENT_THEME_PATH="$HOME/.local/state/omarchy/current/theme"
PI_SOURCE_PATH="$CURRENT_THEME_PATH/pi.json"
PI_AGENT_DIR="$HOME/.pi/agent"
PI_THEME_DIR="$PI_AGENT_DIR/themes"
+27 -14
View File
@@ -5,7 +5,7 @@
TEMPLATES_DIR="$OMARCHY_PATH/default/themed"
USER_TEMPLATES_DIR="$HOME/.config/omarchy/themed"
NEXT_THEME_DIR="$HOME/.config/omarchy/current/next-theme"
NEXT_THEME_DIR="$HOME/.local/state/omarchy/current/next-theme"
COLORS_FILE="$NEXT_THEME_DIR/colors.toml"
declare -A THEME_COLORS
@@ -382,8 +382,8 @@ resolve_theme_mode() {
if [[ -f $NEXT_THEME_DIR/light.mode ]]; then
THEME_COLORS[mode]="light"
elif [[ ${THEME_COLORS[background]} =~ ^#[0-9A-Fa-f]{6}$ ]]; then
bg_hex="${THEME_COLORS[background]#\#}"
elif [[ ${THEME_COLORS[bg]} =~ ^#[0-9A-Fa-f]{6}$ ]]; then
bg_hex="${THEME_COLORS[bg]#\#}"
lum=$(( $(printf "%d" "0x${bg_hex:0:2}") + $(printf "%d" "0x${bg_hex:2:2}") + $(printf "%d" "0x${bg_hex:4:2}") ))
(( lum > 382 )) && THEME_COLORS[mode]="light" || THEME_COLORS[mode]="dark"
else
@@ -407,10 +407,20 @@ if [[ -f $COLORS_FILE ]]; then
THEME_COLORS[$key]="$value"
done <"$COLORS_FILE"
# Legacy compatibility: map ANSI color0..color15 and raw bg/fg to semantic names
# Canonical palette keys are bg/fg. Preserve older themes that still define
# background/foreground by treating those semantic values as the source of
# truth, then expose the old names as template aliases for user templates.
[[ ${THEME_COLORS[background]} ]] && THEME_COLORS[bg]="${THEME_COLORS[background]}"
[[ ${THEME_COLORS[foreground]} ]] && THEME_COLORS[fg]="${THEME_COLORS[foreground]}"
[[ ${THEME_COLORS[bg]} ]] || THEME_COLORS[bg]="${THEME_COLORS[color0]}"
[[ ${THEME_COLORS[fg]} ]] || THEME_COLORS[fg]="${THEME_COLORS[color7]}"
[[ ${THEME_COLORS[bg]} ]] && THEME_COLORS[background]="${THEME_COLORS[bg]}"
[[ ${THEME_COLORS[fg]} ]] && THEME_COLORS[foreground]="${THEME_COLORS[fg]}"
[[ ${THEME_COLORS[bg]} ]] && THEME_COLORS[color0]="${THEME_COLORS[bg]}"
[[ ${THEME_COLORS[fg]} ]] && THEME_COLORS[color7]="${THEME_COLORS[fg]}"
# Legacy compatibility: map ANSI color0..color15 to semantic names.
declare -A legacy_alias=(
[bg]=background
[fg]=foreground
[red]=color1
[green]=color2
[yellow]=color3
@@ -430,18 +440,21 @@ if [[ -f $COLORS_FILE ]]; then
alias_theme_color magenta purple
alias_theme_color bright_magenta bright_purple
[[ ${THEME_COLORS[light_fg]} ]] || THEME_COLORS[light_fg]="${THEME_COLORS[color7]:-${THEME_COLORS[foreground]}}"
[[ ${THEME_COLORS[bright_fg]} ]] || THEME_COLORS[bright_fg]="${THEME_COLORS[color15]:-${THEME_COLORS[foreground]}}"
[[ ${THEME_COLORS[lighter_bg]} ]] || THEME_COLORS[lighter_bg]="${THEME_COLORS[color0]:-${THEME_COLORS[background]}}"
[[ ${THEME_COLORS[dark_fg]} ]] || THEME_COLORS[dark_fg]="${THEME_COLORS[color8]:-${THEME_COLORS[foreground]}}"
[[ ${THEME_COLORS[light_fg]} ]] || THEME_COLORS[light_fg]="${THEME_COLORS[color7]:-${THEME_COLORS[fg]}}"
[[ ${THEME_COLORS[bright_fg]} ]] || THEME_COLORS[bright_fg]="${THEME_COLORS[color15]:-${THEME_COLORS[fg]}}"
THEME_COLORS[cursor]="${THEME_COLORS[bright_fg]}"
[[ ${THEME_COLORS[lighter_bg]} ]] || THEME_COLORS[lighter_bg]="${THEME_COLORS[color0]:-${THEME_COLORS[bg]}}"
[[ ${THEME_COLORS[dark_fg]} ]] || THEME_COLORS[dark_fg]="${THEME_COLORS[color8]:-${THEME_COLORS[fg]}}"
[[ ${THEME_COLORS[muted]} ]] || THEME_COLORS[muted]="${THEME_COLORS[color8]:-${THEME_COLORS[dark_fg]}}"
[[ ${THEME_COLORS[selection]} ]] || THEME_COLORS[selection]="${THEME_COLORS[selection_background]:-${THEME_COLORS[color8]:-${THEME_COLORS[color0]}}}"
[[ ${THEME_COLORS[orange]} ]] || THEME_COLORS[orange]="${THEME_COLORS[yellow]}"
[[ ${THEME_COLORS[selection]} ]] || THEME_COLORS[selection]="${THEME_COLORS[selection_background]:-${THEME_COLORS[color8]:-${THEME_COLORS[color0]:-${THEME_COLORS[bg]}}}}"
[[ ${THEME_COLORS[selection_background]} ]] || THEME_COLORS[selection_background]="${THEME_COLORS[selection]}"
[[ ${THEME_COLORS[selection_foreground]} ]] || THEME_COLORS[selection_foreground]="${THEME_COLORS[bright_fg]}"
[[ ${THEME_COLORS[orange]} ]] || THEME_COLORS[orange]="${THEME_COLORS[yellow]}"
[[ ${THEME_COLORS[brown]} ]] || THEME_COLORS[brown]=$(mix_color "${THEME_COLORS[orange]}" "#000000" 50%)
# Auto-derive shades from base accents when not defined and not aliased from colorN
[[ ${THEME_COLORS[dark_bg]} ]] || THEME_COLORS[dark_bg]=$(mix_color "${THEME_COLORS[background]}" "#000000" 25%)
[[ ${THEME_COLORS[darker_bg]} ]] || THEME_COLORS[darker_bg]=$(mix_color "${THEME_COLORS[background]}" "#000000" 50%)
[[ ${THEME_COLORS[dark_bg]} ]] || THEME_COLORS[dark_bg]=$(mix_color "${THEME_COLORS[bg]}" "#000000" 25%)
[[ ${THEME_COLORS[darker_bg]} ]] || THEME_COLORS[darker_bg]=$(mix_color "${THEME_COLORS[bg]}" "#000000" 50%)
[[ ${THEME_COLORS[bright_red]} ]] || THEME_COLORS[bright_red]=$(mix_color "${THEME_COLORS[red]}" "#ffffff" 20%)
[[ ${THEME_COLORS[bright_yellow]} ]] || THEME_COLORS[bright_yellow]=$(mix_color "${THEME_COLORS[yellow]}" "#ffffff" 20%)
[[ ${THEME_COLORS[bright_green]} ]] || THEME_COLORS[bright_green]=$(mix_color "${THEME_COLORS[green]}" "#ffffff" 20%)
+21 -11
View File
@@ -3,7 +3,7 @@
# omarchy:summary=Sync current Omarchy theme environment into tmux
# omarchy:hidden=true
CURRENT_THEME_PATH="$HOME/.config/omarchy/current/theme"
CURRENT_THEME_PATH="$HOME/.local/state/omarchy/current/theme"
GUM_ENV="$CURRENT_THEME_PATH/gum_env.lua"
COLORS_TOML="$CURRENT_THEME_PATH/colors.toml"
@@ -54,21 +54,31 @@ theme_osc_sequences() {
theme_color() {
local key="$1"
local fallback="${2:-}"
awk -F= -v key="$key" -v fallback="$fallback" '
function clean(raw) {
gsub(/^[[:space:]]+|[[:space:]]+$/, "", raw)
if (raw ~ /^"/) {
sub(/^"/, "", raw)
sub(/".*$/, "", raw)
}
return raw
}
awk -F= -v key="$key" '
{
field = $1
gsub(/^[[:space:]]+|[[:space:]]+$/, "", field)
if (field == key) {
value = $2
gsub(/^[[:space:]]+|[[:space:]]+$/, "", value)
if (value ~ /^"/) {
sub(/^"/, "", value)
sub(/".*$/, "", value)
}
print value
print clean($2)
found = 1
exit
}
if (fallback != "" && field == fallback) fallback_value = clean($2)
}
END {
if (!found && fallback_value != "") print fallback_value
}
' "$COLORS_TOML"
}
@@ -78,8 +88,8 @@ sync_tmux_window_style() {
[[ -f $COLORS_TOML ]] || return
foreground=$(theme_color foreground)
background=$(theme_color background)
foreground=$(theme_color foreground fg)
background=$(theme_color background bg)
[[ -n $foreground && -n $background ]] || return
+2 -2
View File
@@ -3,8 +3,8 @@
# omarchy:summary=Sync Omarchy theme to VS Code, VSCodium, and Cursor
# omarchy:hidden=true
VS_CODE_THEME_DESCRIPTOR="$HOME/.config/omarchy/current/theme/vscode.json"
GENERATED_THEME="$HOME/.config/omarchy/current/theme/vscode-theme.json"
VS_CODE_THEME_DESCRIPTOR="$HOME/.local/state/omarchy/current/theme/vscode.json"
GENERATED_THEME="$HOME/.local/state/omarchy/current/theme/vscode-theme.json"
GENERATED_EXTENSION_NAME="omarchy-theme"
GENERATED_EXTENSION_ID="local.$GENERATED_EXTENSION_NAME"
GENERATED_EXTENSION_VERSION="1.0.0"
+1 -1
View File
@@ -102,7 +102,7 @@ if [[ ! -f $fast_signature_file ]] || ! cmp -s "$fast_signature_file" <(printf '
printf '%s' "$fast_signature" >"$fast_signature_file"
fi
current_theme=$(cat "$HOME/.config/omarchy/current/theme.name" 2>/dev/null)
current_theme=$(cat "$HOME/.local/state/omarchy/current/theme.name" 2>/dev/null)
selected_preview=""
for extension in png jpg jpeg webp gif bmp; do
if [[ -e $preview_dir/$current_theme.$extension ]]; then
+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

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