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

> Discover how omarchy-migrate-notify.service triggers migrations on login without blocking. Learn about its lightweight helper for efficient, non-intrusive updates.

- Repository: [Omacom/omarchy](https://github.com/omacom/omarchy)
- Tags: internals
- Published: 2026-09-09

---

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

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

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