How omarchy-migrate-notify.service Triggers Migrations on Login Without Blocking

The omarchy-migrate-notify.service uses a per-user systemd unit ordered after graphical-session.target to execute a lightweight helper that checks for pending migrations without blocking login, exiting silently if an update lock exists or displaying a desktop notification only when migrations are required.

The omarchy-migrate-notify.service in the omacom/omarchy repository provides a seamless mechanism to alert users about pending system migrations immediately upon graphical login. This systemd user service ensures that critical updates are brought to the user's attention through desktop notifications while maintaining a non-blocking design that never delays the graphical session startup. By leveraging precise ordering constraints and lock-file coordination, omarchy-migrate-notify.service balances user awareness with system performance.

Systemd Integration and Service Architecture

The service definition resides in default/systemd/user/omarchy-migrate-notify.service and utilizes specific systemd directives to ensure safe execution timing. The unit declares After=graphical-session.target and Wants=graphical-session.target, guaranteeing the service starts only after the graphical session is fully initialized and a notification server is available. As documented in docs/update-process.md (lines 161-167), this ordering prevents the migration check from blocking the login process or attempting to display notifications before the desktop environment is ready.

The service uses Type=oneshot, which tells systemd that the service runs to completion and then exits, rather than remaining as a daemon process. This design choice ensures minimal resource consumption and clean process management.

[Unit]
Description=Omarchy migration notification helper
After=graphical-session.target
Wants=graphical-session.target

[Service]
ExecStart=/usr/bin/omarchy-migrate-notify
Type=oneshot

Non-Blocking Execution Flow and Lock Coordination

The helper binary /usr/bin/omarchy-migrate-notify implements a three-phase non-blocking workflow that prevents interference with concurrent system operations.

Respecting the Update Lock File

Before performing any migration checks, the helper verifies whether an update operation is currently in progress by checking for the existence of ${XDG_RUNTIME_DIR:-/tmp}/omarchy-update.lock. As documented in docs/update-process.md (lines 173-182), if this lock file exists—indicating that omarchy update is actively running—the notifier immediately exits with status 0 without displaying any notifications. This silent exit strategy prevents the service from blocking the login process or interfering with active update operations.

Detecting Pending Migrations

When the lock file is absent, the helper executes omarchy-migrate --pending to query the migration state. According to the update process documentation (lines 59-62), this command prints pending migration names and exits with status 0 when migrations are pending, or exits with a non-zero status when no migrations are required. The helper interprets these exit codes to determine whether user notification is necessary.

Desktop Notification Delivery

Only when pending migrations exist does the helper invoke omarchy-notification-send to display a desktop notification. This notification includes an action that launches a terminal running omarchy-migrate, allowing the user to apply updates manually. The service itself never executes migrations; it solely prompts the user to take action.

Implementation Details and Source Code

The complete helper implementation combines D-Bus detection, lock checking, and conditional notification logic. The script first waits for the Freedesktop notification server to become available via busctl, then proceeds with the lock and migration checks.

#!/usr/bin/env bash

# Minimal implementation of bin/omarchy-migrate-notify

# Wait for a running notification server

while ! busctl --user call org.freedesktop.Notifications /org/freedesktop/Notifications org.freedesktop.Notifications GetServerInformation &> /dev/null; do
  sleep 0.2
done

# Respect the per-user update lock – exit silently if an update is in progress

if [[ -e "${XDG_RUNTIME_DIR:-/tmp}/omarchy-update.lock" ]]; then
  exit 0
fi

# Ask Omarchy if there are pending migrations

if omarchy-migrate --pending; then
  # No pending migrations – nothing to do

  exit 0
fi

# Show a desktop notification (uses the notification helper)

omarchy-notification-send \
  "Omarchy migrations pending" \
  "Run omarchy-migrate to apply required updates" \
  "terminal" "omarchy-migrate"

To enable this service for new users, the installation process invokes omarchy-provision-first-run enable omarchy-migrate-notify.service from install/user/first-run/enable-user-units.sh, ensuring the unit starts automatically on first login.

Summary

  • Graphical session ordering: The service uses After=graphical-session.target to ensure notifications only appear after the desktop environment is ready, preventing login delays.
  • Lock-file coordination: The helper checks ${XDG_RUNTIME_DIR:-/tmp}/omarchy-update.lock and exits silently if an update is running, avoiding conflicts with concurrent operations.
  • Exit-code semantics: omarchy-migrate --pending returns 0 when migrations exist and non-zero when none are pending, driving the notification logic.
  • Non-blocking design: With Type=oneshot and rapid lock checking, the service completes in milliseconds without holding up the login process.
  • User-controlled execution: The service only displays notifications and never runs migrations automatically, giving users control over when to apply updates.

Frequently Asked Questions

What triggers omarchy-migrate-notify.service to run?

The service is triggered automatically by systemd user manager after reaching graphical-session.target during the login process. As configured in default/systemd/user/omarchy-migrate-notify.service, the unit is enabled via omarchy-provision-first-run on first login, causing it to execute on every subsequent graphical session startup.

Why does the service use Type=oneshot instead of a long-running service?

The Type=oneshot configuration specifies that the service runs a single command to completion and then exits. This approach is optimal for omarchy-migrate-notify.service because the migration check is a brief, finite operation that does not require persistent background processes, minimizing system resource usage and avoiding unnecessary daemon overhead.

How does the service avoid interfering with running updates?

The helper script checks for the existence of ${XDG_RUNTIME_DIR:-/tmp}/omarchy-update.lock before proceeding. If the lock file exists, indicating an active omarchy update process is holding the lock as described in docs/update-process.md, the script exits immediately with status 0 without displaying notifications, ensuring no interference with the update workflow.

What happens if no migrations are pending?

When omarchy-migrate --pending exits with a non-zero status (indicating no pending migrations), the helper script exits cleanly without invoking the notification system. This ensures users are not bothered with unnecessary alerts when the system is already up to date.

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 →