Skip to content
Operations
Agent

migrations

Read this before creating or changing migrations under `migrations/`.

From plugin
omarchy
47k16 skills16 agents

Claude Code

$ npx -y skills add omacom/omarchy --agent claude-code

Agent definition

migrations.md

Omarchy migrations

Read this before creating or changing migrations under `migrations/`.

Omarchy migrations are one-time repair scripts for existing installs. They are used when a package update needs to change state that pacman cannot safely own by itself.

Migration model

Migrations live in:

migrations/*.sh

They run as the current Omarchy user through `omarchy-migrate`, normally during `omarchy update`. A migration may touch user/session state (`~/.config`, `~/.local`, user systemd, browser/editor prefs, DBus/session state), and may also perform machine-wide repairs when needed.

Completion state is per-user:

~/.local/state/omarchy/migrations/<migration filename>

That means every user gets a chance to run every migration. Migrations run as the user; privileged operations should invoke the appropriate helper or privilege prompt themselves. Migrations must be idempotent: if one user already applied a machine-wide repair, the same migration running for another user should detect that and no-op.

When migrations run

During `omarchy update`

`omarchy update` is the normal update path. It runs package updates, then:

omarchy-migrate
omarchy-hook post-update

`omarchy-migrate` waits for any active pacman transaction to finish, then runs all pending migrations for the current user in the visible update terminal.

At login

Every graphical login starts `omarchy-migrate-notify.service` after `graphical-session.target`. The notifier checks:

omarchy-migrate --pending

It stays silent while `omarchy update` holds its lock, since that update applies the pending migrations itself.

If that user has pending migrations, it shows a notification that opens a terminal for:

omarchy-migrate

The notifier never runs migrations silently in the background.

This is what covers users who did not run the update themselves: someone who bypassed the pacman guard with `sudo env OMARCHY_ALLOW_DIRECT_PACMAN=1 pacman -Syu`, and any second user on the machine, whose migration markers are per-user and therefore still missing after another user updated.

Login is the only trigger on purpose. Watching the packaged migration directory also fires during a normal `omarchy update`, which prompts for migrations that `omarchy-migrate` is about to run in the visible update terminal.

Manually

Users can safely run:

omarchy-migrate

at any time. Already-completed migrations are skipped.

Inspecting pending migrations

Use:

omarchy-migrate --pending

Exit behavior:

  • `0` — one or more migrations are pending
  • non-zero — no migrations are pending

Output is one pending migration per line:

1781158082.sh

Creating a migration

Use the helper:

omarchy-dev-add-migration --no-edit

This creates:

migrations/<unix timestamp>.sh

New migration format:

  • File permissions must be `0644` (`-rw-r--r--`). Migration runners execute them

with `bash -euo pipefail`, not through executable bits.

  • No shebang line.
  • Start with an `echo` describing what the migration does.
  • Use `$OMARCHY_PATH` to reference the Omarchy directory.
  • Be idempotent. Check existing state before changing it.
  • Migrations are strictly ordered and synchronous. A migration that cannot finish must exit non-zero, remain pending, and stop the queue; never mark later migrations complete against state an earlier migration has not established.
  • Use helper commands such as `omarchy-cmd-present`, `omarchy-cmd-missing`,

`omarchy-pkg-add`, `omarchy-pkg-drop`, `omarchy-pkg-present`, and `omarchy-pkg-missing` when appropriate.

  • Never restart the Omarchy shell. `omarchy update` restarts it unconditionally

after migrations run, and the login-time shell already runs current code and hot-reloads `shell.json` edits.

  • Raw `pacman`, `command -v`, and direct config edits are acceptable when

needed for one-off repair work.

Example:

echo "Relink Neovim theme to Omarchy current state"

theme_link="$HOME/.config/nvim/lua/plugins/theme.lua"
current_relative_target="../../../../.local/state/omarchy/current/theme/neovim.lua"

[[ -L $theme_link ]] || exit 0
ln -sfn "$current_relative_target" "$theme_link"

Testing migrations

Run a migration against a temporary home when possible:

HOME=$(mktemp -d) bash -euo pipefail migrations/<timestamp>.sh

To rerun a migration locally, remove its marker and run the migrator:

rm ~/.local/state/omarchy/migrations/<migration>.sh
omarchy-migrate

Don't add a test for a migration under `test/`. It runs once per machine and is frozen once it ships, so the test stops guarding anything. If a migration needs logic worth testing, put that logic in a `bin/` command the migration calls and test the command. Tests of `omarchy-migrate`, the login notifier, and `omarchy-upgrade-to-quattro` stay.

Omarchy 4.0 is upgraded through `bin/omarchy-upgrade-to-quattro`, not through the normal migration runner. Do not add compatibility migrations for old installer layouts; put pre-4 package-layout transition work in the upgrade command instead.

Clearing a privileged file that a retired installer left on disk is the exception, and belongs in a migration whether or not that installer was part of a package layout transition. The upgrade command only runs on a machine still making the 3 to 4 crossing, so anything put there never reaches an install that crossed already, and it never runs at all for an installer that was retired on its own — while the file the installer wrote is still sitting on those machines. The upgrade command finishes by running `omarchy-migrate` (`run_post_upgrade_migrations`), so one migration reaches every population; a copy in the upgrade command would only be a second copy of the same predicate to keep correct. Such a migration must name the defect it clears and match what the old installer actually produced before deleting it. Leave safe administrato

Read more
@basecamp
Ships withomarchy

Omarchy is a beautiful, fun & agentic Linux distribution by DHH. Read more at omarchy.org.

47k3 skills16 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
46.7k
Star history of basecamp/omarchy on GitHub, a chart by star-history.com

Other agents on omarchy.

acceptance-tests

acceptance-tests

Agent

Read this before writing or running the graphical acceptance suite under `test/acceptance.d/`.

@basecamp@basecampInstall Agent
icon-font

icon-font

Agent

Read this before adding a branded glyph to `default/fonts/omarchy/omarchy.ttf`.

@basecamp@basecampInstall Agent
mise-tools

mise-tools

Agent

Read this before adding or changing a mise-managed tool. Default tools belong in `etc/mise/conf.d/omarchy-tools.toml`, which the…

@basecamp@basecampInstall Agent
motion

motion

Agent

Read this before adding or changing any animation in `shell/`: a panel, popup, notification, button, list or anything else that…

@basecamp@basecampInstall Agent

More agents from other plugins.

api-reference

api-reference

Agent

**⚠️ DEVELOPER REFERENCE ONLY** — This file documents the raw GraphQL API schema for development and maintenance purposes (adding…

unraid5d153
@dinglebear-ai@dinglebear-aiInstall Agent
agent

agent

Agent

The generic template and base persona for PAI. All role-specific agents under [/agents/](../agents/) inherit from this file,…

pai2w115
@nirholas@nirholasInstall Agent

Questions about migrations.

Which coding agents can use migrations?
migrations installs in Claude Code and Cursor: each loads subagents from .claude/agents, so copy the file there. Flowy's auto-invocation runs in Claude Code only.