Skip to content

Theming jjui

Themes allow for detailed control over the application’s appearance.

The following configuration loads a base theme from ~/.config/jjui/themes/my-theme.toml.

~/.config/jjui/config.toml
[ui]
theme = "my-theme"
~/.config/jjui/themes/my-theme.toml
[colors]
":selected" = { bg = "red", bold = true }

A custom theme is self-contained: unspecified styles do not inherit from jjui’s built-in theme. Colors from jj and inline [ui.colors] overrides are still applied on top.

Override parts of the active theme in the ui.colors section. This example loads my-theme and sets the global selected background to red:

[ui]
theme = "my-theme"
[ui.colors]
":selected" = { bg = "red" }

[!NOTE] Theme support is actively being developed. The information on this page is subject to change as the application evolves.

Choose different theme files for light and dark terminal appearances with:

[ui.theme]
light = "my-light-theme"
dark = "my-dark-theme"

A single name selects the same theme file for both appearances:

[ui]
theme = "my-theme"

jjui detects changes to the terminal appearance and reapplies the matching theme.

A structured theme can contain shared colors plus appearance-specific overrides:

~/.config/jjui/themes/my-theme.toml
[colors]
title = "magenta"
":selected" = { bold = true }
[light]
background_blend = 0.2
[light.colors]
":selected" = { bg = "white" }
[dark]
background_blend = 0.4
[dark.colors]
":selected" = { bg = "bright black" }

Shared [colors] are loaded first, then [light.colors] or [dark.colors] overrides are applied for the current terminal appearance. Existing flat theme files remain supported.

Selected styles can use a blended background to maintain contrast across different terminal palettes and component surfaces. background_blend accepts a value from 0.0 to 1.0; 0.0 disables blending, while higher values move the selected background closer to the surrounding surface.

Set the value independently in a theme’s [light] and [dark] sections, as shown above. To override the active theme from config.toml, set one value for both appearances:

[ui]
background_blend = 0.4

Or set an override per appearance:

[ui]
background_blend = { light = 0.2, dark = 0.4 }

When blending is enabled, jjui queries the terminal background and ANSI palette. It reapplies the theme when the terminal background changes.

Theme colors are keyed by a selector that targets a UI element. A color can be a foreground color by itself or a style table.

[colors]
":selected" = { fg = "#FF8C00", bg = "#2B2B2B", bold = true }
border = "bright black"

The style table can contain any of the following properties:

PropertyTypeDescription
fgColorSets the foreground (text) color.
bgColorSets the background color.
boldboolIf true, makes the text bold.
underlineboolIf true, adds an underline to the text.
strikethroughboolIf true, adds a strikethrough line.
italicboolIf true, makes the text italic.
reverseboolIf true, swaps the foreground and background.

Colors can be specified in one of three formats:

  • TrueColor (Hex): A string representing a hex color code (e.g., "#FF4500").
  • Base16 Names: A string for standard terminal colors (e.g., red, bright green, white).
  • ANSI256 Codes: An integer from 0 to 255.

A selector combines a scope, component, role, and optional variant. For example, revset completion text:selected targets the text role in a selected completion row within the revset scope.

Selected variants use a :selected suffix:

"revset completion text" = { fg = "green" }
"revset completion text:selected" = { fg = "bright green" }
":selected" = { bg = "bright black" }

More-specific styles take precedence, while broader selectors fill properties that were not set. This lets :selected provide a global selected background while a role-specific selected style overrides only its foreground.

The legacy form with selected as a selector word, such as "revset completion selected text", remains supported. Prefer the suffix form; if both spellings occur in the same theme layer, the suffix form wins.

These are base elements that apply throughout the application unless overridden by a more specific selector.

  • text: The default style for all text.
  • dimmed: Less important text, such as hints, descriptions, and inactive elements.
  • :selected: The variant for a currently highlighted or active item in a list or menu.
  • border: The style for borders around windows, panes, and pop-ups.
  • title: The style for titles in windows, panes, and menus.
  • shortcut: The style for keyboard shortcuts (e.g., [Enter], [q]).
  • matched: The style for the part of the text that matches user input, typically in a completion or filter.

