xfetch has a theme system that separates visual appearance (colors, icons, layout) from module configuration, letting you switch looks without touching your module setup.
Themes operate at the config-loading layer, before any rendering or plugin execution. When you set "theme": "berlin" in config.jsonc, xfetch resolves the theme file, parses it, and merges three layers together:
config.jsonc (theme: "berlin", modules: [...])
|
v
1. Load default Config (hardcoded defaults)
|
v
2. Load user config.jsonc
|
v
3. Load theme/berlin.jsonc ← highest priority
|
v
4. Deep-merge: defaults → config.jsonc → theme
|
v
Final Config (used by renderer)
Starting from xfetch v0.2.0, the merge order gives the theme the highest priority:
| Layer | Source | Contains |
|---|---|---|
| 1. Core defaults | Hardcoded in config.rs | Default icons, colors, layout, modules |
| 2. User config | config.jsonc | modules, info_plugins, plus any visual overrides |
| 3. Theme file | themes/<name>.jsonc | colors, icons, layout, palette_style, show_colors, header_icons, footer_text, logo_path |
A field in the theme file always wins over the same field in config.jsonc or defaults. This means the theme provides the final look, while config.jsonc handles module selection and plugin config.
Note: In v0.1.x the order was reversed (config.jsonc won over theme). If you're upgrading, you may need to move any visual overrides from config.jsonc into the theme file if you want the theme to control them.
The merge uses deep_merge() which works key-by-key:
- Objects: merged recursively — each key is resolved independently
- Strings, numbers, booleans: overlay replaces base
- Empty strings: an empty string does not override a non-empty string (prevents themes from accidentally clearing icons)
- Empty objects
{}: no-op — existing keys are preserved
A theme file is a JSONC document containing only visual fields:
{
"layout": "section",
"show_colors": true,
"palette_style": "circles",
"colors": {
"os": "Magenta",
"cpu": "Red",
"memory": "Yellow",
"disk": "Cyan",
"shell": "Green",
"wm": "Blue"
},
"icons": {
"os": "\uf17c",
"cpu": "\uf2db",
"memory": "\ue266",
"disk": "\uf0a0",
"shell": "\uf0e7",
"wm": "\uf08e"
}
}
| Field | Type | Description |
|---|---|---|
layout | string or null | Layout style: default, pacman, section, side-block, tree, compact, minimal, horizontal, bottom, box, line, dots, bottom-line |
colors | object | Per-module color mapping. Keys are module names, values are color names: Black, Red, Green, Yellow, Blue, Magenta, Cyan, White, Grey/Gray, and dark variants. |
icons | object | Per-module icon mapping. Values can be Nerd Font glyphs, emoji, or any text. |
palette_style | string or null | Palette display: squares, circles, triangles, lines, dots |
show_colors | boolean | Show inline ANSI color swatches next to each module |
logo_path | string or null | Path to a logo file (ASCII, PNG, SVG) |
header_icons | array or null | Pac-Man layout top-border icons |
footer_text | string or null | Pac-Man layout bottom-border text |
When xfetch loads a config with "theme": "dracula", it searches in order:
- Direct path — If the value contains
/or starts with~, load it directly as a file path - Themes directory — Look for
<name>.jsoncin~/.config/xfetch/themes/
If the theme is not found, the config loads without the theme (no error).
# List installed themes
xfetch theme list
# Activate a theme (writes "theme" field into config.jsonc)
xfetch theme set nord
# Remove a theme file
xfetch theme remove nord
# Export current visual config as a reusable theme file
xfetch theme export my-theme
xfetch theme export <name> captures the current runtime visual state (after all three layers are merged) and writes it to ~/.config/xfetch/themes/<name>.jsonc. This lets you share your look without exposing your module list or plugin config.
The exported file contains only visual fields: layout, colors, icons, palette_style, header_icons, footer_text, logo_path, show_colors.
~/.config/xfetch/
config.jsonc # Modules, plugins, and theme reference
themes/
berlin.jsonc # Theme files: colors, icons, layout
dracula.jsonc
nord.jsonc
catppuccin-mocha.jsonc
retro-pacman.jsonc
tree-compact.jsonc
In v0.1.x, config.jsonc won over the theme. If you had a detailed config with explicit colors/icons and then set a theme, nothing would visibly change.
To migrate to v0.2.0+:
- Export your current look:
xfetch theme export my-look - Set it:
xfetch theme set my-look - Remove visual fields (
colors,icons,layout, etc.) fromconfig.jsoncso the theme can fully control them - Keep
modulesandinfo_pluginsinconfig.jsonc
- Keep visual fields (colors, icons, layout) in theme files, not in
config.jsonc - Keep structural fields (modules, info_plugins) in
config.jsonc - Create a separate theme file for each visual variant you want
- Export your current config as a starting point:
xfetch theme export my-base