How to Create a New Migration Script in Omarchy: A Complete Guide
Use omarchy-dev-add-migration --no-edit to scaffold a new migration script in the migrations/ directory, then implement idempotent shell commands that check for existing state before making changes.
Omarchy's migration system provides a robust mechanism for applying one-time configuration changes and repairs that cannot be expressed as ordinary package updates. Migration scripts in Omarchy are idempotent, per-user, and self-contained—ensuring safe, repeatable execution across all user accounts on a system. This guide walks through creating, implementing, and testing migration scripts based on the actual source code in the omacom/omarchy repository.
Understanding Omarchy Migrations
Before writing your first migration, you need to understand how the system executes and tracks these scripts.
What Migrations Are For
Migrations perform one-time repairs or configuration changes. Unlike package updates, which are stateless and version-controlled externally, migrations handle transitional states—for example, migrating user configuration files to a new format or adding required default settings that packages cannot provide.
Per-User Execution Model
The migration system is deliberately per-user rather than system-wide. Each migration's completion marker is stored in:
~/.local/state/omarchy/migrations/<migration-filename>
This design ensures every logged-in user runs every pending migration independently. Even if one user applies a machine-wide fix, other users still execute the same migration to update their personal configurations.
Migrations run as the current Omarchy user, not as root. Privileged operations must invoke helper commands like omarchy-pkg-add or prompt for elevation—the migration runner itself never performs privileged actions directly.
When Migrations Execute
Migrations run in three contexts:
- During
omarchy update— After package upgrades complete,omarchy-migrateruns all pending migrations for the current user - At graphical login — The
omarchy-migrate-notify.servicesystemd unit triggersomarchy-migrate --pending; if migrations are pending, a notification opens a terminal to runomarchy-migrate - Manual invocation — Users can run
omarchy-migrateat any time; completed migrations are automatically skipped
Creating a New Migration Script
Omarchy provides a dedicated helper command to scaffold migration files with the correct naming convention and permissions.
Step 1: Generate the Migration File
Run the developer helper to create a new migration:
omarchy-dev-add-migration --no-edit
This command generates an empty file under migrations/ using the current Unix timestamp as the filename (for example, migrations/1781158082.sh). The --no-edit flag skips opening an editor immediately; omit it if you prefer to edit right away.
Step 2: Implement the Migration
Edit the generated file to implement your changes. Follow these mandatory requirements:
| Requirement | Specification |
|---|---|
| Permissions | 0644 (readable, not executable)—the runner invokes with bash -euo pipefail |
| Shebang | None—the runner supplies the interpreter |
| Header | Leading echo describing the migration's purpose |
| Idempotency | Guard all state-changing commands with existence checks |
Here is a template migration script:
echo "Ensuring required environment variable is set in ~/.bashrc"
# Idempotent check: skip if already present
if grep -q "OMARCHY_FEATURE_ENABLED=1" ~/.bashrc; then
echo "Already configured, skipping"
exit 0
fi
# Apply the change
echo 'export OMARCHY_FEATURE_ENABLED=1' >> ~/.bashrc
echo "Configuration added successfully"
Step 3: Use Helper Commands
For package-related actions, use Omarchy's wrapper commands rather than direct pacman calls:
omarchy-cmd-present <command>— Check if a command existsomarchy-cmd-missing <command>— Check if a command is absentomarchy-pkg-add <package>— Install a package with proper privilege handlingomarchy-pkg-drop <package>— Remove a package
These helpers ensure consistent behavior and proper elevation handling.
Testing Your Migration
Never test migrations directly in your live environment. Use isolated testing and controlled re-execution.
Test in Temporary Environment
Run the script against a temporary home directory to verify it does not depend on your specific user configuration:
HOME=$(mktemp -d) bash -euo pipefail migrations/1781158082.sh
This command simulates a fresh user environment and catches assumptions about existing files or settings.
Re-Run Locally for Development
To test a migration repeatedly during development, remove its completion marker and invoke the migrator:
rm ~/.local/state/omarchy/migrations/1781158082.sh
omarchy-migrate
The migration will execute again because its marker is absent.
Critical Implementation Rules
Follow these rules to ensure your migrations integrate correctly with the Omarchy system:
- Do not restart the Omarchy shell — The
omarchy updatecommand handles restarts after all migrations complete - Make every operation idempotent — Check for existing state before making changes; migrations may run multiple times if markers are cleared
- Keep permissions at
0644— Executable permissions are unnecessary and discouraged - Avoid privileged operations in the script — Delegate to helper commands that handle elevation properly
Key Files and Commands Reference
| Path | Purpose |
|---|---|
agents/skills/migrations.md |
Complete migration guidelines and troubleshooting |
migrations/*.sh |
Migration script storage (e.g., migrations/1781158082.sh) |
bin/omarchy-dev-add-migration |
Scaffold new migration files |
bin/omarchy-migrate |
Execute pending migrations |
bin/omarchy-migrate-notify |
Login-time pending migration checker |
default/systemd/user/omarchy-migrate-notify.service |
Systemd unit for graphical login notifications |
Summary
- Create migration scripts with
omarchy-dev-add-migration --no-edit - Name files using Unix timestamps in the
migrations/directory - Implement idempotent shell code with no shebang and proper header echo
- Test in temporary
HOMEdirectories and re-run by deleting completion markers - Execute automatically during updates, at login via systemd, or manually with
omarchy-migrate
Frequently Asked Questions
What happens if two users run the same migration?
Each user maintains independent completion markers in ~/.local/state/omarchy/migrations/. Both users execute the same migration script independently, which is the intended behavior—this ensures per-user configurations are properly updated even when machine-wide changes are already complete.
Can I use sudo directly in a migration script?
No. Migrations run as the unprivileged Omarchy user. For package installations or other privileged operations, use helper commands like omarchy-pkg-add or omarchy-pkg-drop. These commands handle privilege elevation safely and consistently.
Why can't I make my migration script executable?
The migration runner explicitly invokes scripts with bash -euo pipefail, so executable permissions are unnecessary. The 0644 permission requirement prevents accidental direct execution and ensures consistent execution through the managed runner.
How do I check if my migration will run on a specific system?
Run omarchy-migrate --pending to list migrations that have not yet been applied to the current user. This command checks for the presence of completion markers in ~/.local/state/omarchy/migrations/ without executing any scripts.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →