Ghostty Terminfo Installation
Overview
Ghostty uses xterm-ghostty as its $TERM value. Remote hosts that lack this terminfo entry will show broken terminal behavior. The fix is to transfer the terminfo from the local machine to the remote host.
tic run as a normal user writes to ~/.terminfo, which ncurses searches before the system directory. No sudo, and nothing to add to shell rc files.
When to Use
- Remote SSH sessions show "unknown terminal type xterm-ghostty"
- Missing colors, broken backspace/arrow keys, or garbled output over SSH
- Setting up a new remote host for use with Ghostty
- Writing SSH scripts that should handle Ghostty terminfo automatically
- The entry appears to be installed on the host, but SSH sessions are still broken
Quick Reference
| Task | Command |
|---|---|
| Check if remote has terminfo | ssh HOST 'infocmp xterm-ghostty >/dev/null 2>&1' |
| Install terminfo on remote | infocmp -x xterm-ghostty | ssh HOST tic -x - |
| One-liner check + install | ssh HOST 'infocmp xterm-ghostty >/dev/null 2>&1' || infocmp -x xterm-ghostty | ssh HOST tic -x - |
| Verify after install | ssh HOST 'infocmp -x xterm-ghostty 2>/dev/null | grep -q Smulx && echo OK' |
| Show the terminfo search path | ssh HOST 'infocmp -D' |
Implementation
Local Install
If you're already on the machine, just pipe it directly to tic:
infocmp -x xterm-ghostty | tic -x -
One-Time Install
infocmp -x xterm-ghostty | ssh user@host tic -x -
This exports the local terminfo and compiles it on the remote host. Only needs to run once per remote machine.
It lands in the remote user's ~/.terminfo. Because the entry declares aliases (xterm-ghostty|ghostty|Ghostty), tic writes two files — the name and the alias:
~/.terminfo/78/xterm-ghostty
~/.terminfo/67/ghostty
Re-running the install is safe and idempotent; see Common Mistakes for the warnings it prints.
Conditional Install in SSH Scripts
if [ "$TERM" = "xterm-ghostty" ]; then
ssh "$HOST" 'infocmp xterm-ghostty >/dev/null 2>&1' || \
infocmp -x xterm-ghostty | ssh "$HOST" tic -x -
fi
Only runs when connecting from Ghostty, skips if already installed.
Verifying Properly
Plain infocmp xterm-ghostty succeeding only proves an entry exists — not that the extended capabilities survived, which is the entire point of the -x flags. Check for an extended capability instead:
ssh HOST 'infocmp -x xterm-ghostty 2>/dev/null | grep -q Smulx && echo OK'
Smulx, setrgbf, setrgbb, Sync and fullkbd are the extended caps Ghostty ships. To prove the entry is genuinely identical to the local one, compare the compiled bytes rather than infocmp text — the text rendering varies with ncurses version (hex vs decimal colors#256, \n vs ^J, escaped vs unescaped colons), so textual diffs manufacture false positives:
md5 -q ~/.terminfo/78/xterm-ghostty # remote
md5 -q /Applications/Ghostty.app/Contents/Resources/terminfo/78/xterm-ghostty # local
Troubleshooting: The Entry Exists but SSH Is Still Broken
A compiled entry can be present on the host, byte-identical to the local one, and still be invisible to the terminal. Presence and resolvability are separate conditions. ncurses only searches ~/.terminfo and the compiled-in system directory:
$ ssh HOST 'infocmp -D'
/Users/someone/.terminfo
/usr/share/terminfo
An entry anywhere else — most often /usr/local/share/terminfo — resolves only if TERMINFO_DIRS points at it, and that is exported per-shell. So the same host can pass a check under one shell and fail under another:
$ ssh HOST 'zsh -lc "echo TERMINFO_DIRS=\$TERMINFO_DIRS"' # zsh ignores /etc/profile
TERMINFO_DIRS=
$ ssh HOST 'bash -lc "echo TERMINFO_DIRS=\$TERMINFO_DIRS"' # /etc/profile exports it
TERMINFO_DIRS=/usr/local/share/terminfo:
When zsh is the login shell, that install is broken in practice while a bash -l spot check says it is fine.
Find every copy on the host, then compare against the search path above:
ssh HOST 'for d in ~/.terminfo /usr/local/share/terminfo /etc/terminfo \
/usr/share/terminfo /lib/terminfo; do
find "$d" -name "*ghostty*" 2>/dev/null
done'
Anything outside the infocmp -D directories does not exist as far as the terminal is concerned. Do a normal ~/.terminfo install; the stray copy is then inert and can be removed.
Common Mistakes
- Trusting
lsor a checksum over the search path - finding the compiled file on the host proves nothing about whether ncurses can reach it.infocmp -Dis the check that settles it. - Reading
tic's warnings as failure -ticprintsolder tic versions may treat the description field as an aliason a first install, and additionallyalias ghostty multiply defined.when re-run on a host that already has the entry. Both exit 0 and leave a correct entry; the read-back verify is the real verdict. - Reaching for sudo or a system-wide install - on macOS
/usr/share/terminfois on the sealed read-only system volume, sotic -othere fails even as root with SIP disabled.~/.terminfois the supported target, not a fallback. - Running from non-Ghostty terminal -
infocmp xterm-ghosttyfails if the local machine doesn't have the terminfo. Run from Ghostty or a machine with Ghostty installed. - Forgetting
-xflag - Bothinfocmp -xandtic -xneed the extended flag to preserve Ghostty's extended capabilities. - Workaround instead of fix - Setting
TERM=xterm-256colorbefore SSH works but loses Ghostty-specific features. Install the terminfo instead. - Assuming
ticis missing when a piped install fails - on some hosts the non-interactive SSH shell has a trimmedPATHwithout the ncurses tools. Confirm withssh HOST 'command -v tic'before working around it; if it really is absent, prefix the remote command withPATH=/usr/bin:/bin.