7.2 KiB
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:
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:
/etcdrop-ins or legacy config cleanup/boot/ bootloader cleanup- systemd system units or service state
- hardware quirks
- package-owned layout transitions
State lives in:
/var/lib/omarchy/migrations/system/<migration filename>
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:
~/.configchanges~/.localstate- user systemd units
- browser/editor preferences
- DBus/session-dependent updates
- prompts that need to happen in a visible terminal
State lives in:
~/.local/state/omarchy/migrations/user/<migration filename>
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:
omarchy-migrate
omarchy-hook post-update
omarchy-migrate:
- waits for any active pacman transaction to finish
- runs pending system migrations
- 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:
omarchy update
If a user explicitly bypasses the guard, the omarchy package still runs system
migrations from post_upgrade():
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:
omarchy-migrate --pending user
If that user has pending user migrations, it shows a notification that opens a terminal for:
omarchy-migrate
The notifier never runs user migrations silently in the background.
Manually
Users can safely run:
omarchy-migrate
at any time. Already-completed migrations are skipped.
Inspecting pending migrations
Use:
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:
system/100-system.sh
user/200-user.sh
The lower-level runners also support --pending and print filenames without the
scope prefix:
omarchy-migrate-system --pending
omarchy-migrate-user --pending
Prefer omarchy-migrate --pending ... in user-facing tools and watchers.
Writing migrations
Create a migration with:
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
echodescribing the migration - use
$OMARCHY_PATHfor Omarchy-owned files
Example system migration:
echo "Remove legacy Limine config"
rm -f /boot/EFI/limine/limine.conf
Example user migration:
echo "Refresh user app launchers"
omarchy-refresh-applications
Execution model
Migration runners execute scripts with strict shell settings:
bash -euo pipefail <migration>
$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:
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:
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
omarchy-migrate --pending
Retry failed migrations
Fix the underlying problem, then run:
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:
rm ~/.local/state/omarchy/migrations/user/<migration>.sh
omarchy-migrate
For system migrations:
sudo rm /var/lib/omarchy/migrations/system/<migration>.sh
omarchy-migrate
Be careful: migrations should be idempotent, but manually removing markers is an advanced troubleshooting step.
Agent checklist
Before adding a migration:
- Is this a one-time repair for existing installs?
- Is it system state or user/session state?
- Can it run safely more than once?
- Will it fail loudly if the important work fails?
- Does it avoid hidden interactive work from pacman?
- Does it belong in
omarchy-upgrade-to-4instead? - 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.