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

> Discover Omarchy's migration framework: an automated system that uses ordered, idempotent shell scripts to synchronize user configurations with new releases. Streamline your upgrades.

- Repository: [37signals/omarchy](https://github.com/basecamp/omarchy)
- Tags: deep-dive
- Published: 2026-08-29

---

**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`](https://github.com/basecamp/omarchy/blob/main/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`](https://github.com/basecamp/omarchy/blob/main/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.

```bash

# 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:

```bash
#!/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`](https://github.com/basecamp/omarchy/blob/main/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`](https://github.com/basecamp/omarchy/blob/main/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:

- **`migrations/*.sh`** – Ordered shell scripts containing actual migration logic
- **[`docs/update-process.md`](https://github.com/basecamp/omarchy/blob/main/docs/update-process.md)** – Documents the trigger mechanism between updates and migrations
- **[`docs/file-layout.md`](https://github.com/basecamp/omarchy/blob/main/docs/file-layout.md)** – Defines state storage locations and user isolation principles
- **[`agents/skills/migrations.md`](https://github.com/basecamp/omarchy/blob/main/agents/skills/migrations.md)** – Internal design specifications for the migration command
- **`test/shell.d/*-migration-test.sh`** – Automated verification tests (e.g., [`zram-migration-test.sh`](https://github.com/basecamp/omarchy/blob/main/zram-migration-test.sh))

## 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`](https://github.com/basecamp/omarchy/blob/main/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.