# How the Omarchy Theming System Works: Architecture, Activation Flow, and Customization

> Explore the Omarchy theming system architecture, activation flow, and customization. Learn how Omarchy enables secure, reproducible theme switching with user overrides.

- Repository: [Omacom/omarchy](https://github.com/omacom/omarchy)
- Tags: architecture
- Published: 2026-09-01

---

**Omarchy's theming system separates palette data, template generation, and runtime activation to enable secure, reproducible theme switching with full user override support.**

The Omarchy window manager, developed by the `omacom/omarchy` project, implements a sophisticated theming pipeline that lets users switch desktop appearances on-the-fly. This article explains how the system handles theme storage, template rendering, runtime activation, and user customization based on the source code implementation.

## Theme Layout and Storage Hierarchy

Themes in Omarchy follow a two-tier storage model that balances official distribution with user customization.

Official themes ship under `themes/<name>/` in the source tree and install to `/usr/share/omarchy/themes/<name>/`. Users can override any theme by creating parallel structures in `~/.config/omarchy/themes/<name>/`. This overlay approach ensures system updates never destroy personal modifications.

Each theme typically contains a [`colors.toml`](https://github.com/omacom/omarchy/blob/main/colors.toml) file that defines the palette. When this file is missing, the activation script automatically derives one from [`alacritty.toml`](https://github.com/omacom/omarchy/blob/main/alacritty.toml) using the `omarchy-theme-colors-from-alacritty` helper. This fallback mechanism ensures themes can be imported from existing terminal configurations without manual palette extraction.

## The Template Engine: From Palette to Config

Omarchy's **template rendering system** transforms palette values into application-specific configuration files. The `omarchy-theme-set-templates` command processes every `.tpl` file in `default/themed/*.tpl`, replacing placeholders with actual color values.

### Placeholder Syntax

Template files use Jinja-style placeholders with Omarchy-specific extensions:

- **Basic colors**: `{{ accent }}` → `#7aa2f7`
- **Stripped variants**: `{{ accent_strip }}` → `7aa2f7` (no leading `#`)
- **RGB format**: `{{ accent_rgb }}` → `122,162,247`

### Color Mixing and Gradients

Advanced helpers enable sophisticated color manipulation:

- **Proportional mixing**: `{{ mix background foreground 15% }}` blends two colors by percentage, with `_strip` and `_rgb` suffix variants available
- **Hyprland gradients**: `{{ hypr_gradient hyprland_active_border accent }}` converts gradient strings to Lua tables for the compositor
- **Shell gradients**: `{{ shell_gradient ... }}` produces raw gradient strings for QML consumption

### Override Protection

Hand-written files in `themes/<name>/`—such as [`shell.toml`](https://github.com/omacom/omarchy/blob/main/shell.toml) or [`hyprland.lua`](https://github.com/omacom/omarchy/blob/main/hyprland.lua)—always take precedence over generated equivalents. This guarantee ensures that custom configurations are never accidentally overwritten during theme activation.

## Theme Activation Flow

When a user executes `omarchy-theme-set <name>`, the script in `bin/omarchy-theme-set` performs an eight-step atomic activation:

1. **Stage creation**: Creates `~/.local/state/omarchy/current/next-theme` as a clean working directory
2. **Base copy**: Copies the official theme from `$OMARCHY_PATH/themes/<name>/`
3. **User overlay**: Merges user-provided theme from `~/.config/omarchy/themes/<name>/`

   Security restriction: Themes installed from Git repositories have Lua scripts, terminal configs, and [`vscode.json`](https://github.com/omacom/omarchy/blob/main/vscode.json) stripped—only color files are accepted

4. **Palette generation**: Produces [`colors.toml`](https://github.com/omacom/omarchy/blob/main/colors.toml) from [`alacritty.toml`](https://github.com/omacom/omarchy/blob/main/alacritty.toml) if the palette file is missing
5. **Template rendering**: Executes `omarchy-theme-set-templates` to populate all `.tpl` files
6. **Atomic swap**: Snapshots the current background, then renames the staging directory to `~/.local/state/omarchy/current/theme`
7. **Runtime notification**: Sends [`colors.toml`](https://github.com/omacom/omarchy/blob/main/colors.toml) and [`shell.toml`](https://github.com/omacom/omarchy/blob/main/shell.toml) payloads to the running shell via IPC, updates the background symlink, and triggers the `theme-set` hook
8. **Service restart**: Launches post-theme commands in parallel—restarting terminals, Hyprland, btop, and other themed applications

The entire operation holds a file lock at `${XDG_RUNTIME_DIR:-/tmp}/omarchy-theme-set.lock` to prevent race conditions during concurrent theme changes.

## Runtime Consumption in the Shell

The generated [`shell.toml`](https://github.com/omacom/omarchy/blob/main/shell.toml) (produced from `default/themed/shell.toml.tpl`) feeds two QML singletons at runtime:

- **`Color`**: Exposes palette values and surface roles
- **`Style`**: Provides spacing, typography, and bar sizing constants

UI components access theme-aware borders through the `BorderSurface` API, which ensures consistent application of colors, gradients, widths, and alpha values across the desktop. This abstraction layer shields components from direct color manipulation while enabling dynamic theme switching without restarts.

## Practical Commands and Configuration

### CLI Operations

```bash

# List all available themes

omarchy theme list

# Apply a theme immediately

omarchy theme set "Tokyo Night"

# Preview a theme's color ramp

omarchy dev theme-preview Tokyo-Night

```

### Example Palette Definition

```toml

# ~/.config/omarchy/themes/MyTheme/colors.toml

mode = "dark"
accent = "#7aa2f7"
selection = "#292e42"
muted = "#414868"

background = "#1a1b26"
dark_background = "#13141c"
lighter_background = "#24283b"

foreground = "#a9b1d6"
red = "#f7768e"
blue = "#7aa2f7"

```

### QML Usage

```qml
// Component consuming themed values
BorderSurface {
    color: Color.popups.background
    borderSpec: Border.surfaceSpec("popups", "border", Color.popups.border, 2)
}

```

## Key Source Files

| Path | Purpose |
|------|---------|
| [`docs/theming.md`](https://github.com/omacom/omarchy/blob/main/docs/theming.md) | Complete documentation of placeholders, mixing syntax, and gradient helpers |
| `bin/omarchy-theme-set` | Main activation script with staging, security filtering, and IPC |
| `bin/omarchy-theme-set-templates` | Template engine for `.tpl` file processing |
| `default/themed/*.tpl` | Built-in templates for shell, Hyprland, and application configs |

## Summary

- **Separation of concerns**: Palette ([`colors.toml`](https://github.com/omacom/omarchy/blob/main/colors.toml)), templates (`.tpl` files), and runtime (QML singletons) operate independently
- **Layered storage**: System themes in `/usr/share/` and user overrides in `~/.config/` merge safely
- **Security-first Git imports**: Remote themes are sanitized to prevent arbitrary code execution
- **Atomic activation**: Staging directory + file lock ensures consistent state transitions
- **Override preservation**: Hand-written configs always win over generated files
- **Live switching**: IPC notification updates running components without full session restart

## Frequently Asked Questions

### How do I create a custom theme in Omarchy?

Create a directory at `~/.config/omarchy/themes/<name>/` containing at minimum a [`colors.toml`](https://github.com/omacom/omarchy/blob/main/colors.toml) file. Add any `.tpl` templates you want generated, or include hand-written files like [`shell.toml`](https://github.com/omacom/omarchy/blob/main/shell.toml) or [`hyprland.lua`](https://github.com/omacom/omarchy/blob/main/hyprland.lua) to bypass generation entirely. Run `omarchy theme set <name>` to activate.

### Why are some files missing when I install a theme from Git?

Omarchy's `omarchy-theme-set` script strips Lua scripts, terminal configurations, and [`vscode.json`](https://github.com/omacom/omarchy/blob/main/vscode.json) from Git-installed themes as a security measure. Only color-related files are accepted from untrusted sources. To use full theme capabilities, install themes locally under `~/.config/omarchy/themes/` or trust the source and copy files manually.

### Can I modify a single color without copying a full theme?

Yes. Create a minimal user override in `~/.config/omarchy/themes/<original-name>/colors.toml` containing only the values you want to change. The overlay system in `omarchy-theme-set` merges your partial definition with the base theme, preserving all other palette entries and generated configs.

### What happens if template rendering fails mid-activation?

The staging directory approach prevents partial application. All rendering occurs in `~/.local/state/omarchy/current/next-theme` before an atomic rename to `theme`. If any step fails—missing palette, template syntax error, or lock contention—the staging directory is discarded and the current theme remains active without interruption.