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

> Learn how Omarchy bootstraps its runtime by customizing the Lua module path for user state, overrides, and default modules. Explore environment setup in this deep dive.

- Repository: [Omacom/omarchy](https://github.com/omacom/omarchy)
- Tags: deep-dive
- Published: 2026-09-08

---

**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`](https://github.com/omacom/omarchy/blob/main/default/hypr/bootstrap.lua). When the Hyprland compositor starts, it executes this script directly via:

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

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

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

```bash
#!/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`](https://github.com/omacom/omarchy/blob/main/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`](https://github.com/omacom/omarchy/blob/main/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.