# Omarchy Theme Activation Flow: Complete Pipeline Guide

> Understand the Omarchy theme activation flow. Learn how Omarchy sets themes, applies overlays, renders templates, and updates your environment for a seamless experience.

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

---

**When you run `omarchy theme set <name>`, Omarchy builds a staged theme at `~/.local/state/omarchy/current/next-theme`, applies user overlays with optional filtering for third-party themes, renders templates from `default/themed/*.tpl`, moves the result to the active location, and fires hooks to update the running environment.**

The basecamp/omarchy repository implements a robust activation pipeline that ensures safe, reproducible theme switching. Understanding the Omarchy theme activation flow helps developers customize their desktop environment while maintaining system integrity. This process handles everything from built-in themes to user-written overlays and third-party git installations.

## The Six-Stage Activation Pipeline

When executing `omarchy theme set <name>` or the shortcut `omarchy-theme-set <name>`, the system follows a strict sequence defined in `bin/omarchy-theme-set`.

### Stage 1: Create the Staging Directory

Omarchy first constructs a clean workspace at `~/.local/state/omarchy/current/next-theme`. This staging area serves as a build environment where the theme is assembled, validated, and prepared before becoming active. Using a staging directory ensures that the current running theme remains untouched until the new theme is fully validated and ready.

### Stage 2: Copy Base Theme and Apply Overlays

The system copies the requested theme from the read-only source tree at `themes/<name>/` into the staging area. Then it checks for user-written overlays at `~/.config/omarchy/themes/<name>/` and layers those files on top.

**Security filtering** applies differently based on theme provenance:

- **User-written themes**: Full overlay copy without restrictions
- **Git-installed themes**: Only *allowed* files (colors, icons, etc.) are overlaid; disallowed files (Lua scripts, terminal configs, [`vscode.json`](https://github.com/basecamp/omarchy/blob/main/vscode.json), etc.) are dropped and reported to *stderr*

This filtering prevents third-party themes from executing arbitrary code while preserving aesthetic customizations.

### Stage 3: Generate Missing Files from Templates

The `omarchy-theme-set-templates` command renders any `*.tpl` files found in `default/themed/` (such as `shell.toml.tpl` or `hyprland.lua.tpl`) using the theme's [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml). This step only executes when the staged theme contains a [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml) file.

Template rendering bridges the gap between static theme assets and dynamic configuration files that require specific color values or environment-specific paths.

### Stage 4: Move to Active Location

Once staging is complete, Omarchy atomically moves the contents from `next-theme` to `~/.local/state/omarchy/current/theme`. It writes the selected theme name to a `theme.name` file in that directory. This location is what the running shell reads to apply colors, icons, and other visual properties.

The atomic move operation ensures that the active theme is never in a partially-copied state.

### Stage 5: Notify the Running Environment

After activation, Omarchy executes the **theme-set hook** located at `~/.config/omarchy/hooks/theme-set*` with the theme name passed as `$1`. It then runs the `post_theme_commands` list defined in `bin/omarchy-theme-set`, which typically restarts or retints applications that need to pick up new colors.

The hook dispatch runs under a file lock (`flock`) to serialize concurrent theme changes and prevent race conditions during environment updates.

### Stage 6: Background and Preview Handling

The theme switcher UI (`omarchy-theme-switcher`) can invoke the same pipeline and updates background images (`preview.png`, `unlock.png`, etc.) as part of the staging step. Any errors about dropped files during this process print to *stderr* for developer visibility.

## Key Implementation Files

- **`bin/omarchy-theme-set`**: Core implementation of the activation pipeline that orchestrates the six-stage process
- **`bin/omarchy-theme-set-templates`**: Handles rendering of `*.tpl` files into the staged theme using color definitions
- **[`docs/theming.md`](https://github.com/basecamp/omarchy/blob/main/docs/theming.md)**: Authoritative documentation covering the theme workflow and security considerations
- **[`test/shell.d/theme-staging-test.sh`](https://github.com/basecamp/omarchy/blob/main/test/shell.d/theme-staging-test.sh)**: Automated test suite verifying each step of the staging process
- **`default/themed/*.tpl`**: Template files (e.g., `shell.toml.tpl`, `hyprland.lua.tpl`) used to generate missing theme assets

## Practical Usage Examples

Activate a built-in theme:

```bash
omarchy theme set "Tokyo Night"

```

Activate a user-written theme with full overlay support:

```bash
omarchy theme set my-custom

```

Install and activate a third-party theme (with automatic filtering):

```bash
omarchy theme install https://github.com/example/omarchy-theme.git
omarchy theme set example-theme

```

Create a post-theme hook to reload your terminal:

```bash
#!/usr/bin/env bash

# ~/.config/omarchy/hooks/theme-set/01-reload.sh

omarchy-theme-color   # regenerates terminal colour scheme

kill -USR1 "$(pidof alacritty)" 2>/dev/null || true

```

## Summary

- **Staging architecture**: Omarchy builds themes in `~/.local/state/omarchy/current/next-theme` before activation to ensure atomic deployment
- **Security filtering**: Git-installed themes automatically drop disallowed files (Lua scripts, terminal configs) while preserving colors and icons
- **Template system**: The `omarchy-theme-set-templates` utility generates dynamic config files from `*.tpl` templates using the theme's [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml)
- **Atomic activation**: The final move to `~/.local/state/omarchy/current/theme` happens only after all validation and generation steps complete
- **Hook integration**: Custom scripts in `~/.config/omarchy/hooks/theme-set*` execute under `flock` serialization to safely update running applications

## Frequently Asked Questions

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

Omarchy maintains the active theme at `~/.local/state/omarchy/current/theme`, with a `theme.name` file identifying the selected theme. During activation, it temporarily builds the theme in a `next-theme` subdirectory before atomically moving it to the active location.

### How does Omarchy handle third-party themes differently than custom themes?

For themes installed from git repositories, Omarchy applies a strict filter that drops disallowed files like Lua scripts, terminal configs, and [`vscode.json`](https://github.com/basecamp/omarchy/blob/main/vscode.json) to prevent code execution, reporting drops to *stderr*. User-written themes in `~/.config/omarchy/themes/<name>/` receive full overlay privileges without filtering.

### What happens if theme activation fails midway?

Because Omarchy uses a staging directory (`next-theme`) and only moves to the active location after all templating and validation succeeds, failures during staging leave the current active theme untouched. The file lock (`flock`) mechanism ensures that concurrent activation attempts queue safely rather than corrupting the theme state.

### Can I run custom commands after a theme switches?

Yes. Place executable scripts in `~/.config/omarchy/hooks/theme-set*` (e.g., [`theme-set/01-reload.sh`](https://github.com/basecamp/omarchy/blob/main/theme-set/01-reload.sh)). These hooks receive the theme name as the first argument (`$1`) and execute after the theme moves to the active location but before the templating process completes.