Skip to main content

External themes

OpenUsage loads custom themes from JSON files alongside the bundled set. Drop a file in the right directory, restart the TUI (or press r), and your theme appears in the Theme tab.

File schema

Every theme file is a single JSON object with 24 color fields, a name, and an optional icon. All 24 color fields and name are required; icon is optional. Invalid or incomplete files are silently skipped at load time.

FieldTypePurpose
namestringDisplay name. Must be unique within the merged set; same-name external themes override built-ins.
iconstringOptional emoji or single grapheme shown next to the name.
basehex colorPage background (the darkest layer).
mantlehex colorOne step above base — header strips.
surface0hex colorTile / card background.
surface1hex colorSlight elevation above surface0.
surface2hex colorHighlights and selected rows.
overlayhex colorModal backdrops and tooltips.
texthex colorPrimary foreground.
subtexthex colorSecondary foreground (labels, helper text).
dimhex colorTertiary foreground (timestamps, hints).
accenthex colorBrand accent — used for active selections and highlights.
bluehex colorStatus / chart color.
sapphirehex colorStatus / chart color.
greenhex colorHealthy gauge fill.
yellowhex colorWarning gauge fill.
redhex colorCritical gauge fill, error states.
peachhex colorStatus / chart color.
tealhex colorStatus / chart color.
flamingohex colorStatus / chart color.
rosewaterhex colorStatus / chart color.
lavenderhex colorStatus / chart color.
skyhex colorStatus / chart color.
maroonhex colorStatus / chart color.

Hex values may be 3-digit (#abc) or 6-digit (#aabbcc). Alpha is not supported.

Where to put the file

Two locations are scanned, in order:

  1. <config_dir>/themes/*.json — typically ~/.config/openusage/themes/ (Linux/macOS) or %APPDATA%\openusage\themes\ (Windows).
  2. Each path in the OPENUSAGE_THEME_DIR environment variable, separated by : on Unix or ; on Windows.

Built-in themes load first, then external paths in the order above. A later file with the same name replaces an earlier one.

export OPENUSAGE_THEME_DIR=~/dotfiles/openusage-themes:~/work/themes

Authoring workflow

  1. Copy a built-in close to what you want as a starting point.
  2. Save your edits as ~/.config/openusage/themes/my-theme.json.
  3. Press r in the dashboard, or restart openusage.
  4. Open the Theme tab (, then 3) and select your theme.

Source examples in the repo:

Complete example

A minimal high-contrast theme suitable for accessibility testing:

{
"name": "Hi-Contrast",
"icon": "◆",
"base": "#000000",
"mantle": "#0A0A0A",
"surface0": "#181818",
"surface1": "#2A2A2A",
"surface2": "#3E3E3E",
"overlay": "#2A2A2A",
"text": "#FFFFFF",
"subtext": "#E0E0E0",
"dim": "#A0A0A0",
"accent": "#FFCC00",
"blue": "#3B82F6",
"sapphire": "#0EA5E9",
"green": "#22C55E",
"yellow": "#EAB308",
"red": "#EF4444",
"peach": "#FB923C",
"teal": "#14B8A6",
"flamingo": "#F472B6",
"rosewater": "#FECACA",
"lavender": "#C4B5FD",
"sky": "#7DD3FC",
"maroon": "#9F1239"
}

Tips

:::tip Live iteration With OPENUSAGE_DEBUG=1, the theme loader prints which files were considered and which were skipped — useful when a file isn't showing up. :::

:::warning Strict parsing Unknown extra keys are tolerated, but missing required fields cause silent skip. If your theme doesn't appear, run with OPENUSAGE_DEBUG=1 and look for theme: skipping <path>: <reason>. :::

:::note No reload watcher The TUI loads themes at startup. After editing a JSON file, press r to refresh, or restart the binary. :::

Override a bundled theme

To customize a built-in without forking the source, save a file with the same name:

{
"name": "Tokyo Night",
"icon": "🗼",
"accent": "#FF6600",
"...": "rest of the fields"
}

The bundled "Tokyo Night" disappears and yours takes its place in the Theme tab.