What Is the Migration Framework in Omarchy? A Technical Deep Dive

The migration framework in Omarchy is an automated, per-user upgrade system that executes ordered, idempotent shell scripts to synchronize user configurations with new distribution releases.

The migration framework serves as the critical bridge between Omarchy releases and existing user environments in the basecamp/omarchy repository. When the distribution evolves its filesystem layout or default configurations, this framework ensures every user transitions safely without manual intervention or data loss.

Integration with the Update Process

The migration framework activates immediately after package updates complete. When you run omarchy update, the command first installs new package versions and then automatically invokes omarchy-migrate to apply any pending migration scripts, as documented in docs/update-process.md.

This coupling ensures that filesystem changes and configuration updates arrive atomically with the new code they support. The framework executes migrations using bash -euo pipefail to enforce strict error handling and exit immediately if any command fails during the transition.

Per-User Execution Model

Unlike system-wide package managers, the migration framework runs as the logged-in user, never as root. Each migration records its completion state under ~/.local/state/omarchy/migrations/, guaranteeing that every individual user account processes every migration independently.

According to docs/file-layout.md, this design isolates user-specific changes and prevents permission conflicts. If three different users share a single workstation, each receives their own migration state directory and applies transformations to their personal configuration files separately.

Idempotent Script Architecture

Migration scripts follow a strict naming convention: migrations/<timestamp>.sh, where the timestamp represents Unix epoch time. This naming scheme establishes a total execution order while keeping scripts self-contained and safe to run multiple times.

Each script is designed to be idempotent—safe to execute repeatedly without side effects. The framework wraps each script and creates a marker file at ~/.local/state/omarchy/migrations/<timestamp>.sh.finished after successful completion, skipping already-applied migrations on subsequent runs.


# Run all pending migrations for the current user

omarchy-migrate

# Show which migrations are still pending without applying them

omarchy-migrate --pending

A typical migration script removes obsolete configuration lines or migrates settings to new formats:

#!/usr/bin/env bash
set -euo pipefail

# Remove an obsolete tmux alert hook

sed -i '/^# TMUX ALERT/d' "$HOME/.config/tmux.conf"

Login Notifications for Pending Migrations

To prevent users from missing critical upgrades, the framework includes a systemd user service called omarchy-migrate-notify.service. This service activates at login, runs omarchy-migrate --pending to detect unapplied changes, and displays a desktop toast notification prompting the user to execute the migrations.

As detailed in docs/notifications.md, this mechanism ensures that pending migrations are never forgotten, even if the user updates the system but never runs omarchy update again during that session.

Security and Privilege Restrictions

The migration framework enforces strict safety boundaries. Migrations may only modify user-owned files in the home directory. Any task requiring elevated privileges—such as system-level package changes or root-owned file modifications—must be handled by separate privileged helpers during the initial omarchy update phase.

This security model, documented in docs/file-layout.md, ensures that the per-user migration runner never executes with root permissions, minimizing the attack surface and preventing accidental system damage from user-level configuration scripts.

Key Implementation Files

The migration framework relies on several critical components within the repository:

Summary

The migration framework in Omarchy provides a deterministic, user-centric mechanism for evolving configurations across releases:

  • Automatic execution hooks into omarchy update to apply changes immediately after package installation
  • User isolation ensures each account maintains independent migration state in ~/.local/state/omarchy/migrations/
  • Safety guarantees enforce bash -euo pipefail execution and restrict modifications to user-owned files only
  • Idempotent design allows scripts to be re-run safely using epoch-timestamp ordering
  • Login reminders via omarchy-migrate-notify.service prevent users from missing critical upgrades

Frequently Asked Questions

How do I check if I have pending migrations without running them?

Use the --pending flag with the migrate command. Run omarchy-migrate --pending to display which epoch-timestamped scripts remain unapplied without executing them. This command is also what the login notification service queries to determine if it should prompt you.

What happens if a migration script fails?

Because the framework executes scripts with bash -euo pipefail, any command that returns a non-zero exit code immediately stops the migration. The framework does not create the .finished marker file for failed migrations, ensuring they will be re-attempted on the next run of omarchy-migrate or omarchy update.

Can I skip a specific migration?

While the framework automatically skips completed migrations (those with .finished markers in ~/.local/state/omarchy/migrations/), there is no built-in mechanism to bypass individual pending scripts. Each script must exit successfully to record completion. If you need to skip a problematic migration, you would need to create the corresponding .finished marker file manually, though this is not recommended as it may leave your configuration inconsistent.

Why do migrations run as the user instead of root?

Running migrations as the logged-in user rather than root follows the principle of least privilege. According to the source code in docs/file-layout.md, this design prevents migration scripts from accidentally modifying system files or other users' configurations. System-level changes required for an update are handled separately during the package installation phase, while user-specific configuration transformations remain isolated to the requesting account.

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 →