How Omarchy Install Scripts and Finalize Scripts Function

Omarchy’s installation pipeline splits system configuration into three distinct phases: root-side installation executed by omarchy-apply-system within the ISO chroot, per-user finalization managed by omarchy-provision-user with idempotency markers in ~/.local/state/omarchy/done/, and first-run graphical setup triggered by omarchy-provision-first-run after the initial login.

The omacom/omarchy repository implements a modular, idempotent installation architecture that cleanly separates system-wide defaults from per-user configuration. Understanding how Omarchy install scripts and their finalize counterparts function is essential for customizing the distribution or debugging provisioning failures. The pipeline leverages specific orchestration scripts and marker files to ensure operations run exactly once or safely on repeat invocations.

Root-Side Installation Phase

The root-side installation runs during ISO construction inside a chroot environment. The entry point omarchy-apply-system sources four top-level aggregator scripts located under the install/ directory:

run_logged "$OMARCHY_INSTALL/config/all.sh"      # System-wide configuration

run_logged "$OMARCHY_INSTALL/hardware/all.sh"      # Hardware-specific fixes

run_logged "$OMARCHY_INSTALL/login/all.sh"       # SDDM theme and session setup

run_logged "$OMARCHY_INSTALL/post-install/all.sh" # Post-installation tasks

Each leaf script resides in directories like install/config/, install/hardware/, install/login/, or install/post-install/. These scripts are sourced (not executed) via the run_logged helper defined in install/helpers/logging.sh, which records all output to /var/log/omarchy-install.log.

Because these scripts run as root within the ISO chroot, they perform privileged operations such as copying files to /usr/share/omarchy, modifying /etc configuration, enabling system services, loading kernel modules, and setting up udev rules or firewall policies. These steps execute once per ISO build without per-script idempotency guards, relying instead on the immutable nature of the build process.

Per-User Finalization (omarchy-provision-user)

After the system boots and the user logs in, bin/omarchy-provision-user handles runtime configuration that requires the target user’s home directory and environment. This script follows a strict idempotency protocol to prevent redundant operations on subsequent runs.

Idempotency Checks and Environment Setup

The finalizer first checks for an existing marker using omarchy-done check finalize-user. If the marker file ~/.local/state/omarchy/done/finalize-user exists and the --force flag is not supplied, the script exits immediately. When proceeding, it sets critical environment variables including OMARCHY_PATH, OMARCHY_INSTALL, and updates PATH to ensure child scripts locate Omarchy resources correctly.

A unique feature of the finalizer is its dev-aware skill symlink creation. For every skill directory under $OMARCHY_PATH/default/agents/skills/*/, the script creates symlinks into the user’s home directory at locations like ~/.agents/skills and ~/.claude/skills. This operation repeats on every run to support development checkouts where skills may change frequently.

The script then updates XDG user directories and populates ~/.config/gtk-3.0/bookmarks to ensure consistent file manager behavior across sessions.

Executing User Leaf Scripts

The finalizer sources install/user/all.sh (located in the repository root), which aggregates all per-user configuration leaf scripts such as install/user/theme.sh and install/user/mise.sh. After sourcing these, the script refreshes application launchers, sets the default browser, and configures MIME handlers.

If invoked with the --first-install flag (used during ISO creation), the script touches all migration scripts under install/migrations/ to mark them as already applied for the brand-new user account. Finally, it creates the idempotency marker using omarchy-done mark finalize-user.

First-Run Graphical Setup (omarchy-provision-first-run)

After the first interactive graphical login, omarchy-provision-first-run executes actions requiring a live user systemd instance. This phase runs only once, guarded by the marker ~/.local/state/omarchy/done/first-run-user.

This script performs the following operations:

  • Invokes omarchy-provision-user if it hasn't completed yet.
  • Enables user-level systemd units including bt-agent.service and omarchy-sleep-lock.service.
  • Applies GNOME and GTK settings via dconf that require an active graphical session.
  • Performs speaker tuning and displays a welcome toast notification.
  • Handles initial Wi-Fi configuration prompts.

Idempotency Management with omarchy-done

The bin/omarchy-done utility provides three primitives used throughout the installation pipeline:

  • omarchy-done check <name> — Returns success (exit code 0) if the marker file exists.
  • omarchy-done mark <name> — Creates the marker file in ~/.local/state/omarchy/done/.
  • omarchy-done ensure <name> — Checks for the marker, creates it if missing, and returns success.

The finalizer uses check and mark to control the finalize-user state, while the first-run script uses ensure for the first-run-user marker. This design allows administrators to force re-provisioning by removing marker files or using the --force flag.

Adding New Leaf Scripts to Omarchy

Extending the installation pipeline requires adding leaf scripts to the appropriate aggregator.

For system-side changes:

  1. Create a new script at install/config/my-feature.sh.
  2. Add the following line to install/config/all.sh:
    run_logged "$OMARCHY_INSTALL/config/my-feature.sh"

For per-user changes:

  1. Create a new script at install/user/my-feature.sh.
  2. Source it within install/user/all.sh:
    source "$OMARCHY_INSTALL/user/my-feature.sh"

Both approaches automatically inherit logging via run_logged and environment variable injection.

Common Operations and Examples

Run the per-user finalizer manually (normally invoked automatically):

omarchy provision user

Force re-run after adding a new leaf script:

omarchy provision user --force

Execute first-run steps manually (rarely needed):

omarchy provision first-run

Example leaf script structure for user customization:

#!/usr/bin/env bash

# File: install/user/example.sh

source "$OMARCHY_INSTALL/helpers/logging.sh"

run_logged "Installing example configuration"
mkdir -p ~/.config/example
echo "option = true" > ~/.config/example/settings.conf

Summary

  • Root-side installation runs via omarchy-apply-system in the ISO chroot, sourcing install/{config,hardware,login,post-install}/all.sh to configure system defaults.
  • Per-user finalization executes through bin/omarchy-provision-user, creating skill symlinks, updating XDG directories, and sourcing install/user/all.sh while respecting the finalize-user idempotency marker.
  • First-run setup triggers on initial graphical login via omarchy-provision-first-run, enabling user systemd units and applying desktop settings, protected by the first-run-user marker.
  • Idempotency is enforced by bin/omarchy-done, which manages marker files under ~/.local/state/omarchy/done/ to prevent duplicate operations.
  • Logs for root-side operations write to /var/log/omarchy-install.log via the run_logged helper in install/helpers/logging.sh.

Frequently Asked Questions

What is the difference between omarchy-apply-system and omarchy-provision-user?

omarchy-apply-system runs during ISO creation inside a chroot environment as root, configuring system-wide settings in /etc and /usr/share. omarchy-provision-user runs after installation as the target user, managing home directory configuration, skill symlinks, and user-specific settings with full idempotency protection.

How does Omarchy ensure finalize scripts do not run multiple times?

The system uses marker files managed by bin/omarchy-done. omarchy-provision-user checks for ~/.local/state/omarchy/done/finalize-user before executing and creates this marker upon completion. Subsequent runs exit immediately unless the --force flag is provided or the marker file is manually removed.

Where are Omarchy installation logs stored?

Root-side installation steps log to /var/log/omarchy-install.log through the run_logged function defined in install/helpers/logging.sh. Per-user finalization also uses run_logged (or a fallback implementation) to record operations, though output typically appears in the terminal during interactive use.

How do I add a custom step to the per-user finalizer?

Create a new shell script in install/user/ (for example, install/user/custom.sh) and source it from install/user/all.sh. The finalizer will automatically execute your script with proper logging and environment variables, provided the finalize-user marker is cleared or --force is used on the next run.

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 →