How Omarchy Migrations Work: A Complete Guide to System Updates

Omarchy migrations are per-user shell scripts that perform one-time repairs or adjustments when package updates cannot safely modify system state, tracked via marker files in ~/.local/state/omarchy/migrations/ and executed through the omarchy-migrate command.

When you update the Omarchy declarative desktop environment, some changes require more than just package replacement—they need intelligent, context-aware fixes to user configurations or shared system state. This article explains how Omarchy's migration system bridges that gap, based on the implementation in the omacom/omarchy repository.

Where Migrations Live and How They're Tracked

All migration scripts reside in the migrations/ directory as *.sh files (migrations/*.sh). These are small, focused Bash scripts designed for atomic, one-time execution.

Each migration completes per-user, not globally. After a migration runs, omarchy-migrate creates a marker file in:

~/.local/state/omarchy/migrations/<migration-filename>

This design ensures every user account on a machine independently runs each migration. On subsequent executions, omarchy-migrate skips any migrations where this marker already exists. This per-user isolation prevents partial system states and ensures multi-user machines remain consistent.

When Omarchy Migrations Run

The migration system triggers through four distinct paths:

During omarchy update

The primary trigger occurs automatically after package updates. The omarchy update command executes this sequence:

  1. Update packages
  2. Run omarchy-migrate
  3. Run post-update hook (omarchy-hook post-update)

The omarchy-migrate command waits for any active pacman transaction to complete, then executes all pending migrations for the current user directly in the visible update terminal. You see the output in real-time.

At Graphical Login

Each graphical login starts the systemd user service at default/systemd/user/omarchy-migrate-notify.service. This service calls omarchy-migrate --pending. If pending migrations exist, it displays a desktop notification that, when clicked, opens a terminal and runs omarchy-migrate.

Critical safety note: This notification system never runs migrations automatically in the background. The user must explicitly open a terminal and execute the command.

Manual Execution

Users can run migrations anytime:


# Execute all pending migrations for current user

omarchy-migrate

The command scans migrations/, skips completed migrations (those with marker files), and runs the remainder.

Inspecting Pending Migrations

Check what needs to run without executing:

omarchy-migrate --pending

This prints pending migrations to stdout and exits with status 0 when migrations exist, non-zero otherwise—useful for scripting and the login notifier service.

Core Design Principles

Idempotency

Migrations must be safe to re-run. If a machine-wide repair was already applied by another user, the script should detect this condition and no-op gracefully. The migration guide in the repository documentation emphasizes this requirement.

User-Context Execution

Migrations run as the current user, never as root. Any privileged operations must explicitly invoke appropriate helpers or request elevation. This limits blast radius and follows least-privilege principles.

Explicit User Action for Notifications

The omarchy-migrate-notify.service only prompts—it never auto-runs. Users retain full control over when migrations execute.

Examining Migration Files

Example Migration Structure

A typical migration script follows this pattern:

#!/usr/bin/env bash

# 1788009111.sh – Rename deprecated config directory

if [[ -d "$HOME/.omarchy-old" ]]; then
    mv "$HOME/.omarchy-old" "$HOME/.omarchy-backup-$(date +%s)"
    echo "Migrated old config to backup"
fi

# Completion marker handled automatically by omarchy-migrate

The numeric prefix (1788009111) appears to use a timestamp or sequence number for ordering, though the system executes all pending migrations regardless of order.

Triggering Login Notifications Manually

For debugging or testing:

systemctl --user start omarchy-migrate-notify.service

Key Files and Their Roles

File Purpose
agents/skills/migrations.md Complete migration model documentation, execution triggers, and authoring guidelines
migrations/*.sh Actual migration scripts shipped with each Omarchy release
bin/omarchy-migrate Public command that scans and executes pending per-user migrations
bin/omarchy-migrate-notify Helper script invoked by systemd to display login-time notifications
default/systemd/user/omarchy-migrate-notify.service Systemd user unit triggering notifications after graphical login
docs/update-process.md Full update pipeline documentation including migration phase
docs/file-layout.md Directory structure reference for migrations and state markers

Summary

  • Omarchy migrations are per-user shell scripts in migrations/*.sh that perform one-time repairs package managers cannot handle
  • Completion tracking uses marker files in ~/.local/state/omarchy/migrations/ per user
  • Three execution triggers: during omarchy update, at graphical login (via notification), or manual omarchy-migrate invocation
  • Safety constraints: idempotent design, user-context execution, explicit user consent for login-triggered runs
  • Core commands: omarchy-migrate (run pending), omarchy-migrate --pending (list only)

Frequently Asked Questions

Why do migrations run per-user instead of system-wide?

Each user may have different configuration states requiring different repairs. The marker file system in ~/.local/state/omarchy/migrations/ ensures personalized handling without assuming homogeneous environments across accounts.

What happens if a migration fails partway through?

Run omarchy-migrate again—migrations are designed to be idempotent. They should detect partial completion and resume or complete safely. Check the terminal output from omarchy update or manual execution for specific error details.

Can I skip a migration I don't want to run?

The system does not provide a native skip mechanism. However, you can manually create the marker file that omarchy-migrate checks: touch ~/.local/state/omarchy/migrations/<script-name>. Only do this if you fully understand what the migration does and have applied equivalent changes manually.

How do I know if pending migrations exist before logging in graphically?

Run omarchy-migrate --pending from any terminal session. Exit status 0 indicates pending migrations exist; non-zero means you're fully caught up.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →