# How Omarchy Manages Themes: Template-Driven Customization in Basecamp's Linux Desktop

> Discover how Omarchy manages themes with a template-driven system. Learn about shell commands, placeholder rendering, and protecting user overrides in Basecamp's Linux desktop.

- Repository: [37signals/omarchy](https://github.com/basecamp/omarchy)
- Tags: how-to-guide
- Published: 2026-08-29

---

**Omarchy manages themes through a three-layer template system where shell commands like `omarchy-theme-set` update state files, `omarchy-theme-set-templates` renders `{{variable}}` placeholders against [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml) definitions, and guard logic in [`install/config/theme-system.sh`](https://github.com/basecamp/omarchy/blob/main/install/config/theme-system.sh) protects user overrides from being overwritten.**

Omarchy is Basecamp's opinionated Arch Linux desktop environment designed for deep customization without core code modification. Understanding how Omarchy manages themes reveals a sophisticated template engine that synchronizes appearances across Quickshell, Qtile, and GTK while keeping user changes safe from updates. The workflow centers on [`install/user/theme.sh`](https://github.com/basecamp/omarchy/blob/main/install/user/theme.sh), which coordinates rendering and application through a strict precedence hierarchy.

## The Three-Layer Theme Architecture

Omarchy's theming system organizes assets into distinct layers that prioritize user customizations over system defaults.

### Default Theme Assets

The foundation resides in `default/themes/` and `default/themed/*.tpl`. The `default/themes/` directory contains baseline color palettes such as *catppuccin* and *gruvbox*, each defined in a [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml) file. Meanwhile, `default/themed/` stores QML and GTK template files containing `{{variable}}` placeholders that await substitution during the rendering phase.

### User Override Directory

Individual customizations live in `~/.config/omarchy/themes/`. Any [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml), `background.png`, or font file placed here masks the corresponding default asset. According to the source logic, the system always checks this location first, ensuring personal modifications persist across system updates.

### Runtime Resolution Layer

The [`install/user/theme.sh`](https://github.com/basecamp/omarchy/blob/main/install/user/theme.sh) script and the `omarchy-theme-*` command suite form the active resolution layer. At login, these tools read the active theme state from `~/.config/omarchy/theme/current`, parse the relevant [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml), and expand templates into runtime locations like `~/.config/qtile/theme.py` and `~/.config/gtk-3.0/gtk.css`.

## Theme Selection and State Persistence

Theme selection begins with the **`omarchy-theme-set <name>`** command implemented in [`install/user/theme.sh`](https://github.com/basecamp/omarchy/blob/main/install/user/theme.sh). This utility updates a small state file at `~/.config/omarchy/theme/current` that records the chosen theme identifier. The resolver reads this file on each startup to determine which theme directory to source for subsequent rendering operations.

## Template Rendering Engine

All UI components use templates stored under `default/themed/` that contain `{{variable}}` placeholders for colors and assets. The **`omarchy-theme-set-templates`** helper performs the actual rendering by:

1. Loading [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml) from the active theme directory
2. Parsing each `*.tpl` file and substituting placeholders with concrete hexadecimal color values
3. Writing expanded files to the user's configuration tree, such as `~/.config/quickshell/theme.qml`

This template engine allows a single theme definition to propagate consistently across Quickshell, Qtile, and GTK environments without manual synchronization.

## Applying Themes to Sub-Systems

After template generation completes, the **`omarchy-theme-apply`** command distributes assets to subsystem-specific directories:

- **Quickshell**: Copies generated QML files to `~/.config/quickshell/`
- **Qtile**: Writes [`theme.py`](https://github.com/basecamp/omarchy/blob/main/theme.py) and CSS files to `~/.config/qtile/`
- **GTK**: Installs the generated [`gtk.css`](https://github.com/basecamp/omarchy/blob/main/gtk.css) into `~/.config/gtk-3.0/`

If user overrides exist in `~/.config/omarchy/themes/`, the resolver incorporates those values automatically before writing to runtime locations, ensuring custom colors take precedence.

## Guard Logic for User Customization Safety

The **[`install/config/theme-system.sh`](https://github.com/basecamp/omarchy/blob/main/install/config/theme-system.sh)** script contains protective guard logic that prevents accidental overwriting of user customizations. Before copying any default asset, the system checks for a user-provided counterpart in the override directory. If a custom file exists, the script skips the copy operation, preserving user modifications during theme updates or re-installations.

## Creating Custom Themes and Validation

Extending Omarchy's visual palette requires no core code changes.

### Adding a New Theme

To create a custom theme:

1. Copy an existing folder from `default/themes/` into `~/.config/omarchy/themes/`
2. Edit [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml) or add custom `background.png` and font files
3. Execute `omarchy-theme-set <new-name>` to activate the configuration

The system regenerates all templates on the next login, or immediately if you manually invoke `omarchy-theme-set-templates`.

### Automated Testing

The repository includes shell-based tests verifying theme pipeline integrity. The [`test/shell.d/theme-install-guards-test.sh`](https://github.com/basecamp/omarchy/blob/main/test/shell.d/theme-install-guards-test.sh) script asserts that user overrides take precedence, while [`test/shell.d/theme-staging-test.sh`](https://github.com/basecamp/omarchy/blob/main/test/shell.d/theme-staging-test.sh) validates that template rendering produces expected output files. Run the full suite with `./test/shell` to confirm theming system behavior on a fresh clone.

## Essential Theme Management Commands

```bash

# List available themes

omarchy-theme-list

# Switch to the "catppuccin" theme

omarchy-theme-set catppuccin

# Re-render templates without logging out

omarchy-theme-set-templates

# Manually apply the currently rendered theme

omarchy-theme-apply

```

All commands source their logic from [`install/user/theme.sh`](https://github.com/basecamp/omarchy/blob/main/install/user/theme.sh) and operate on the file structures defined in the basecamp/omarchy repository.

## Summary

- Omarchy manages themes through a **template-driven workflow** separating defaults, user overrides (`~/.config/omarchy/themes/`), and runtime application
- The **`omarchy-theme-set`** command persists theme selection to `~/.config/omarchy/theme/current`
- **Template rendering** occurs via `omarchy-theme-set-templates`, substituting `{{variable}}` placeholders with values from [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml)
- **Guard logic** in [`install/config/theme-system.sh`](https://github.com/basecamp/omarchy/blob/main/install/config/theme-system.sh) protects user customizations from being overwritten by defaults
- **Testing scripts** in [`test/shell.d/theme-install-guards-test.sh`](https://github.com/basecamp/omarchy/blob/main/test/shell.d/theme-install-guards-test.sh) and [`test/shell.d/theme-staging-test.sh`](https://github.com/basecamp/omarchy/blob/main/test/shell.d/theme-staging-test.sh) validate theme installation and rendering correctness

## Frequently Asked Questions

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

Omarchy records the active theme name in `~/.config/omarchy/theme/current`. The `omarchy-theme-set` command updates this file, and the runtime resolver reads it during startup to determine which theme directory to process for template rendering.

### How do I prevent Omarchy from overwriting my custom color scheme?

Place your modified [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml) or any custom assets in `~/.config/omarchy/themes/`. The guard logic in [`install/config/theme-system.sh`](https://github.com/basecamp/omarchy/blob/main/install/config/theme-system.sh) checks this directory before copying default files and skips any assets where user versions exist, ensuring your customizations remain intact.

### Can I create a theme without modifying the Omarchy source code?

Yes. Copy any theme from `default/themes/` into your user directory at `~/.config/omarchy/themes/`, modify the [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml) or template files, and run `omarchy-theme-set <your-theme-name>`. The system treats user directories as authoritative without requiring changes to the base installation in `/usr/share/omarchy` or the repository root.

### What file format does Omarchy use for theme color definitions?

Omarchy uses **TOML** files named [`colors.toml`](https://github.com/basecamp/omarchy/blob/main/colors.toml) to define color palettes. These files contain key-value pairs that map to the `{{variable}}` placeholders in the `default/themed/*.tpl` template files processed by `omarchy-theme-set-templates`.