These styles appear during interactive operations like rebase, squash or duplicate.

  • source_marker: The marker for the revision being moved or acted upon.
  • target_marker: The marker for the destination of the operation.

The input bar at the top of the screen.

  • revset title: The “Revset:” label.
  • revset text: The user input area. It’s recommended to make this bold.
  • Completions Dropdown:
    • revset completion:selected: The highlighted item in the completions list.
    • revset completion matched: The part of a completion that matches the input.
    • revset completion dimmed: The auto-suggested part of a completion.
    • Append :selected to a role, such as revset completion matched:selected, to style that role in the highlighted row.

The central list of commits or operations.

  • revisions: The base style for the entire list area.
  • revisions:selected: The currently highlighted line.
  • revisions dimmed: Hint text shown during interactive operations.

The bar at the bottom showing the current mode and available actions.

  • status: The base style for the entire bar. A distinct bg is recommended.
  • status title: The current mode indicator (e.g., NORMAL). A contrasting bg helps it stand out.
  • The actions also uses shortcut and dimmed styles.

The pop-up list showing the evolution history for a revision.

  • evolog: Base style for the view.
  • evolog:selected: The highlighted item. Can be styled differently from revisions:selected to show which pane is active.

The Git and Bookmarks menus use their own scopes:

  • git / bookmarks: Base styles.
  • git:selected / bookmarks:selected: Selected items.
  • git matched / bookmarks matched: Filter matches.
  • Items also use scoped title, shortcut, dimmed, and border roles.

The pop-up window displaying key-bindings and help text.

  • help: The base style for the window. To avoid a “patchy” look, define a bg color here. This color will serve as the background for the entire content area.
  • The window uses border and title styles.

The pane on the right that shows diffs or other details.

  • preview: The base style for the pane.
  • Uses preview border style for its frame.

The small inline dialog for confirmations (e.g., “Abandon all?”).

  • confirmation: Base style for the dialog. Should have a border.
  • The message uses the global text style.
  • Options use confirmation:selected for the highlighted choice and confirmation dimmed for other choices.
fire theme screenshot
[colors]
"text" = { fg = "#F0E6D2", bg = "#1C1C1C" }
"dimmed" = { fg = "#888888" }
":selected" = { bg = "#4B2401", fg = "#FFD700" }
"border" = { fg = "#3A3A3A" }
"title" = { fg = "#FF8C00", bold = true }
"shortcut" = { fg = "#FFA500" }
"matched" = { fg = "#FFD700", underline = true }
"source_marker" = { bg = "#6B2A00", fg = "#FFFFFF" }
"target_marker" = { bg = "#800000", fg = "#FFFFFF" }
"revisions rebase source_marker" = { bold = true }
"revisions rebase target_marker" = { bold = true }
"status" = { bg = "#1A1A1A" }
"status title" = { fg = "#000000", bg = "#FF4500", bold = true }
"status shortcut" = { fg = "#FFA500" }
"status dimmed" = { fg = "#888888" }
"revset text" = { bold = true }
"revset completion:selected" = { bg = "#4B2401", fg = "#FFD700" }
"revset completion matched" = { bold = true }
"revset completion dimmed" = { fg = "#505050" }
"revisions:selected" = { bold = true }
"oplog:selected" = { bold = true }
"evolog:selected" = { bg = "#403010", fg = "#FFD700", bold = true }
"help" = { bg = "#2B2B2B" }
"help title" = { fg = "#FF8C00", bold = true, underline = true }
"help border" = { fg = "#3A3A3A" }
"git" = { bg = "#2B2B2B" }
"bookmarks" = { bg = "#2B2B2B" }
"confirmation" = { bg = "#2B2B2B" }
"confirmation text" = { fg = "#F0E6D2" }
"confirmation:selected" = { bg = "#4B2401", fg = "#FFD700" }
"confirmation dimmed" = { fg = "#888888" }
"confirmation border" = { fg = "#FF4500" }
"undo" = { bg = "#2B2B2B" }
"undo confirmation dimmed" = { fg = "#888888" }
"undo confirmation:selected" = { bg = "#4B2401", fg = "#FFD700" }
"preview" = { fg = "#F0E6D2" }
Contribute Community