/ 6 min read
Fixing Codex CLI colors over SSH in Ghostty
Codex CLI looked flat over SSH from Ghostty because the Ubuntu devbox did not know xterm-ghostty, and the shell environment was disabling color. This is the setup I use and the fix that made the Codex textbox background render correctly again.
I run most of my coding setup on machines that are not in my backpack.
My daily machine is a MacBook. I travel with it, work from random places, and spend a lot of time unplugged from power. My IP address changes all the time. Some days I am on hotel Wi-Fi, some days I am tethered to my phone, and some days I want to check something from the phone itself without opening the laptop at all.
So I keep the real work somewhere else.
At a fixed place I have a small Ubuntu devbox. I also use a VPS for the same kind of work. Both sit on Tailscale. My laptop and phone connect into that private network, and I SSH into whichever box has the context I need. Codex runs there, not on the device in my hands.
This setup is boring in the best way. My laptop stays cool. Battery lasts longer. My phone can become a thin client when I need it. Long-running sessions do not die because I closed the lid or changed networks. I can leave a Codex session open on the devbox, come back later from a different device, and keep going.
The annoying part was cosmetic, but it was annoying enough to fix.
Codex CLI did not look right over SSH from Ghostty. The app worked, but the styling was off. The most obvious missing piece was the grey background behind the input textbox. Locally, Codex has a nice TUI with shaded areas and clear visual separation. Over SSH, my prompt area looked flat. It was usable, but the whole interface felt half-rendered.
I first blamed Tailscale SSH because that is how I usually connect. Then I tried regular SSH and saw the same thing. That ruled out Tailscale. The problem sat somewhere between Ghostty, SSH, Ubuntu, and Codex's terminal rendering.
The setup
The client side:
- macOS
- Ghostty as the terminal
- SSH or Tailscale SSH into remote machines
The server side:
- Ubuntu devbox at a fixed place
- Ubuntu VPS with the same issue
- Codex CLI installed on the remote machine
- Bash as the interactive shell
Ghostty sets TERM=xterm-ghostty. That is the right value. The catch is that the remote machine also needs to know what xterm-ghostty means.
Terminal apps read TERM as more than a label. They ask the system's terminfo database what the terminal can do. Colors, background color erase, cursor movement, alternate screen behavior, keyboard handling, mouse support: a lot of that comes from terminfo.
On my Ubuntu box, this failed:
infocmp xterm-ghosttyThe output was:
infocmp: couldn't open terminfo file /usr/share/terminfo/x/xterm-ghosttyThat was the first real clue. Ghostty was telling the remote machine "I am xterm-ghostty", and Ubuntu was replying "never heard of it."
The first fix: install Ghostty terminfo
Ghostty documents this exact SSH problem. Newer terminal emulators often ship their own TERM value before every remote system has that entry in its terminfo database.
The usual fix is to copy the Ghostty terminfo entry to the remote host:
infocmp -x xterm-ghostty | ssh user@host -- tic -x -That works when your local machine has the terminfo source available through infocmp. In my case, I was already inside the Ubuntu box while debugging, so I installed the compiled entry on the remote machine instead.
Ubuntu 24.04 did not have xterm-ghostty, even after installing the extended ncurses package:
sudo apt-get install -y ncurses-term
infocmp xterm-ghosttyStill missing.
I pulled a packaged ghostty-terminfo entry and installed the compiled file into my user terminfo directory:
mkdir -p ~/.terminfo/x
install -m 0644 xterm-ghostty ~/.terminfo/x/xterm-ghosttyAfter that:
infocmp xterm-ghostty >/dev/null && echo terminfo-ok
tput colorsReturned:
terminfo-ok
256That fixed the remote terminal capability lookup. But Codex still did not look quite right.
The second fix: clean up the SSH environment
The next clue came from printing the color-related environment:
echo "$TERM"
echo "$COLORTERM"
echo "$TERM_PROGRAM"
echo "$NO_COLOR"I had:
xterm-ghostty
1TERM was correct. COLORTERM and TERM_PROGRAM were empty. Worse, NO_COLOR=1 was set.
NO_COLOR is not a vague preference. It is a convention that tells command-line programs to disable ANSI color output. If a TUI respects it, backgrounds and styling can disappear. That matched what I saw in Codex.
For Ghostty SSH sessions, I wanted three things:
- keep TERM=xterm-ghostty
- set COLORTERM=truecolor
- unset NO_COLOR
I added this near the top of ~/.bashrc, after the interactive-shell check:
# Ghostty over SSH: make color capability explicit for TUI apps such as Codex.
if [ "${TERM:-}" = "xterm-ghostty" ]; then
export COLORTERM="${COLORTERM:-truecolor}"
export TERM_PROGRAM="${TERM_PROGRAM:-ghostty}"
unset NO_COLOR
fiThen I opened a fresh SSH session and checked:
echo "$TERM $COLORTERM $TERM_PROGRAM ${NO_COLOR-unset}"
infocmp xterm-ghostty >/dev/null && echo terminfo-ok
tput colorsExpected output:
xterm-ghostty truecolor ghostty unset
terminfo-ok
256After that, Codex rendered correctly. The grey textbox background came back.
The short version
If Codex CLI looks flat or colorless over SSH from Ghostty, check these on the remote machine:
echo "$TERM"
echo "$COLORTERM"
echo "$TERM_PROGRAM"
echo "$NO_COLOR"
infocmp xterm-ghostty >/dev/null && echo terminfo-ok
tput colorsYou want:
TERM=xterm-ghostty
COLORTERM=truecolor
TERM_PROGRAM=ghostty
NO_COLOR unset
tput colors -> 256Install terminfo if infocmp fails:
infocmp -x xterm-ghostty | ssh user@host -- tic -x -If you cannot do that, use the downgrade path:
TERM=xterm-256color codexThat avoids the unknown terminal type, but you lose the Ghostty-specific entry. I would rather fix terminfo once and keep the terminal honest.
Why this matters to me
I know this sounds like a small thing. The app worked before. I could still type prompts, read diffs, and run commands.
But I spend hours in Codex now. The TUI is part of the workspace. When the input area loses its background, the interface becomes harder to scan. It feels like the terminal is lying about the state of the app. Tiny visual bugs become friction when you stare at them all day.
The whole point of my devbox setup is that my laptop and phone stay light. I want my devices to act like windows into the same remote workspace, not like machines carrying the whole environment around. SSH should feel local enough that I forget about it.
For Codex in Ghostty, that meant teaching Ubuntu what Ghostty is and making sure the shell was not telling Codex to turn colors off.
Once both were fixed, the setup felt like it should have from the start.
Links
- Ghostty terminfo docs: https://ghostty.org/docs/help/terminfo
- Ghostty shell integration docs: https://ghostty.org/docs/features/shell-integration
- NO_COLOR convention: https://no-color.org/