How omarchy-migrate-notify.service Detects Pending Migrations in Omarchy

omarchy-migrate-notify.service runs a three-stage bash script that checks for a runtime lock file, queries omarchy-migrate --pending to list outstanding migrations, and counts the results to decide whether to alert the user via desktop notification or terminal output.

Omarchy uses systemd user services to keep users informed about system maintenance tasks. The omarchy-migrate-notify.service specifically handles migration notifications—ensuring users know when pending configuration or data migrations require attention. This service triggers automatically when a graphical user logs in, executing the helper script at bin/omarchy-migrate-notify to perform detection.

The Three-Stage Detection Process

The omarchy-migrate-notify script follows a precise sequence to avoid false notifications and race conditions with active updates.

Stage 1: Check for Concurrent Updates

Before any detection occurs, the script verifies no update is currently running. The update_in_progress function (lines 7-14 in bin/omarchy-migrate-notify) checks for the existence of $XDG_RUNTIME_DIR/omarchy-update.lock:


# From omarchy-migrate-notify

update_in_progress() {
  [[ -f "$XDG_RUNTIME_DIR/omarchy-update.lock" ]]
}

If this lock file exists, the script exits silently. This prevents duplicate or misleading notifications when an update process will handle migrations automatically.

Stage 2: Query Pending Migrations

With no active update, the script executes the core detection command (line 20):

pending_migrations=$(omarchy-migrate --pending)

The omarchy-migrate binary with the --pending flag outputs one pending migration per line. This output is captured in the pending_migrations variable for evaluation.

Stage 3: Count and Evaluate Results

Lines 21-22 strip empty lines and compute the count:

count=$(echo "$pending_migrations" | grep -v '^[[:space:]]*$' | wc -l)

The script then branches based on this count:

  • Zero pending migrations: Exit without notification
  • One or more pending migrations: Build and send a user-facing alert

Notification Delivery Workflow

Waiting for the Desktop Environment

Before displaying any notification, the script ensures the notification daemon is ready. Line 33 calls omarchy-notification-wait to synchronize with the desktop environment.

Double-Checking the Update Lock

Lines 35-39 perform a final update_in_progress check. This second verification closes a race window where an update could have started between the initial check and notification readiness:

if update_in_progress; then
  exit 0
fi

This defensive pattern prevents alerting users about migrations that will be resolved momentarily.

Fallback to Terminal Output

If desktop notification fails, lines 48-60 fall back to terminal output, printing the pending migrations directly:


# Simplified fallback logic

echo "Pending migrations:"
echo "$pending_migrations"

Manual Testing and Verification

You can manually trigger the same detection logic the service uses:


# Run the full notification workflow

omarchy-migrate-notify

To inspect pending migrations directly without notification logic:


# Raw list of pending migrations (same source the helper queries)

omarchy-migrate --pending

Test the lock-file behavior by simulating an active update:


# Create the lock file that blocks notification

export XDG_RUNTIME_DIR=/tmp
touch /tmp/omarchy-update.lock

# This will exit silently due to the lock

omarchy-migrate-notify

Key Source Files

Understanding the omarchy-migrate-notify.service detection mechanism requires familiarity with these components:

File Purpose
default/systemd/user/omarchy-migrate-notify.service Systemd user unit defining when and how the helper launches (ExecStart at line 17)
bin/omarchy-migrate-notify Bash script implementing the three-stage detection and notification logic
bin/omarchy-migrate Core migration tool providing the --pending query interface
docs/notifications.md User documentation for Omarchy's notification system
agents/skills/migrations.md Architectural overview of migration handling

Summary

  • omarchy-migrate-notify.service triggers at graphical login via systemd user service activation
  • Detection relies on omarchy-migrate --pending output, counting non-empty lines to identify pending work
  • Dual lock checks (before and after waiting for the notification daemon) eliminate race conditions with concurrent updates
  • The fallback to terminal output ensures users receive critical migration information even when desktop notifications fail
  • Implementation spans bin/omarchy-migrate-notify with critical logic at lines 7-14, 20-22, and 35-39

Frequently Asked Questions

How does omarchy-migrate-notify.service know when to run?

The service includes an [Install] section targeting default.target with a WantedBy=graphical-session.target dependency. This configuration causes systemd to start the service automatically when a graphical user session begins, ensuring users receive timely migration alerts after login.

What happens if omarchy-migrate --pending returns no output?

When omarchy-migrate --pending produces empty output or only whitespace, the count operation yields zero and the script exits cleanly without any user notification. This silent success path avoids spamming users when no migrations are pending.

Why does the script check the update lock twice?

The initial check prevents wasted work when an update is already running. The second check after omarchy-notification-wait addresses a race condition: an update could have started during the wait period. This double-guard pattern ensures users never receive stale notifications about migrations that will be handled automatically.

Can I run the detection logic without triggering a notification?

Yes—direct invocation of omarchy-migrate --pending bypasses all notification logic and simply lists pending migrations to stdout. This is useful for scripting, automated health checks, or when you want to inspect system state without desktop interaction.

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 →