Table of contents
- Choosing a theme
- Editing a theme
- A light and a dark theme
- Match your terminal
- Importing a theme
- Writing a theme
- Start from another theme
- Reload, export and share
- Chrome colours
- Roles for one piece of chrome
- Border colours
- Borders and titles
- Looks
- Colour depth
- Your terminal's colours
- Cursor colour
- Glyph sets
- Spacing and text
- Quieting what you are not using
- Selection and search colours
- Spotlight
- Related
Colour themes, custom and imported themes, chrome colours, glyph sets, spacing, dimming and the spotlight.
Four things decide what TUIOS looks like:
| Part | What it controls | How to set it |
|---|---|---|
| Colour | The terminal colours, the accents, the borders | appearance.theme |
| Shape | The characters the chrome is drawn with: borders, controls, rules, rail marks | appearance.glyphs |
| Spacing | Empty ground between panes, padding inside dialogs | appearance.gap, appearance.panel_padding |
| Text | What a window title, a workspace tab and the clock show | window_title_format, dock_workspace_tab_format, clock_format |
Every option on this page can be changed while TUIOS runs, from the settings page (, in window mode), with tuios set-config, or by editing config.toml, which is reloaded when saved.
Try it live: the Make it yours track lets you try themes and glyphs in your browser.
Choosing a theme
On Omarchy, tuios uses the Omarchy theme when you set no theme, and follows it when you switch it. (Added in v0.10.0) See Omarchy.
TUIOS ships over 300 themes. A theme sets the 16 ANSI colours plus foreground, background and cursor, and TUIOS derives its own interface colours from them.
[appearance]
theme = "catppuccin_mocha"
# Change it in the running session
tuios set-config appearance.theme catppuccin_mocha
# Start with a theme, overriding the config for this run
tuios --theme dracula
# Find one
tuios list-themes --filter gruvbox
tuios --list-themes | fzf --preview 'tuios --preview-theme {}'
Theme ids use underscores: tokyo_night, not tokyo-night.
In the app, open the picker from the palette (Theme picker) or from the Theme row on the settings page. It is searchable, shows a swatch per theme, and applies the selection live as you move. Esc puts back the theme you started with.
Type to filter the list. The picker also takes these keys: (Added in v0.10.1)
| Key | What it does |
|---|---|
| Ctrl+E | Edit the highlighted theme in the theme editor |
| Ctrl+O | Make a new theme from the highlighted one, and open it in the theme editor |
| Ctrl+F | Show all themes, then only dark ones, then only light ones |
| Ctrl+R | Go to a random theme in the list |
| Ctrl+Y | Copy the id of the highlighted theme |
| Ctrl+D | Delete the highlighted theme file. For an edited built-in theme, remove your edit. Press y to confirm |
A theme from a file in your themes directory shows (yours). A file that uses the id of a built-in theme shows (edited). You cannot delete the theme that is in use, or a theme file that another file names as its base.
In a client of tuios ssh or tuios-web, the arrow keys do not preview a theme. The theme applies to every client of that server, so the picker shows a sample line in the highlighted theme. Enter applies the theme. The glyph picker works the same way. (Added in v0.10.1)
An empty theme turns theming off, except on a machine with Omarchy. TUIOS then emits plain colour indices and your terminal's own palette decides what they look like. theme = "none" turns theming off on every machine. (Added in v0.10.0)
Checking a theme
tuios list-themes <id> prints a theme's colours with the contrast each one measures against the theme's background. It tells you whether a palette is readable before you look at it.
tuios list-themes catppuccin_latte
tuios list-themes catppuccin_latte --json | jq -r '.palette.illegible[]'
tuios list-themes --json | jq -r .active
CharmTone themes
(Added in v0.10.0)
Two built-in themes use CharmTone, the colour system of Charm.
| Theme | Ground | Text | Accent |
|---|---|---|---|
charmtone |
Pepper #201F26 |
Sash #ECEBF0 |
Charple #6B50FF |
charmtone-light |
Salt #F7F6FB |
Char #3A3943 |
Charple #6B50FF |
[appearance]
theme = "charmtone"
background = "theme" # paint the Pepper ground behind the panes
The dark theme uses the ANSI colours of Crush, the coding agent from Charm. Bright black is Squid, so that shell suggestions and comments are easy to read. The light theme uses a darker shade of each colour. CharmTone has no dark yellow, so yellow is Cumin, a light brown. Run tuios list-themes charmtone-light to see the contrast of each colour.
Editing a theme
(Added in v0.10.1)
The theme editor changes a theme's colours while you look at the whole screen. It opens as a sheet on the side with no rail. The panes do not move.
To open it:
- Command palette: Edit theme, for the theme in use.
- Settings, Appearance: Edit theme.
- Theme picker: Ctrl+E edits the highlighted theme. Ctrl+O makes a new theme from it, named
<theme>-custom.
The sheet has three tabs:
- Quick: two seeds, the accent and the surface, and whether the theme is dark. The rest of the chrome follows them. A new theme opens here.
- Roles: the chrome roles, in groups: Accents, Frame, Dock and rail, Dialogs and Status.
Text,Dim textandQuiet textshow their measured colour. You cannot set them. - Pane colours: the foreground, the background, the selection, the cursor and the sixteen. Programs in panes use these colours.
Each row shows the role, a swatch, where the colour comes from, its hex and its contrast. A contrast under its floor shows !: 4.5:1 for text, 3:1 for a mark, a pill or a border. At 16 colours the sheet shows no contrast, because the terminal decides those colours.
| Key | What it does |
|---|---|
| ↑ ↓ | Move between rows |
| Tab, Shift+Tab | Go to the next or the previous tab |
| Enter | Open the colour picker on the row. On Dark theme, switch between dark and light |
| e | Type a value: hex, a slot, a role or a CharmTone name. Tab completes the name |
| x | Give the row back to the base |
| f | Fix the row's contrast: make the colour lighter or darker until it reads on its ground |
| u | Undo the last change |
| Ctrl+S | Save the theme file |
| Space | Hide the sheet to see the whole screen. Press Space again to show it |
| Esc | Close the editor. With changes that are not saved, press Esc two times |
- When the cursor lands on a role, every part of the screen in that role flashes in its inverse colour. A role that may not be on the screen, such as the copy-mode pill, shows a sample under the list.
- At 256 colours, the sheet tells you when two status colours look the same.
- Ctrl+S writes only what differs from the base. A new theme saves as
<id>.jsonin the themes directory. A built-in theme saves as an edited copy under its own id. - If the file changed on disk after the editor read it, Ctrl+S tells you and writes nothing. Press Ctrl+S again to replace the file.
- A client of
tuios sshortuios-webcannot save. Only the sheet shows the change there.
A light and a dark theme
(Added in v0.10.1)
theme_light sets a second theme for a light terminal. theme is then the dark theme:
[appearance]
theme = "catppuccin_mocha"
theme_light = "catppuccin_latte"
- TUIOS asks the terminal for its background when it starts, and uses
theme_lighton a light background. - A terminal that follows the system's light and dark switch, such as Ghostty or kitty, tells TUIOS when the switch happens. TUIOS then changes the theme.
- With
theme_lightset, the theme picker asks what a pick is for. Press d for the dark theme, l for the light theme or b for both. - A
--themeflag wins overtheme_light. - Only the local client follows the switch. A client of
tuios sshortuios-webusestheme.
Match your terminal
(Added in v0.10.1)
If your terminal already has a theme, TUIOS can use it with no theme file:
[appearance]
theme = "none"
- The panes use the terminal's own colours.
- The dialogs, the rail and the dock use greys made from the terminal's background. On a dark background the dialogs sit one step lighter than it. On a light background they sit one small step darker.
- The accents stay the TUIOS accents. To change them, use a theme file with a
chromeobject. tuios theme reloadasks each terminal for its colours again. Run it after a tool changes the terminal's colours.
An empty theme keeps the fixed grey ramp for the dialogs on a dark terminal. A client of tuios ssh or tuios-web keeps the fixed ramp too, because one server serves many terminals.
Importing a theme
tuios import-theme converts a kitty, ghostty, alacritty or wezterm colour scheme into a TUIOS theme. The format is read from the file's content, so the extension does not matter.
tuios import-theme ~/.config/kitty/current-theme.conf --name mine
tuios set-config appearance.theme mine
A scheme that sets only some colours imports those, and the rest fall back to the xterm defaults. Wezterm's TOML schemes are read. Its Lua schemes are not.
Writing a theme
A theme is a JSON file in ~/.config/tuios/themes/ (following $XDG_CONFIG_HOME). The file name without .json, lowercased, is its id unless the file sets id.
{
"id": "my-theme",
"display_name": "My Theme",
"fg": "#e0def4",
"bg": "#191724",
"cursor": "#e0def4",
"black": "#26233a",
"red": "#eb6f92",
"green": "#31748f",
"yellow": "#f6c177",
"blue": "#9ccfd8",
"purple": "#c4a7e7",
"cyan": "#ebbcba",
"white": "#e0def4",
"bright_black": "#6e6a86",
"bright_red": "#eb6f92",
"bright_green": "#31748f",
"bright_yellow": "#f6c177",
"bright_blue": "#9ccfd8",
"bright_purple": "#c4a7e7",
"bright_cyan": "#ebbcba",
"bright_white": "#e0def4"
}
- The colour names are
purpleandbright_purple, notmagenta. - A colour is a hex string or an object:
{"r": 255, "g": 0, "b": 0, "a": 255}. - Every field is optional.
fgdefaults to#e5e5e5,bgto#000000,cursortofg, the eight normal colours to the xterm defaults, and eachbright_*to its normal colour. Set the bright colours yourself, or bright text looks the same as normal text. - The directory is read again when you select a theme or run
list-themes, so a file you just wrote can be selected at once. Subdirectories are not read. - Every client watches the themes and glyphs directories. When you save a file there, the client reads the files again and repaints. An edit to the theme in use shows at once. New output in a pane takes the edited colours. (Added in v0.10.1)
- A file that does not parse is skipped.
tuios list-themesreports it underproblemswith the reason.
Start from another theme
(Added in v0.10.1)
base names a theme to start from. A field that the file leaves out comes from the base:
{
"id": "dracula-ember",
"base": "dracula",
"red": "#ff5555",
"chrome": { "accent": "bright_red" }
}
- The base is a built-in theme or another file in the themes directory. A base can have a base of its own.
darkcomes from the base unless the file sets it.- A slot or role name in
chromeis read after the merge, so"accent": "bright_red"follows abright_redthat the file changes. - A file can use the id of a built-in theme and name that theme as its base. This edits the built-in theme for you only.
- Files that name each other as base do not load.
tuios list-themesshows the loop.
Reload, export and share
(Added in v0.10.1)
tuios theme reload makes every client on this machine read the theme and glyph files again. Use it as a hook when a program writes a theme:
# pywal: write a tuios theme from the wallpaper, then reload
wal -i ~/wall.png -o "tuios theme reload"
For matugen, set post_hook = "tuios theme reload" on the template that writes the theme.
tuios theme export <theme> prints a theme as a theme file. A theme of yours is written with its base and only the colours that differ. --full writes every colour. --format base16 writes a base16 scheme in YAML for other programs.
tuios theme share <theme> prints the same file as one line, for a chat message or a comment:
tuios-theme:v1:eyJpZCI6ImRyYWN1bGEtZW1iZXIiLCJiYXNlIjoiZHJhY3VsYSIs...
The part after tuios-theme:v1: is the file in base64url with no padding.
Chrome colours
The 16 ANSI colours are what programs in your panes paint with. By default TUIOS also takes its own accents from them: the logo and the selected row from bright_blue, the terminal-mode border from bright_green, and so on. A chrome object sets those accents directly, without changing what programs see:
{
"id": "amber",
"chrome": {
"accent": "#ffb454",
"accent_bright": "#ffd580",
"success": "#aad94c",
"warning": "#ffb454",
"error": "#ff3333",
"info": "#59c2ff",
"surface": "#2b2118"
}
}
| Field | What it colours | Taken from when absent |
|---|---|---|
accent |
Logo, selected row, window-mode pill | bright_blue |
accent_bright |
Secondary accent, focused border in window mode | bright_cyan |
success |
Terminal-mode pill, focused border in terminal mode, success messages | bright_green |
warning |
Copy-mode pill, warnings | yellow |
error |
Error messages | red |
info |
Info messages | blue |
surface |
The fill of every dialog: palette, pickers, menus, which-key | A fixed dark grey, or on a light theme a step below its background |
canvas, panel, card |
The darker and lighter steps around surface |
Derived from surface |
Dialogs sit on a fixed grey ramp so they stay readable over any pane content. On a light theme the ramp is built from the theme's background instead, so a dialog is a light panel rather than a dark slab, and the screen behind it fades toward the background rather than toward black. The accent and key colours are darkened at their own hue until they read as text on it (4.5:1), and the status colours until they read as marks (3:1).
surface moves the ramp, and TUIOS picks text colours for it by contrast, so a light surface gets dark text. Text colours cannot be set directly. A field that is not a valid hex colour is ignored on its own.
Roles for one piece of chrome
(Added in v0.10.1)
These chrome fields colour one piece of the screen each. They sit in nested objects. A field that you leave out draws as before:
"chrome": {
"border": { "unfocused": "bright_black", "copy": "yellow", "multifocus": "magenta" },
"rule": "surface",
"status": { "attention": "bright_red", "busy": "accent" },
"dots": { "close": "red", "minimize": "yellow", "zoom": "green" },
"dock": { "ground": "#181825" },
"rail": { "ground": "#181825" }
}
| Field | What it colours |
|---|---|
border.unfocused |
The border of a pane without focus |
border.copy |
The copy-mode pill, and the focused border in copy mode |
border.multifocus |
The border of each pane that takes the keys with multifocus |
rule |
The line under the dock and the lines on the rail |
status.attention |
An agent that waits for input, on the rail and on the focused border |
status.busy |
A working agent on the rail |
dots.close, dots.minimize, dots.zoom |
The window buttons in the dots style |
dock.ground, rail.ground |
The background of the dock and of the rail |
The config keys dock_background, sidebar.background, border_unfocused_color and border_focused_color win over these roles. At 16 colours the roles are not used.
Border colours
appearance.border_focused_color and appearance.border_unfocused_color override the theme's border colours with a hex value. They live in config.toml, not in the theme. Clear one to hand the border back to the theme.
Borders and titles
(Added in v0.10.1)
- Border colour by state. When the theme sets
border.copyorstatus.attention, the focused border takes that colour in copy mode and while the pane's agent waits for you. - Gradient.
appearance.border_focused_gradientdraws the focused border in two or more colours, separated by spaces or commas. Each takes any colour value, so"accent accent_bright"follows the theme.appearance.border_gradient_anglesets the direction in degrees,0to359. The default is45, from the top left corner to the bottom right corner. A state colour draws in place of the gradient. - Title style.
appearance.window_title_styleispill(the default),tab(the fill with no caps) orplain(the name in the border's colour, with no fill). - Title place.
appearance.window_title_alignisauto(the default),left,centerorright.
[appearance]
border_focused_gradient = "#33ccff #00ff99"
border_gradient_angle = 45
window_title_style = "plain"
window_title_align = "center"
Looks
(Added in v0.10.1)
A look is one TOML file that sets how TUIOS looks: the theme, the glyph set, the borders, the gaps, the dock, the rail and the layout. It can also hold a theme and a glyph set. The gallery shares looks, and tuios look apply installs one:
tuios look apply tuios.dev/r/<id> # or an id, an https URL or a file
tuios look show
tuios look remove
tuios look keys # the keys a look can set
- TUIOS shows each change and asks first.
--yesskips the question. - A look cannot set a key that runs a program, names a file or a folder, or changes a host, the daemon, the keybindings or the hooks. TUIOS leaves out such a key and names it.
- TUIOS checks each value as
tuios set-configdoes. A value that is not correct stops the look. - The look goes to
config.d/look.toml.config.tomldoes not change.config.tomlwins overconfig.d, so a key thatconfig.tomlsets hides the same key in the look. - A theme in the look installs as
look-<id>.tuios look removedeletes the look file and the theme and glyph set it installed. - When you change a look key in the settings, TUIOS writes the change to
config.toml, so the next apply or remove keeps it.
Colour depth
The chrome is designed for each colour depth a terminal can have, rather than drawn in truecolor and stepped down. TUIOS reads the depth the way other programs do, from TERM, COLORTERM and NO_COLOR. There is no setting for it.
| Depth | Detected when | What the chrome does |
|---|---|---|
| truecolor | COLORTERM=truecolor or 24bit, or a terminal known to have it (kitty, Ghostty, WezTerm, Alacritty, foot) |
The ramp described above |
| 256 | TERM ends in 256color and COLORTERM is unset: Apple Terminal, mosh, tmux without Tc |
The greys sit on the xterm grey ramp (232 to 255), so no panel or selected row turns navy. Colours step to the nearest palette entry in OKLab, and a saturated colour never lands on a grey |
| 16 | TERM=xterm, TERM=linux, or NO_COLOR set |
No grounds are painted. Panels use your terminal's background and frame themselves with a line, the selected row and title chips are reverse video, and colours are your palette's slots |
At 16 colours a theme's own colours give way to your terminal's palette slots, so set the terminal to the same theme to see them. This holds for the panes too: a pane sends slot 1 for red, and your terminal paints it. At 256 colours a pane's colours and a theme ground step down the same way the chrome does, so a dark ground stays grey and a red stays red. (Added in v0.10.1) The review diff is drawn per depth too: tinted lines in truecolor, fixed palette entries at 256 colours, and coloured line numbers with bold, underlined changed words at 16.
mosh passes 24-bit colour but not COLORTERM, so over mosh TUIOS sees 256 colours. If your terminal has truecolor, export COLORTERM=truecolor on the far machine.
Your terminal's colours
With no theme and no pane background, TUIOS asks each client's terminal for its background, foreground and 16 colours, and answers a program in a pane that asks for them (OSC 10, 11 and 4) with those. The chrome is measured against your terminal's background, so a light terminal gets the light ramp. A local client follows your system's light and dark switch as it happens. A client over SSH or in a browser asks once, when it attaches. A terminal that answers nothing, such as mosh, gets plain black and white; set a theme or appearance.pane_background there.
Theme colours in a pane
(Added in v0.10.0)
With a theme set, a program in a pane gets the theme's background, foreground and 16 colours when it asks with OSC 10, 11 and 4. This also holds in a daemon session. Before v0.10.0, a pane of a daemon session got black, white and the xterm colours. Neovim, Claude Code and other programs use this answer to pick a light or a dark look.
A program that turns on mode 2031 gets a report when the background changes between light and dark: from a theme switch, an Omarchy switch or a scheme switch of your terminal. TUIOS sends no SIGWINCH.
Cursor colour
(Added in v0.9.3)
A program in a pane can set the cursor colour with OSC 12. TUIOS sends the colour of the focused pane to your terminal. When the program resets the colour with OSC 112, your terminal's own cursor colour comes back. It also comes back when the focus moves to a pane that set no colour. This works in a native terminal and in tuios-web.
Glyph sets
A glyph set picks the shapes the chrome is drawn with. Four ship: default, unicode (no Nerd Font glyphs), heavy and ascii.
tuios set-config appearance.glyphs heavy
tuios set-config appearance.border_style glyphs
tuios list-glyphs heavy
With no set configured and no --ascii-only, TUIOS picks one from the environment: a locale that is not UTF-8 (C, POSIX, ISO-8859-1, read from the first of LC_ALL, LC_CTYPE and LANG that is set) gets ASCII, and the Linux console (TERM=linux) gets unicode. tuios list-glyphs with no argument says which set that is and why.
border_style = "glyphs" is what makes the border follow the set. The settings page has a searchable Glyph set picker with a live preview. Writing your own set, the roles it can name and the width rules are covered in Configuration.
Spacing and text
tuios set-config appearance.gap 2 # cells between tiled panes, 0 to 8
tuios set-config appearance.panel_padding 4 # columns inside dialogs, 1 to 6
tuios set-config appearance.clock_format "Mon 3:04PM"
tuios set-config appearance.window_title_format "{index}: {title}"
window_title_formataccepts{title},{index}and{cwd}.dock_workspace_tab_formataccepts{index}and{name}, and{icon}and{zoom}(Added in v0.10.0). See Workspace tab style.clock_formatis a Go time layout, such as15:04orMon 3:04PM. The default is15:04, with no seconds. (Added in v0.10.1) Before, it was15:04:05. A clock without seconds wakes TUIOS once a minute.
Quieting what you are not using
| Key | Default | Meaning |
|---|---|---|
appearance.dim_unfocused |
0 |
Fade panes you are not in, as a percent from 0 to 90. 0 is off |
appearance.dim_foreground (Added in v0.10.0) |
true |
false keeps the text of a pane you are not in at full strength, and dim_unfocused dims only its background |
appearance.zen_mode |
"disabled" |
Hide pane borders: disabled, always, or mouse (hidden while the mouse is still) |
appearance.border_style |
"rounded" |
rounded, normal, thick, double, block, outer-half-block, inner-half-block, ascii, hidden or glyphs |
dim_unfocused dims pane content only. Borders, title bars, the rail and the dock stay as they are. Without a theme it can only dim cells a program coloured itself, because a cell in the terminal's default colour has no colour TUIOS knows. Set a theme first.
Selection and search colours
[appearance.selection] holds the colours a pane marks text with. They are settings rather than part of the theme, because TUIOS chooses them and the program in the pane does not.
| Key | Default | Meaning |
|---|---|---|
bg / fg |
#45475A / empty |
Selected text. An empty fg keeps the text's own colour |
bold |
false |
Also draw selected text bold |
search_bg / search_fg |
#8A6D2F / #F5E7C8 |
Every search match |
match_bg / match_fg |
#E5A93D / #1C1B19 |
The match under the cursor |
cursor_bg / cursor_fg |
#39C5CF / #08222B |
The copy mode cursor |
flash |
true |
Sweep a band of light over text you just copied. The sweep follows appearance.motion: basic and full draw it, none turns it off |
flash_ms |
420 |
How long the sweep takes, 80 to 3000 |
flash_style |
"diagonal" |
diagonal, diagonal-reverse, horizontal or vertical |
flash_color |
empty | The colour of the sweep |
The scrollback browser uses the same search and selection colours.
Spotlight
The spotlight lights one area of the screen and dims the rest. It is meant for recordings and demos. Press B in window management mode, Ctrl+B B in any mode, or run Toggle spotlight from the palette. The key was b in earlier versions.
While the spotlight is on, the dock shows a Spotlight chip. Click it to turn the spotlight off. Esc in window mode also turns it off. In terminal mode, Esc goes to the program in the pane, so use Ctrl+B B. See Spotlight.
| Key | Default | Meaning |
|---|---|---|
spotlight.enabled |
false |
Start with the spotlight on |
spotlight.follow |
"mouse" |
Follow the mouse or the focused pane's cursor |
spotlight.radius |
10 |
Half the beam's height, in rows |
spotlight.dim |
75 |
Percent of its light an unlit cell loses |
spotlight.edge |
"hard" |
hard cuts the beam off, soft fades it |
spotlight.shake |
false |
Shake the mouse left and right to toggle the beam |
The spotlight belongs to one client. Another client attached to the same session sees its own screen unchanged. Over SSH or in the browser, follow = "cursor" and edge = "hard" send far fewer bytes.
Related
- Configuration: Every appearance key, and writing a glyph set
- Session Rail: The sidebar and its colours
- Screenshots: Render a pane in any theme
- CLI Reference: --theme, --list-themes, list-themes, import-theme, theme and look
- Introduction
- Getting Started
- Learn tuios, hands on
- Keybindings
- Hints
- Finding a Pane
- Links
- TUIOS vs Others
Windows and Layout
Sessions and Machines
Agents
- Agents
- Inbox and Review
- Agent Messaging
- Program Status
- Worktrees
- Checkpoints
- Ship
- Push Notifications
- Turn Off Agent Features
Scripting
Recording
Reference