Terminal Color Codes
October 08, 2025
So there I was, making a cool new feature: I wanted to show “dead” connections in fowl for a few seconds before they disappear. I thought it would be fun to “fade out” the text in the TUI (terminal UI).
As an aficionado of dark-mode (usually Solarized Dark) I basically just faded towards “black”.
But this isn’t “correct”, even for dark mode, and is decidedly the wrong effect in a light-mode terminal.
So Just Set The Background
Yes, a cheap trick would be to simply set the background color to something I personally like, and fade towards that. Since we can set terminal colours, how hard can it be to get the terminal color?
Oh My
There’s like “a lot” going on. As usual, jvns.ca has the goods and a way deeper dive than I’m doing here.
Let’s just start at the end, and look at the test code I cribbed together:
import tty
import termios
import os
import sys
old = termios.tcgetattr(1)
tty.setraw(1)
os.write(0, b"\x1b]11;?\x1b\\")
color = os.read(2, 40)
termios.tcsetattr(1, termios.TCSAFLUSH, old)
print(color)
Okay, so looking at this in order, we remember the old terminal attributes and stuff and set “raw” mode. See jvns stuff if you don’t know what “raw mode” means – but that’s the mode we need to do any ANSI / control-sequence stuff at all.
Note: in newest Python tty.setraw()
returns the old mode.
Once that is done, we write “the goods”: b"\x1b]11;?\x1b\\"
Let’s break that down:
b"\x1b"
is “ESC” in documentation on control sequences.b"]"
means Operating System Command (OSC)b"11"
is the “Ps” value, in this case meaning “VT100 text background color”b";"
is an argument separatorb"?"
is the “Pt” value, where?
means “don’t set it, just tell me the value”b"\x1b\\"
is String Terminator / “ST” (also can useb"\x07"
or BEL for some reason)
Okay so we’ve just asked a question in “xterm” language – and compatible terminals. (I tried on gnome-terminal and Kitty and they worked – but interestingly NOT inside tmux, for reasons I don’t care to explore currently).
The os.read()
call reads back the answer, which is the same as the escape sequence you’d use to set the background color. In my case, on a Solarized Light terminal, I see: b"\x1b]11;rgb:fdfd/f6f6/e3e3\x1b\\"
.
Translating similar to above, we read that as: “ESC-OSC”, “background”, “rgb:fdfd/f6f6/e3e3” and “close”. Indeed, the XResources value for base03 in Solarized Light is #fdf6e3
(does anyone know why each value is doubled like that?).
Great!
Cool! Now we can get the actual (default) background colour of our terminal (maybe) and then use that to “fade” foreground text toward it (if our terminal supports 256 or “lots” of colours, which most do these days).
Follow-up on Mastodon if you have thoughts!
Oh, SnoopJ pointed me to termbg which uses just 63 Rust crates to accomplish the same thing (but cross-platform).