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_stripand_rgbsuffix 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:
-
Stage creation: Creates
~/.local/state/omarchy/current/next-themeas a clean working directory -
Base copy: Copies the official theme from
$OMARCHY_PATH/themes/<name>/ -
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.jsonstripped—only color files are accepted -
Palette generation: Produces
colors.tomlfromalacritty.tomlif the palette file is missing -
Template rendering: Executes
omarchy-theme-set-templatesto populate all.tplfiles -
Atomic swap: Snapshots the current background, then renames the staging directory to
~/.local/state/omarchy/current/theme -
Runtime notification: Sends
colors.tomlandshell.tomlpayloads to the running shell via IPC, updates the background symlink, and triggers thetheme-sethook -
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 rolesStyle: 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 (.tplfiles), 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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →