Omarchy First-Run Provisioning Workflow: How It Automates User Setup on Initial Login

The Omarchy first-run provisioning workflow is a declarative, idempotent shell script that configures a fresh user environment exactly once—enabling systemd units, applying themes, installing notification hooks, and displaying welcome messages—triggered automatically on first login via Hyprland's autostart hook.

Omarchy, Basecamp's opinionated Linux desktop environment, handles user onboarding through a carefully orchestrated provisioning system. When you log into a fresh Omarchy installation for the first time, the omarchy-provision-first-run script executes automatically, transforming a generic system into a personalized workspace without manual intervention. This article explains the complete workflow architecture, underlying scripts, and how you can interact with or troubleshoot the process.


Entry Point: How the Workflow Launches

The provisioning chain begins inside the Hyprland compositor configuration. In [default/hypr/autostart.lua](https://github.com/basecamp/omarchy/blob/quattro/default/hypr/autostart.lua), the autostart hook calls the main provisioning script:

-- Located in default/hypr/autostart.lua
spawn_once("omarchy-provision-first-run")

This ensures the workflow runs automatically when the graphical session starts, but only completes successfully once per user.


Core Script: omarchy-provision-first-run

The orchestrator lives at bin/omarchy-provision-first-run. It implements four key architectural patterns:

1. Idempotence Through State Tracking

The script uses omarchy-done, a flag-tracking utility, to prevent duplicate runs:

FIRST_RUN_DONE="first-run-user"
OMARCHY_STATE="${XDG_STATE_HOME:-$HOME/.local/state}/omarchy"

# Check if already completed

if omarchy-done check "$FIRST_RUN_DONE" && [[ "$1" != "--force" ]]; then
    echo "First run already completed. Use --force to re-run."
    exit 0
fi

The flag file is stored in ~/.local/state/omarchy/first-run-user. Pass --force to override and re-run the entire workflow.

2. Base User Provisioning

Before user-specific setup, the script invokes omarchy-provision-user:

omarchy-provision-user "$@" || true

This || true pattern makes the step fault-tolerant—the user may have been provisioned during system installation.

3. Structured Step Execution

Each provisioning phase runs through run_first_run_step, which provides unified logging, timing, and failure tracking:

run_first_run_step() {
    local step_name="$1"
    local step_script="$2"
    
    echo "[$(date --iso-8601=seconds)] START: $step_name" >> "$LOG_FILE"
    
    if bash "$step_script" >> "$LOG_FILE" 2>&1; then
        echo "[$(date --iso-8601=seconds)] DONE: $step_name" >> "$LOG_FILE"
    else
        echo "[$(date --iso-8601=seconds)] FAIL: $step_name" >> "$LOG_FILE"
        first_run_failed=1
    fi
}

4. Notification Service Synchronization

Before displaying UI feedback, the script waits for the notification daemon:

omarchy-notification-wait --timeout=30 || echo "WARNING: Notification service not ready" >> "$LOG_FILE"

This prevents silent failures when the notification subsystem hasn't finished initializing.


Provisioning Steps Explained

The workflow executes eight distinct steps, each implemented as a focused shell script in install/user/first-run/:

Step Purpose Source File
Voxtype hook Schedules post-update prompt to install Voxtype dictation software install-voxtype.hook
Fingerprint setup hook Notifies user to configure fingerprint authentication setup-fingerprint.hook
Agent setup hook Prompts user to configure Omarchy background agents setup-agent.hook
Enable user units Activates per-user systemd services (timers, daemons) [enable-user-units.sh](https://github.com/basecamp/omarchy/blob/quattro/install/user/first-run/enable-user-units.sh)
GNOME theme Applies the configured GTK/Icon theme [gnome-theme.sh](https://github.com/basecamp/omarchy/blob/quattro/install/user/first-run/gnome-theme.sh)
GTK primary paste Enables middle-click paste behavior in GTK apps [gtk-primary-paste.sh](https://github.com/basecamp/omarchy/blob/quattro/install/user/first-run/gtk-primary-paste.sh)
Speaker tuning Applies audio output optimization [audio-tuning.sh](https://github.com/basecamp/omarchy/blob/quattro/install/user/first-run/audio-tuning.sh)
Welcome notification Displays initial user greeting [welcome.sh](https://github.com/basecamp/omarchy/blob/quattro/install/user/first-run/welcome.sh)
Wi-Fi/update scheduling Registers periodic network and update reminders [wifi.sh](https://github.com/basecamp/omarchy/blob/quattro/install/user/first-run/wifi.sh)

Each script follows the Unix philosophy: single purpose, readable implementation, and independent testability.


Completion and Failure Handling

After executing all steps, the workflow evaluates overall success:

if [[ $first_run_failed -eq 0 ]]; then
    omarchy-done mark "$FIRST_RUN_DONE"
    notify-send "Omarchy" "First-run provisioning complete" --icon=dialog-information
else
    notify-send "Omarchy" "First-run provisioning had errors. Check $LOG_FILE" --icon=dialog-warning
    exit 1
fi

Successful completion writes the persistent flag. Failures preserve the incomplete state, triggering a retry on next login.


Practical Usage and Troubleshooting

Running the Workflow Manually


# Default: run only if not previously completed

omarchy-provision-first-run

# Force complete re-run after configuration changes

omarchy-provision-first-run --force

Examining Provisioning Logs


# View the detailed execution log

cat ~/.local/state/omarchy/first-run.log

# Follow live output during manual execution

tail -f ~/.local/state/omarchy/first-run.log & omarchy-provision-first-run --force

Executing Individual Steps


# Run only the systemd units step

bash "$OMARCHY_PATH/install/user/first-run/enable-user-units.sh"

# Source OMARCHY_PATH if undefined

export OMARCHY_PATH="${OMARCHY_PATH:-/usr/lib/omarchy}"

Resetting First-Run State


# Remove completion flag to trigger fresh run

rm ~/.local/state/omarchy/first-run-user

Architectural Strengths of the Design

The Omarchy first-run provisioning workflow demonstrates several engineering best practices:

  • Idempotence: State flags prevent destructive re-execution
  • Observability: Comprehensive logging to ~/.local/state/omarchy/first-run.log
  • Fault isolation: Per-step error containment with || true or explicit failure tracking
  • Modularity: Each concern separated into testable scripts
  • Graceful degradation: Notification timeouts don't block core functionality
  • Retry semantics: Failure preserves incomplete state for automatic recovery

Summary


Frequently Asked Questions

What triggers the Omarchy first-run provisioning workflow?

The workflow launches automatically when Hyprland starts, via the autostart hook in [default/hypr/autostart.lua](https://github.com/basecamp/omarchy/blob/quattro/default/hypr/autostart.lua). This calls omarchy-provision-first-run without requiring manual user action.

How do I re-run the first-run provisioning after making changes?

Execute omarchy-provision-first-run --force. The --force flag bypasses the completion check stored in ~/.local/state/omarchy/first-run-user and re-executes all provisioning steps regardless of prior state.

Where are the first-run provisioning logs stored?

All execution output writes to ~/.local/state/omarchy/first-run.log. Each step records start timestamps, completion status, and any error output, enabling post-hoc debugging of provisioning failures.

Can I run individual provisioning steps without the full workflow?

Yes. Each step is implemented as an independent shell script in install/user/first-run/. Source the OMARCHY_PATH environment variable and execute any script directly with bash "$OMARCHY_PATH/install/user/first-run/<script-name>.sh".

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 →