Runtime Finalization with `omarchy-provision-user`: How Omarchy Prepares User Environments
The omarchy-provision-user script finalizes per-user runtime configuration after system-wide provisioning completes, using idempotency markers to prevent duplicate work and supporting forced re-runs via the --force flag.
In the Omarchy repository, user environment setup is deliberately split into static configuration (applied during the initial refresh) and runtime finalization (applied when a user actually logs in). The omarchy-provision-user script handles the latter—steps that cannot be expressed in configuration files because they depend on the active user context, such as dev-aware skill symlinks or per-user state directories.
What omarchy-provision-user Does
The script performs runtime-only tweaks that complete a user's Omarchy environment. These include creating skill symlinks, adjusting user-specific configurations, and setting up per-user runtime state.
According to the Omarchy source code, the finalizer is designed to be:
- Idempotent – Safe to run multiple times without side effects
- Conditional – Skips work when a completion marker exists
- Forceable – Allows override via
--forcefor upgrades or repairs
How the Finalization Chain Works
Three scripts cooperate to ensure proper initialization:
| Script | Purpose | Key Interaction |
|---|---|---|
omarchy-provision-owner |
System-wide provisioning | Calls user finalizer after system setup |
omarchy-provision-first-run |
First-login wrapper | Builds arguments and invokes finalizer |
omarchy-provision-user |
Per-user runtime finalization | Executes actual user-level setup |
1. System-Wide Provisioning Triggers User Finalization
After installing packages and configuring system services, omarchy-provision-owner invokes the user finalizer with flags indicating a first-install scenario:
"$OMARCHY_PATH/bin/omarchy-provision-user" --force --first-install
See omarchy-provision-owner#L851
2. First-Run Wrapper Collects Arguments
The omarchy-provision-first-run script gathers configuration arguments and passes them to the finalizer:
omarchy-provision-user "${finalize_user_args[@]}" || true
See omarchy-provision-first-run#L46
Argument collection occurs earlier in the same script (lines 19–24), allowing customization of the finalization process.
3. User Finalization Executes Runtime Logic
Once invoked, omarchy-provision-user follows this control flow:
# Check for existing completion marker
if omarchy-done check finalize-user && (( force == 0 )); then
exit 0
fi
# ... perform runtime setup ...
# Record completion
omarchy-done mark finalize-user
See idempotency check at L59 and marker creation at L130
The usage signature is defined at L10.
Idempotency and the Marker System
The finalizer avoids redundant work through state markers stored in ~/.local/state/omarchy/done/.
| Command | Behavior |
|---|---|
omarchy-done check finalize-user |
Returns success if marker exists |
omarchy-done mark finalize-user |
Creates marker after successful completion |
The --force flag bypasses this check, enabling re-finalization after environment changes or upgrades.
Practical Usage Examples
# Automatic first-login execution (no manual invocation needed)
# This runs automatically via shell profile integration
# Force re-finalization after adding new skills
omarchy-provision-user --force
# Typical invocation from system provisioning
omarchy-provision-user --force --first-install
Why Separate Runtime Finalization?
Certain configuration steps cannot be performed statically:
- Dev-aware symlinks – Skill directories may reference
OMARCHY_PATHlocations that differ across installations - Per-user state – Marker files and runtime directories must reside in
$HOME - Conditional setup – Some steps depend on the execution environment present only during active login
By isolating these in omarchy-provision-user, Omarchy maintains clean separation between system-level and user-level concerns.
Source File Reference
| File | URL |
|---|---|
bin/omarchy-provision-user |
https://github.com/omacom/omarchy/blob/quattro/bin/omarchy-provision-user |
bin/omarchy-provision-owner |
https://github.com/omacom/omarchy/blob/quattro/bin/omarchy-provision-owner |
bin/omarchy-provision-first-run |
https://github.com/omacom/omarchy/blob/quattro/bin/omarchy-provision-first-run |
bin/omarchy-done |
https://github.com/omacom/omarchy/blob/quattro/bin/omarchy-done |
Summary
omarchy-provision-usercompletes per-user environment setup that static configuration cannot express- Idempotency markers in
~/.local/state/omarchy/done/prevent duplicate work; use--forceto override - The script is invoked automatically via
omarchy-provision-first-runor directly fromomarchy-provision-ownerduring first install - Dev-aware paths and user-specific state require this runtime separation from system-wide provisioning
Frequently Asked Questions
How do I re-run the user finalizer after modifying my Omarchy skills?
Pass the --force flag to bypass the idempotency check: omarchy-provision-user --force. This recreates symlinks and applies any new runtime configuration without requiring manual marker deletion.
Where does omarchy-provision-user store its completion state?
The marker file is created at ~/.local/state/omarchy/done/finalize-user via the omarchy-done mark command, checked via omarchy-done check at L59.
What is the difference between omarchy-provision-owner and omarchy-provision-user?
omarchy-provision-owner performs system-wide setup (packages, services, global configuration) while omarchy-provision-user handles per-user runtime finalization that requires an active user environment. The owner script triggers the user script at L851 during first install.
When is omarchy-provision-first-run executed?
This wrapper runs automatically when a user logs in for the first time, collecting arguments and invoking the finalizer at L46 to complete environment setup before interactive use begins.
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 →