# How User Themes Overlay Built-In Omarchy Themes: Complete Technical Guide

> Discover how Omarchy applies user themes by overriding built-in defaults. This guide explains the `~/.config/omarchy/theme/` file replacement process.

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

---

**Omarchy applies user themes by seeding the user configuration directory with built-in template files, then performing a file-by-file replacement where any user-provided files in `~/.config/omarchy/theme/` completely override the corresponding built-in defaults.**

The basecamp/omarchy repository implements a transparent theme overlay system that lets users customize desktop environments without forking entire themes. This architecture stores pristine defaults in `default/themed/` while layering user-specific modifications from the home configuration directory. Understanding how user themes overlaid on top of built-in Omarchy themes function requires examining the interplay between the `omarchy-theme-refresh` and `omarchy-theme-set` utilities.

## Theme Storage Architecture

Omarchy maintains a strict separation between immutable built-in themes and mutable user overrides.

- **Built-in themes** reside in `default/themed/<theme-name>/` and contain template files (`.tpl`, `.lua`, `.json`) that define colors, fonts, and UI settings using placeholders like `{{ variable }}`.
- **User themes** live in `~/.config/omarchy/theme/<theme-name>/` and contain only the specific files the user chooses to override.

When the overlay system activates, it treats the built-in directory as the baseline and the user directory as a selective patch layer.

## The Three-Stage Overlay Mechanism

The overlay process operates through three distinct phases orchestrated by shell scripts in the `bin/` directory.

### Stage 1: Seeding the User Directory

The `bin/omarchy-theme-refresh` script initializes the user theme workspace without destroying existing customizations.

```bash
omarchy-theme-refresh kanagawa

```

This command copies files from `default/themed/kanagawa/` to `~/.config/omarchy/theme/kanagawa/` **only if they do not already exist**. This non-destructive seeding ensures users always have a complete set of editable templates while preserving modifications across theme updates. The verification logic for this behavior appears in [`test/shell.d/user-theme-test.sh`](https://github.com/basecamp/omarchy/blob/main/test/shell.d/user-theme-test.sh).

### Stage 2: Rendering the Built-In Base

When applying a theme, the `bin/omarchy-theme-set` script first loads the complete built-in theme from `default/themed/<theme>/`. It parses template files and expands placeholders using the base color palette defined in the theme's [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml). This generates a complete, rendered configuration set representing the default appearance.

### Stage 3: Applying User Overrides

After rendering the base, `omarchy-theme-set` iterates through the user theme directory at `~/.config/omarchy/theme/<theme>/`. For every file present in the user directory, the script **completely replaces** the corresponding built-in file in the rendered output. This is a file-level replacement, not a deep merge of configuration keys.

The script then writes the final composite configuration to runtime locations such as Hyprland, foot, and Alacritty configuration directories.

## Creating and Applying Custom Theme Overrides

To customize a theme without duplicating the entire codebase:

1. **Initialize the user theme directory** to expose editable templates:

```bash
omarchy-theme-refresh kanagawa

```

2. **Modify specific files** in the user directory. For example, create `~/.config/omarchy/theme/kanagawa/hyprland.lua` with a custom accent color:

```lua
-- User override replacing default hyprland.lua
colors.accent = "#FF5733"

```

3. **Apply the theme** to activate the overlay:

```bash
omarchy-theme-set kanagawa

```

The command renders the built-in Kanagawa theme, then overlays your [`hyprland.lua`](https://github.com/basecamp/omarchy/blob/main/hyprland.lua) file, replacing the default accent color definition while preserving all other theme settings.

## Source File Reference

| Path | Function |
|------|----------|
| `default/themed/<theme>/*.tpl` | Built-in template files containing placeholders for color expansion |
| `bin/omarchy-theme-refresh` | Seeds user directories with default files only when missing |
| `bin/omarchy-theme-set` | Loads built-in themes and applies user file overrides |
| `~/.config/omarchy/theme/<theme>/` | User override storage location |
| [`test/shell.d/user-theme-test.sh`](https://github.com/basecamp/omarchy/blob/main/test/shell.d/user-theme-test.sh) | Automated tests verifying non-destructive seeding behavior |

## Summary

- **Non-destructive seeding**: `omarchy-theme-refresh` copies built-in files to the user directory only if absent, preserving existing edits.
- **File-level overlay**: User themes override built-in defaults by replacing entire files, not by merging individual configuration keys.
- **Template rendering**: Built-in themes use placeholder syntax expanded before user overlays are applied.
- **Runtime application**: The `omarchy-theme-set` script writes the final composite configuration to window manager and terminal emulator configs.
- **Selective customization**: Users need only copy and modify the specific files they wish to change, leaving the default infrastructure intact.

## Frequently Asked Questions

### What happens if I delete a file from my user theme directory?

If you remove a file from `~/.config/omarchy/theme/<theme>/`, the next time you run `omarchy-theme-set`, the system will use the built-in version of that file from `default/themed/<theme>/`. The overlay system falls back to defaults for any files not present in the user directory, allowing you to revert specific settings by simply deleting your custom copies.

### Does Omarchy merge individual configuration keys or entire files?

Omarchy performs **entire file replacement**, not deep merging. If you provide a [`colors.lua`](https://github.com/basecamp/omarchy/blob/main/colors.lua) file in your user theme directory, it completely replaces the built-in [`colors.lua`](https://github.com/basecamp/omarchy/blob/main/colors.lua) for that theme. To modify a single color, you must copy the entire file and edit the specific value, which is why the `omarchy-theme-refresh` command seeds complete file sets initially.

### Where does Omarchy store the active theme configuration?

Omarchy writes the final rendered configuration to your system's standard configuration paths (e.g., `~/.config/hypr/`, `~/.config/foot/`), not to a separate Omarchy runtime directory. The overlay mechanism generates these files dynamically by combining `default/themed/` templates with `~/.config/omarchy/theme/` overrides at application time.

### How do I revert a theme to its original built-in state?

To restore a theme to pristine defaults, delete the corresponding directory in `~/.config/omarchy/theme/<theme-name>/` and run `omarchy-theme-set <theme-name>`. This removes all user overrides, causing the system to rely exclusively on files from `default/themed/<theme-name>/` during the next application cycle.