# How the Omarchy Template System Works: A Declarative Theming Pipeline

> Discover how the Omarchy template system works. This declarative pipeline renders static .tpl files into configuration files using a theme's color palette.

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

---

**The Omarchy template system is a deterministic theming pipeline that renders static `.tpl` templates into concrete configuration files by substituting color placeholders with values defined in a theme's [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml) palette.**

The Omarchy template system provides a declarative approach to Linux desktop theming, allowing users to define a single color palette that automatically propagates across terminal emulators, window managers, and applications. According to the basecamp/omarchy source code, this architecture separates color definitions from configuration logic, enabling consistent themes without manually editing dozens of config files.

## Theme Structure and Palette Definition

Themes reside in `themes/<name>/` for built-in themes or `~/.config/omarchy/themes/<name>/` for user-created variants. The only required file is **[`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml)**, which defines the color palette that every template can reference. This centralized palette approach ensures that changing a single hex value automatically updates every dependent application configuration.

## Template Sources and Precedence

All built-in templates are plain text files ending in `.tpl` and reside in `default/themed/*.tpl`. Users may add custom overrides in `~/.config/omarchy/themed/*.tpl`, which the system processes first, taking precedence over built-in templates. This layered approach allows users to customize specific application configurations without forking the entire theme.

## The Activation Pipeline

When you invoke **`omarchy-theme-set <name>`**, the system executes a deterministic activation flow:

1. Creates a clean staging area at `~/.local/state/omarchy/current/next-theme`
2. Copies first-party theme files into the staging directory
3. Overlays any user-provided theme files
4. Generates a [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml) from an [`alacritty.toml`](https://github.com/basecamp/omarchy/blob/main/alacritty.toml) if needed
5. Runs **`omarchy-theme-set-templates`** to render every `.tpl` into concrete config files

This process ensures atomic theme switching—the current configuration remains untouched until the new theme is fully rendered and validated.

## Rendering Mechanics and Placeholders

The `omarchy-theme-set-templates` command reads each template and performs substitution based on [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml). The system supports several placeholder types:

- **Simple color keys**: `{{ accent }}` produces `#7aa2f7`, while `{{ accent_strip }}` outputs `7aa2f7` (no hash), and `{{ accent_rgb }}` yields `122,162,247` (comma-separated values)
- **Color mixing**: `{{ mix background foreground 15% }}` blends two colors by the specified percentage
- **Gradient helpers**: `{{ hypr_gradient hyprland_active_border accent }}` converts Hyprland-style gradients into Lua tables, while `{{ shell_gradient ... }}` generates shell-compatible border tokens

Rendering only occurs if a [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml) is present in the theme directory.

## File Precedence and Safety Guards

If a concrete configuration file already exists (for example, a hand-written [`shell.toml`](https://github.com/basecamp/omarchy/blob/main/shell.toml)), the template is skipped entirely. This safety mechanism ensures that user-created configurations always win over generated output, preventing accidental overwrites of manual customizations.

## Post-Activation Hooks

After the staging directory moves into place, `omarchy-theme-set` fires a **`theme-set`** hook and retints all running applications—including terminals, Hyprland, browsers, and editors—via the `post_theme_commands` list defined in `bin/omarchy-theme-set`.

## Practical Examples

### Creating a Custom Template

```bash

# Create a user template that uses the palette

cat >"$HOME/.config/omarchy/themed/alacritty.toml.tpl" <<'EOF'
background = "{{ background }}"
foreground = "{{ foreground }}"
cursor     = "{{ accent_rgb }}"
selection  = "{{ selection }}"
EOF

```

### Activating a Theme

```bash

# Set a theme (this runs the whole pipeline)

omarchy-theme-set solarized-dark

```

### Manual Rendering for Debugging

```bash

# Render templates manually (useful for debugging)

omarchy-theme-set-templates

# Or preview a single template without affecting current theme

OMARCHY_PATH="$PWD" omarchy-theme-set-templates \
  --template "$HOME/.config/omarchy/themed/alacritty.toml.tpl"

```

### Using Gradient Helpers

In `default/themed/hyprland.lua.tpl`:

```text
local border = {{ hypr_gradient hyprland_active_border accent }}

```

When the theme defines `hyprland_active_border = "rgba(33ccffee) rgba(00ff99ee) 45deg"`, the rendered output becomes:

```lua
local border = { colors = { "rgba(33ccffee)", "rgba(00ff99ee)" }, angle = 45 }

```

## Summary

- Themes require only a [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml) file to define the palette, stored in either the system `themes/<name>/` or user `~/.config/omarchy/themes/<name>/` directories.
- Templates use `.tpl` extensions in `default/themed/` or user overrides in `~/.config/omarchy/themed/`, with user templates taking precedence.
- The `omarchy-theme-set` command orchestrates the full pipeline: staging, overlaying, and rendering via `omarchy-theme-set-templates`.
- Placeholders like `{{ accent }}`, `{{ mix ... }}`, and `{{ hypr_gradient ... }}` provide powerful color manipulation without scripting.
- Existing concrete config files automatically override templates, protecting manual customizations.
- Post-activation hooks ensure all running applications immediately reflect the new theme.

## Frequently Asked Questions

### How do I override a built-in template without modifying system files?

Place your custom `.tpl` file in `~/.config/omarchy/themed/`. The Omarchy template system processes user templates before built-ins, so your version takes precedence while leaving the original system files untouched.

### What happens if I have both a template and a concrete configuration file?

The concrete file wins. If [`shell.toml`](https://github.com/basecamp/omarchy/blob/main/shell.toml) exists, the system skips rendering `shell.toml.tpl` entirely. This safety guard ensures that hand-written configurations are never overwritten by the templating engine.

### Can I use the template system for applications not included in Omarchy?

Yes. Create a new `.tpl` file in `~/.config/omarchy/themed/` using the placeholder syntax documented in [`docs/theming.md`](https://github.com/basecamp/omarchy/blob/main/docs/theming.md). As long as your template references valid color keys from [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml), the `omarchy-theme-set-templates` command will process it during theme activation.

### How do I debug why my template isn't rendering correctly?

Run `omarchy-theme-set-templates` manually to see real-time rendering output, or use the `--template` flag with a specific file path to test individual templates without activating the full theme. Check that your [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml) is valid and that you're using the correct placeholder syntax—either simple keys like `{{ accent }}` or helper functions like `{{ mix background foreground 20% }}`.