How Omarchy Processes Theme .tpl Templates with {{ Variable }} Placeholders
Omarchy renders theme .tpl templates into concrete configuration files by using a sed‑based substitution engine defined in bin/omarchy-theme-set-templates, which replaces {{ variable }} placeholders with values derived from the theme’s colors.toml palette.
The Omarchy desktop environment (omacome/omarchy) uses a template-driven theming system that converts abstract color palettes into application-specific config files. When you activate a theme with omarchy-theme-set, the system processes hidden-hand .tpl templates located in default/themed/ and ~/.config/omarchy/themed/ to generate finalized configs like hyprland.lua and alacritty.toml. This pipeline—validated by the test suite in test/shell.d/theme-staging-test.sh—handles everything from simple hex colors to interpolated gradients.
The Theme Activation Pipeline
When a user runs omarchy-theme-set <theme_name>, the command creates a clean staging directory at ~/.local/state/omarchy/current/next-theme. It copies the selected theme assets, including colors.toml, and then invokes bin/omarchy-theme-set-templates to perform the actual rendering. This separation keeps the activation logic distinct from the template engine, as documented in docs/theming.md.
Building the Color Palette Map
Before any substitution occurs, the engine loads the palette into an associative array named THEME_COLORS. The script reads the theme’s colors.toml via omarchy-theme-color --file "$COLORS_FILE" --all, parsing tab-delimited key-value pairs.
while IFS=$'\t' read -r key value; do
THEME_COLORS[$key]="$value"
done < <(omarchy-theme-color --file "$COLORS_FILE" --all)
This array maps keys like accent to hex values like #7aa2f7, forming the lookup table for all subsequent replacements.
Processing Simple Color Placeholders
For every entry in THEME_COLORS, the add_template_value function generates three distinct sed substitution rules. These allow template authors to request colors in different formats without manual conversion.
Hex, Strip, and RGB Variants
- **
{{ key }}** → Raw hex value (e.g.,#7aa2f7) - **
{{ key_strip }}** → Hex without the hash (e.g.,7aa2f7) - **
{{ key_rgb }}** → Comma-separated decimal RGB (e.g.,122,162,247)
The script constructs these rules using printf (see lines 100‑107):
printf 's|{{ %s }}|%s|g\n' "$key" "$value"
printf 's|{{ %s_strip }}|%s|g\n' "$key" "${value#\#}"
printf 's|{{ %s_rgb }}|%s|g\n' "$key" "$(hex_to_rgb "$value")"
Example usage in default/themed/alacritty.toml.tpl:
[colors]
foreground = "{{ foreground }}"
background = "{{ background_strip }}"
cursor = "{{ accent_rgb }}"
Advanced Variable Processing
Beyond static color lookups, the engine supports computed values through color mixing and gradient parsing helpers defined in the same bin/omarchy-theme-set-templates script.
Color Mixing with mix, mix_strip, and mix_rgb
Templates can interpolate between two palette colors using the syntax {{ mix <start_key> <end_key> <amount> }}. The engine detects these tokens via grep -Eo in the add_mix_values function (lines 49‑51).
For each match, add_mix_value performs four operations:
- Retrieves the start and end colors from
THEME_COLORS. - Uses an
awkfunctionmix_colorto linearly interpolate the two hex values. - Optionally strips the leading
#or converts to decimal RGB based on the token suffix. - Emits a sed substitution rule that replaces the entire token with the computed value.
Example usage:
selection = "{{ mix background foreground 20% }}"
This mixes 20% of the foreground color into the background color, outputting a new hex value.
Gradient Helpers
When a palette entry contains Hyprland-style gradient strings like rgba(33ccffee) rgba(00ff99ee) 45deg, three helpers parse and reformat them:
{{ hypr_gradient <key> <fallback> }}→ Generates a Lua table:{ colors = { "rgba(33ccffee)", "rgba(00ff99ee)" }, angle = 45 }{{ gradient_start <key> <fallback> }}→ Returns the first solid color as hex:#33ccff(or the fallback if parsing fails){{ shell_gradient <key> <fallback> }}→ Emits the raw gradient string:rgba(33ccffee) rgba(00ff99ee) 45deg
The implementation lives in add_gradient_function_value and its helpers hypr_gradient_value, gradient_start_value, and shell_gradient_value (lines 54‑78), with regex parsing in add_gradient_function_values (lines 84‑90).
Example in a Lua template:
local active_border = {{ hypr_gradient hyprland_active_border accent }}
Rendering the Final Configuration Files
After collecting all sed rules into a temporary script file ($sed_script), the engine iterates over template files. User-provided templates in ~/.config/omarchy/themed/ are processed first; if a generated file already exists, built-in templates are skipped.
for tpl in "${template_files[@]}"; do
filename=$(basename "$tpl" .tpl)
output_path="$NEXT_THEME_DIR/$filename"
[[ ! -f $output_path ]] && sed -f "$sed_script" "$tpl" >"$output_path"
done
The [[ ! -f $output_path ]] check enforces user‑overrides‑built‑in ordering. The rendered files land in the staging directory and are moved to the active theme location by the parent omarchy-theme-set process.
Summary
- Omarchy uses
bin/omarchy-theme-set-templatesto render.tplfiles into concrete configs during theme activation. - The engine loads
colors.tomlinto aTHEME_COLORSassociative array to fuel substitutions. - Simple placeholders support three formats: raw hex (
{{ key }}), stripped hex ({{ key_strip }}), and decimal RGB ({{ key_rgb }}). - The
mixfunction performs linear interpolation between two palette colors with_stripand_rgbvariants. - Gradient helpers parse Hyprland-style color lists into Lua tables, hex values, or raw strings.
- User templates in
~/.config/omarchy/themed/override built-in defaults indefault/themed/.
Frequently Asked Questions
Where are the template files located in Omarchy?
Omarchy ships with default templates in default/themed/ (e.g., default/themed/shell.toml.tpl). Users can create custom overrides in ~/.config/omarchy/themed/, which take precedence over the built-in versions during the rendering process.
What file handles the actual template rendering logic?
The bin/omarchy-theme-set-templates script contains the complete rendering engine. It is invoked by bin/omarchy-theme-set after the theme has been staged in ~/.local/state/omarchy/current/next-theme.
Can I use color mixing in my custom templates?
Yes. The template engine supports {{ mix <color1> <color2> <percentage> }} syntax, which linearly interpolates between two palette colors. You can also use mix_strip or mix_rgb suffixes to output the result in different formats.
How does Omarchy handle conflicting template files?
The rendering loop processes user templates first and skips built-in templates if the output file already exists. This user‑overrides‑built‑in behavior ensures that custom configurations in ~/.config/omarchy/themed/ always take priority over files in default/themed/.
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 →