# Omarchy migrations Omarchy migrations are one-time repair scripts for existing installs. They are used when a package update needs to change state that pacman cannot safely own by itself. They are for both humans and agents: - Users should know when migrations run, where state is stored, and how to retry or inspect pending work. - Agents should know which migration scope to use, how to write safe migration scripts, and what should **not** be a migration. ## The two migration scopes Omarchy migrations are split by execution context: ```text migrations/system/*.sh migrations/user/*.sh ``` ### System migrations System migrations run as root and must be noninteractive. Use system migrations for machine-wide state, for example: - `/etc` drop-ins or legacy config cleanup - `/boot` / bootloader cleanup - systemd system units or service state - hardware quirks - package-owned layout transitions State lives in: ```text /var/lib/omarchy/migrations/system/ ``` ### User migrations User migrations run as the current graphical/login user and may be interactive. Use user migrations for per-user or session-aware state, for example: - `~/.config` changes - `~/.local` state - user systemd units - browser/editor preferences - DBus/session-dependent updates - prompts that need to happen in a visible terminal State lives in: ```text ~/.local/state/omarchy/migrations/user/ ``` A user migration is pending for a given user only when the script exists under `/usr/share/omarchy/migrations/user/` and that user's matching state file is missing. There is no global root-owned “user migrations required” queue. ## When migrations run ### During `omarchy update` `omarchy update` is the normal update path. It runs package updates, then: ```bash omarchy-migrate omarchy-hook post-update ``` `omarchy-migrate`: 1. waits for any active pacman transaction to finish 2. runs pending system migrations 3. runs pending user migrations for the current user System migrations usually already ran during the pacman transaction via the `omarchy` package `post_upgrade()`, but the second check is intentional and idempotent. ### During direct pacman updates Raw `sudo pacman -Syu` is guarded. Users should normally run: ```bash omarchy update ``` If a user explicitly bypasses the guard, the `omarchy` package still runs system migrations from `post_upgrade()`: ```bash omarchy-migrate-system ``` User migrations are never run by pacman. Instead, the user session watches the packaged user migration directory and runs a notifier. The notifier checks: ```bash omarchy-migrate --pending user ``` If that user has pending user migrations, it shows a notification that opens a terminal for: ```bash omarchy-migrate ``` The notifier never runs user migrations silently in the background. ### Manually Users can safely run: ```bash omarchy-migrate ``` at any time. Already-completed migrations are skipped. ## Inspecting pending migrations Use: ```bash omarchy-migrate --pending omarchy-migrate --pending system omarchy-migrate --pending user ``` Exit behavior: - `0` — one or more matching migrations are pending - non-zero — no matching migrations are pending Output is scope-prefixed: ```text system/100-system.sh user/200-user.sh ``` The lower-level runners also support `--pending` and print filenames without the scope prefix: ```bash omarchy-migrate-system --pending omarchy-migrate-user --pending ``` Prefer `omarchy-migrate --pending ...` in user-facing tools and watchers. ## Writing migrations Create a migration with: ```bash omarchy-dev-add-migration system --no-edit omarchy-dev-add-migration user --no-edit ``` Choose the scope based on the state being changed, not on convenience. ### File format Migrations are plain shell files: - filename: unix timestamp, generated by `omarchy-dev-add-migration` - mode: `0644` - no shebang - start with an `echo` describing the migration - use `$OMARCHY_PATH` for Omarchy-owned files Example system migration: ```bash echo "Remove legacy Limine config" rm -f /boot/EFI/limine/limine.conf ``` Example user migration: ```bash echo "Refresh user app launchers" omarchy-refresh-applications ``` ### Execution model Migration runners execute scripts with strict shell settings: ```bash bash -euo pipefail ``` `$OMARCHY_PATH` is exported into the migration process. A migration is marked complete only after the script exits successfully. If it fails, the marker is not written and the migration will be retried later. Because failed migrations can be retried after doing partial work, migrations must be idempotent. Prefer operations that are safe to run more than once: ```bash mkdir -p ~/.config/example rm -f ~/.config/example/legacy.conf install -Dm644 "$OMARCHY_PATH/default/example.conf" ~/.config/example/example.conf systemctl --user enable --now some-unit.service || true ``` Use `|| true` only when a failure is genuinely acceptable. ## What belongs in a migration? Good migration uses: - deleting or moving legacy files that block the packaged layout - marking or enabling new service state - migrating old config paths to new config paths - repairing known bad state from an earlier Omarchy release - one-time compatibility for existing installs Bad migration uses: - fresh-install setup that belongs in `install/` or `/etc/skel` - package installation that belongs in package dependencies or package lists - recurring maintenance - arbitrary cleanup that should be a user command - pre-4 upgrade work that belongs in `omarchy-upgrade-to-4` - hidden user/session work from pacman ## Fresh installs and new users Fresh users created from the packaged layout should not have to run historical user migrations. The package seeds user migration markers into `/etc/skel` so new users start with shipped user migrations marked complete. The ISO/finalization path also marks shipped user migrations complete for the freshly-created install user when running: ```bash omarchy-finalize-user --first-install ``` Existing users keep their own migration state and run only migrations whose state files are missing. ## Troubleshooting ### See what is pending ```bash omarchy-migrate --pending ``` ### Retry failed migrations Fix the underlying problem, then run: ```bash omarchy-migrate ``` A failed migration is not marked complete, so it will retry. ### Re-run a completed migration manually Remove its marker, then run the migration command again: ```bash rm ~/.local/state/omarchy/migrations/user/.sh omarchy-migrate ``` For system migrations: ```bash sudo rm /var/lib/omarchy/migrations/system/.sh omarchy-migrate ``` Be careful: migrations should be idempotent, but manually removing markers is an advanced troubleshooting step. ## Agent checklist Before adding a migration: 1. Is this a one-time repair for existing installs? 2. Is it system state or user/session state? 3. Can it run safely more than once? 4. Will it fail loudly if the important work fails? 5. Does it avoid hidden interactive work from pacman? 6. Does it belong in `omarchy-upgrade-to-4` instead? 7. Did you add or update tests if behavior changed? If the answer to any of these is unclear, stop and ask before adding the migration.