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

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 file that defines the palette. When this file is missing, the activation script automatically derives one from 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 or 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 stripped—only color files are accepted

  4. Palette generation: Produces colors.toml from 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 and 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 (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


# 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


# ~/.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

// 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 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), 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 file. Add any .tpl templates you want generated, or include hand-written files like shell.toml or 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 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →