# What Does `omarchy finalize user` Do? Understanding the User Provisioning Script

> Learn what omarchy finalize user does to complete per-user setup, including symlinks, app configuration, and script sourcing. Understand user provisioning in Oarchy.

- Repository: [37signals/omarchy](https://github.com/basecamp/omarchy)
- Tags: deep-dive
- Published: 2026-08-29

---

**`omarchy finalize user` is an idempotent runtime script that completes per-user setup after the static `/etc/skel` seed, creating symlinks, configuring default applications, and sourcing user-specific install scripts while tracking completion state in `~/.local/state/omarchy/done/finalize-user`.**

The `omarchy finalize user` command is a core utility in the **basecamp/omarchy** repository that bridges the gap between system-wide defaults and live user configuration. Unlike static skeleton files copied at account creation, this script executes runtime logic that requires `$HOME` expansion, environment detection, and dynamic path configuration. It ensures every user receives the correct development environment, AI assistant skills, and desktop integration without manual intervention.

## Core Functionality and Idempotency

The command is implemented in `bin/omarchy-provision-user` and designed to run safely multiple times. It uses an idempotency guard to prevent redundant work unless explicitly overridden.

### Idempotency Check and State Tracking

Before performing any operations, the script verifies whether finalization has already occurred using `omarchy-done check finalize-user`. If the marker file exists at `~/.local/state/omarchy/done/finalize-user`, the script exits immediately. This prevents accidental overwrites of user customizations during routine maintenance. To bypass this guard and force re-execution, pass the `--force` flag.

### Environment Setup

The script establishes critical environment variables that subsequent steps depend upon:
- **`OMARCHY_PATH`**: Points to the repository location
- **`OMARCHY_INSTALL`**: Path to installation scripts
- **`OMARCHY_SETUP_CONTEXT`**: Runtime context flag
- **`$PATH` modification**: Prepends `$OMARCHY_PATH/bin` to ensure Omarchy utilities are available

## Step-by-Step Execution Flow

The finalization process performs eight distinct categories of setup tasks:

**1. Skill Symlink Creation**
The script loops over `"$OMARCHY_PATH"/default/agents/skills/*/` and creates symlinks in multiple AI assistant configuration directories:
- `~/.agents/skills`
- `~/.claude/skills`
- `~/.codex/skills`
- `~/.pi/agent/skills`
- `~/.gemini/config/skills`

This exposes development-aware "skills" to various AI coding assistants without duplicating files.

**2. XDG User Directories and GTK Bookmarks**
Standard directories are ensured via `xdg-user-dirs-update` for `TEMPLATES`, `PUBLICSHARE`, and `DESKTOP`. The script explicitly creates `~/Downloads`, `~/Pictures`, and `~/Videos`, then populates `~/.config/gtk-3.0/bookmarks` with `file://$HOME/<dir> <dir>` entries for quick navigation in GTK file dialogs.

**3. Desktop Application Refresh**
The helper `omarchy-refresh-applications` regenerates per-user `.desktop` launchers, ensuring the application menu reflects current system state.

**4. Default Application Handlers**
Sensible defaults are configured for web browsing and email:
- `xdg-settings set default-web-browser chromium.desktop`
- `xdg-mime default HEY.desktop x-scheme-handler/mailto`

**5. Per-User Install Scripts**
The script sources `"$OMARCHY_INSTALL/user/all.sh"`, which aggregates additional setup tasks including theme installation, Chromium extensions, Git configuration, xcompose settings, mise integration, keyring setup, and hardware-specific quirks.

**6. Migration Tracking (First-Install Mode)**
When invoked with `--first-install` (typically during ISO creation), the script touches marker files under `~/.local/state/omarchy/migrations/` for each shipped migration. This signals that the fresh user account already has all architectural migrations applied.

**7. Completion Marking**
Finally, the script executes `omarchy-done mark finalize-user` to create the completion marker, preventing future automatic runs.

## Command-Line Usage and Options

The script supports several invocation patterns depending on the deployment context:

```bash

# Standard idempotent finalization for the current user

omarchy finalize user

# Force re-execution (useful after updating Omarchy defaults)

omarchy finalize user --force

# First-install mode (marks all migrations as complete)

omarchy finalize user --first-install

```

## Architectural Role in the Setup Pipeline

According to [`docs/file-layout.md`](https://github.com/basecamp/omarchy/blob/main/docs/file-layout.md), `omarchy finalize user` represents the **second layer** of home-directory population. The three-layer architecture follows this sequence:

1. **`/etc/skel`**: Static files copied at user creation time by the system
2. **`omarchy finalize user`**: Dynamic runtime configuration requiring `$HOME` context and environment variables
3. **`omarchy-reinstall-configs`**: Explicit resync operations for updating existing configurations

This layering allows the ISO installation process to create a functional user account immediately while deferring complex setup logic until the proper environment context is available. During installation, the ISO runs `omarchy-provision-user --force --first-install` inside the chroot after creating the target user, and `omarchy-provision-first-run` calls the finalizer during the first graphical login to catch any missed configuration.

## Summary

- **`omarchy finalize user`** completes per-user setup after account creation, implemented in `bin/omarchy-provision-user`.
- The command is **idempotent** by default, tracking state in `~/.local/state/omarchy/done/finalize-user` and skipping work unless `--force` is specified.
- Key actions include creating **AI skill symlinks** across multiple assistant directories, configuring **XDG directories** and **GTK bookmarks**, setting **default applications** (Chromium and HEY), and sourcing **per-user install scripts** from [`install/user/all.sh`](https://github.com/basecamp/omarchy/blob/main/install/user/all.sh).
- The `--first-install` flag marks all shipped migrations as already applied for freshly created users.
- This command bridges static skeleton files and dynamic runtime configuration in the Omarchy architecture.

## Frequently Asked Questions

### What is the difference between `omarchy finalize user` and `/etc/skel`?

`/etc/skel` contains static files that the system copies into new home directories at account creation time, such as dotfiles and basic directories. `omarchy finalize user` performs dynamic configuration that requires runtime environment variables, path expansion, and script execution—tasks impossible for static skeleton files. According to the basecamp/omarchy source code, finalization runs after the skel copy and before any explicit configuration resync.

### Is `omarchy finalize user` safe to run multiple times?

Yes. The script is designed to be **idempotent** and will exit immediately if it detects a completion marker at `~/.local/state/omarchy/done/finalize-user`. You can safely run the command multiple times without duplicating symlinks or overwriting configurations. To force a refresh after changing Omarchy defaults, use the `--force` flag.

### Where does `omarchy finalize user` store its completion state?

The script records completion in `~/.local/state/omarchy/done/finalize-user` using the `omarchy-done` utility. It checks for this marker at startup using `omarchy-done check finalize-user`. In `--first-install` mode, it also touches migration markers under `~/.local/state/omarchy/migrations/` to indicate which architectural migrations have been applied.

### How does `omarchy finalize user` handle AI assistant skills?

The script automatically exposes development skills to multiple AI assistants by creating symlinks from `"$OMARCHY_PATH"/default/agents/skills/*/` into five different configuration directories: `~/.agents/skills`, `~/.claude/skills`, `~/.codex/skills`, `~/.pi/agent/skills`, and `~/.gemini/config/skills`. This ensures consistent tool availability across Claude, Codex, Pi, and Gemini without maintaining duplicate copies of skill definitions.