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

> Discover the Omarchy first-run provisioning workflow. Automate user setup on first login, enabling systemd units, themes, and more with this idempotent script.

- Repository: [37signals/omarchy](https://github.com/basecamp/omarchy)
- Tags: how-to-guide
- Published: 2026-08-20

---

**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/main/default/hypr/autostart.lua)](https://github.com/basecamp/omarchy/blob/quattro/default/hypr/autostart.lua), the autostart hook calls the main provisioning script:

```lua
-- 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`](https://github.com/basecamp/omarchy/blob/quattro/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:

```bash
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`](https://github.com/basecamp/omarchy/blob/quattro/bin/omarchy-provision-user):

```bash
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:

```bash
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:

```bash
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/`](https://github.com/basecamp/omarchy/tree/quattro/install/user/first-run):

| Step | Purpose | Source File |
|------|---------|-------------|
| **Voxtype hook** | Schedules post-update prompt to install Voxtype dictation software | [`install-voxtype.hook`](https://github.com/basecamp/omarchy/blob/quattro/install/user/first-run/install-voxtype.hook) |
| **Fingerprint setup hook** | Notifies user to configure fingerprint authentication | [`setup-fingerprint.hook`](https://github.com/basecamp/omarchy/blob/quattro/install/user/first-run/setup-fingerprint.hook) |
| **Agent setup hook** | Prompts user to configure Omarchy background agents | [`setup-agent.hook`](https://github.com/basecamp/omarchy/blob/quattro/install/user/first-run/setup-agent.hook) |
| **Enable user units** | Activates per-user systemd services (timers, daemons) | [[`enable-user-units.sh`](https://github.com/basecamp/omarchy/blob/main/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/main/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/main/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/main/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/main/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/main/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:

```bash
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

```bash

# 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

```bash

# 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

```bash

# 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

```bash

# 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

- The **Omarchy first-run provisioning workflow** triggers automatically via [[`autostart.lua`](https://github.com/basecamp/omarchy/blob/main/autostart.lua)](https://github.com/basecamp/omarchy/blob/quattro/default/hypr/autostart.lua) on initial Hyprland login
- Orchestrated by [`bin/omarchy-provision-first-run`](https://github.com/basecamp/omarchy/blob/quattro/bin/omarchy-provision-first-run), which uses `omarchy-done` for idempotence
- Performs **base user provisioning**, **systemd unit activation**, **theme configuration**, **audio tuning**, and **notification setup**
- Eight modular scripts in [`install/user/first-run/`](https://github.com/basecamp/omarchy/tree/quattro/install/user/first-run) handle specific tasks
- Supports **`--force`** for re-runs and provides detailed logging for troubleshooting
- Completes by marking state only when all steps succeed, enabling automatic retry on partial failure

---

## 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/main/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/`](https://github.com/basecamp/omarchy/tree/quattro/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"`.