How Omarchy Bootstraps Its Runtime Environment: A Deep Dive into the Lua Module Path and Environment Setup

Omarchy initializes its runtime by setting the OMARCHY_PATH environment variable and executing a Lua bootstrap script that reconstructs package.path to prioritize user-generated state, user overrides, and finally default modules shipped with the distribution.

Omarchy, a distinctive Hyprland-based desktop environment, employs a deterministic, layered initialization system that ensures user customizations take precedence while maintaining fallback to pristine defaults. Understanding how Omarchy bootstraps its runtime environment reveals a sophisticated approach to Lua module resolution and shell command distribution that keeps the system predictable across updates and user modifications.

The Foundation: OMARCHY_PATH Environment Variable

Omarchy’s entire runtime discovery mechanism hinges on the ** OMARCHY_PATH ** environment variable. At login, this variable is injected into the user’s session through a systemd user unit or a profile script installed by the Omarchy package. By default, it points to /usr/share/omarchy, serving as the canonical root for all Omarchy resources, including Lua modules, configuration templates, and helper binaries.

All Omarchy CLI commands and shell integrations rely on this variable to locate default configuration files. The system propagates OMARCHY_PATH to every child process, guaranteeing that nested scripts and spawned applications maintain consistent path resolution. According to the Omarchy source code, if the variable is undefined, bootstrap scripts fallback to /usr/share/omarchy as a hardcoded default.

Lua Module Path Bootstrap Strategy

At the heart of Omarchy’s initialization lies default/hypr/bootstrap.lua. When the Hyprland compositor starts, it executes this script directly via:

dofile((os.getenv("OMARCHY_PATH") or "/usr/share/omarchy") .. "/default/hypr/bootstrap.lua")

This bootstrap file performs two critical functions: it clears previously loaded Omarchy-related modules to prevent stale cache issues, and it reconstructs Lua’s package.path to implement a deterministic search hierarchy.

The Three-Layer Module Resolution Order

The bootstrap script rebuilds package.path to search three distinct locations in strict priority order:

  1. Generated state – ~/.local/state/?.lua for runtime-generated modules
  2. User-provided modules – ~/.config/?.lua for user customizations and themes
  3. Omarchy defaults – $OMARCHY_PATH/?.lua for the distribution’s core modules shipped in /usr/share/omarchy

This layered approach ensures that user-generated runtime data overrides static user configuration, which in turn overrides the base distribution files. When users run omarchy-refresh-config or omarchy-migrate, these utilities leverage the same bootstrap logic to resolve files in $OMARCHY_PATH/config and copy defaults into the user’s ~/.config hierarchy while preserving this search order.

Dynamic Module Cache Clearing

Before reconstructing the path, the bootstrap explicitly clears any previously loaded Omarchy modules from Lua’s global namespace. This guarantees that configuration reloads or Hyprland restarts pick up changes to user themes or custom Lua scripts without requiring a full system restart.

Shell Wrapper Architecture and Binary Distribution

Rather than installing binaries directly to /usr/bin, Omarchy uses a shell wrapper pattern centered around the omarchy-shell binary. All Omarchy CLI commands live as thin wrapper scripts under bin/omarchy-*, which perform two essential operations:

  • They prefix the command search path with $OMARCHY_PATH/bin to ensure helper scripts resolve correctly
  • They explicitly export OMARCHY_PATH to any child processes, maintaining environment consistency across nested invocations

The test suite validates this behavior in test/shell.d/runtime-smoke-test.sh, which launches the shell with an explicit OMARCHY_PATH and verifies that expected modules load from the correct tier of the path hierarchy.

Configuration Refresh and Migration Utilities

Omarchy’s maintenance utilities rely on the bootstrap environment to safely manage configuration updates. The omarchy-refresh-config tool reads default templates from $OMARCHY_PATH/config and copies them into the user’s home directory, while omarchy-migrate uses the same resolution logic to handle version upgrades without overwriting user customizations. Both utilities respect the three-tier module system, ensuring that user overrides remain intact while providing access to updated defaults.

Practical Implementation Examples

To launch a Hyprland session with the proper Omarchy bootstrap, set the environment variable before execution:

export OMARCHY_PATH="/usr/share/omarchy"
exec Hyprland

Within your Hyprland configuration (e.g., ~/.config/hypr/hyprland.lua), ensure the bootstrap runs before any user code:

-- Loads the module path before user scripts execute
dofile((os.getenv("OMARCHY_PATH") or "/usr/share/omarchy") .. "/default/hypr/bootstrap.lua")

When writing custom scripts that invoke Omarchy commands, explicitly set the path to ensure binary discovery:

#!/usr/bin/env bash
export OMARCHY_PATH="/usr/share/omarchy"
omarchy-bar put "Hello from my script!"

Summary

  • OMARCHY_PATH serves as the canonical root for all Omarchy resources, typically set to /usr/share/omarchy via systemd or profile scripts
  • default/hypr/bootstrap.lua reconstructs Lua’s package.path with a deterministic three-tier priority: generated state, user config, then distribution defaults
  • Shell wrappers ensure consistent binary discovery by prepending $OMARCHY_PATH/bin to PATH and propagating the environment variable to child processes
  • Refresh and migration tools leverage the same bootstrap logic to safely manage configuration updates without destroying user customizations
  • The design guarantees that user modifications always override defaults while core functionality falls back to pristine Omarchy distribution files

Frequently Asked Questions

What is the default value of OMARCHY_PATH if the environment variable is not set?

If OMARCHY_PATH is undefined, the bootstrap mechanism falls back to /usr/share/omarchy. This default is hardcoded in the dofile call within default/hypr/bootstrap.lua and throughout the shell wrapper scripts, ensuring the system remains functional even if the environment variable is missing.

How does Omarchy handle module reloading during configuration changes?

The bootstrap process explicitly clears previously loaded Omarchy-related modules from Lua’s package cache before reconstructing package.path. This ensures that when users reload their Hyprland configuration or run omarchy-refresh-config, the system picks up changes to user themes or custom Lua files without requiring a logout or reboot.

Where does Omarchy look for user-customized Lua modules?

Omarchy searches for Lua modules in three locations in strict order: first ~/.local/state/?.lua for runtime-generated state, then ~/.config/?.lua for user customizations, and finally $OMARCHY_PATH/?.lua for distribution defaults. This hierarchy ensures that user-generated data overrides static configuration, which in turn overrides base Omarchy files.

How do Omarchy CLI wrappers maintain environment consistency across nested scripts?

Every bin/omarchy-* wrapper script prefixes the command search path with $OMARCHY_PATH/bin and explicitly exports the OMARCHY_PATH variable to child processes. This propagation ensures that scripts calling other Omarchy commands, or spawning sub-shells, maintain the same base directory context and module resolution behavior as the parent process.

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 →