Anatomy of a theme
The whole file tree
Only colors.toml is genuinely required. Everything else is optional, and a good first theme ships three files.
omarchy-yourname-theme/
├── colors.toml the palette — the only required file
├── backgrounds/ wallpapers, cycled with Super + Ctrl + Space
│ ├── 001-first-light.png
│ └── 002-late-shift.png
├── icons.theme one line: the GTK icon set name
├── preview.png thumbnail for the theme picker
├── unlock.png lock-screen art (transparent PNG)
├── preview-unlock.png thumbnail for Style > Unlock
├── keyboard.rgb six hex digits for RGB keyboards
├── btop.theme hand-written, overrides the generated file
├── chromium.theme
├── helix.toml
├── shell.toml replaces the whole generated shell config
├── shell.bar.toml …or replace just the [bar] section
├── README.md
└── LICENSEFile reference
| File | What it does |
|---|---|
colors.toml | The palette. Every generated configuration is rendered from these keys. See the reference. |
backgrounds/ | Wallpapers, one directory deep. JPEG, JPG, PNG, GIF, BMP and WebP are recognised; they are cycled in sorted filename order. |
icons.theme | A single line naming a GTK icon set so the file manager matches your colours. The built-in options are the Yaru family: Yaru, Yaru-blue, Yaru-dark, Yaru-magenta, Yaru-olive, Yaru-prussiangreen, Yaru-purple, Yaru-red, Yaru-sage, Yaru-wartybrown and Yaru-yellow. |
preview.png | The image the theme picker shows for your theme. |
unlock.png and preview-unlock.png | Ship both and your theme is offered under Style > Unlock. The unlock image should be a transparent PNG; omarchy plymouth preview <background-hex> <text-hex> <logo.png> <output.png> renders the matching preview. |
keyboard.rgb | Six hex digits, no #, for supported RGB keyboards. |
light.mode | An empty marker file that forces light mode. Still honoured, but mode = "light" in colors.toml is the current way to say it. |
shell.toml | Replaces the entire generated Omarchy shell configuration: bar sizing, control states, spacing, typography, corner radii. |
shell.<section>.toml | Replaces one section of the generated shell config after it is built — shell.lock.toml becomes [lock], shell.bar.toml becomes [bar]. The section header inside the file is optional; the filename decides. |
btop.theme, chromium.theme, helix.toml, hermes.yaml, obsidian.css, claude.json, pi.json, t3code.json, vscode-theme.json | Hand-written application colours. Ship one and Omarchy skips generating it. |
README.md, LICENSE | Not read by Omarchy, but they are what a person sees before installing your theme. Ship both. |
What an installed theme may not ship
A theme you write by hand is yours, and Omarchy stages all of it. A theme cloned from someone else’s repository is held to a shorter list: installing a theme should change what your desktop looks like, never what it runs.
From a cloned theme, Omarchy drops:
- Any
*.luafile. Hyprland loads a theme’shyprland.luaandgum_env.luaat login, and Neovim loadsneovim.luaat startup. alacritty.toml,foot.ini,ghostty.confandkitty.conf. Each one names the program the terminal launches.vscode.json, which names an extension to install — and a VS Code extension is arbitrary JavaScript.- Every symlink, at any depth, because in a cloned theme it points wherever the theme author chose.
Everything that is colour is kept exactly as you wrote it, including files Omarchy would otherwise have generated. Anything dropped is regenerated from your colors.toml and named on stderr, so nothing fails silently. Omarchy tells a cloned theme from a hand-written one by the .git directory that omarchy theme install leaves behind.
Design around this rather than against it. If your theme only looks right with a custom hyprland.lua, it will not look right for anyone who installs it.
A theme older than colors.toml is not left without a palette: its alacritty.toml is converted to a palette in a scratch directory, and only the resulting colors.toml is staged.
Theming an application Omarchy does not cover
Templates belong to the user, not to the theme — a cloned theme cannot install one. If you use an application Omarchy does not theme, drop a file in ~/.config/omarchy/themed/ named after the config it produces, plus a .tpl extension, and write the config with palette placeholders.
gui:
theme:
activeBorderColor: ["{{ accent }}", bold]
inactiveBorderColor: ["{{ muted }}"]
selectedLineBgColor: ["{{ selection }}"]The file is regenerated on every theme switch. Your templates are processed before Omarchy’s, so naming one after a built-in output also overrides how that application is themed. There is a fully commented alacritty.toml.tpl.sample in that directory listing every variable available.