Skip to content

Instantly share code, notes, and snippets.

@ewilderj
Last active February 10, 2026 21:38
Show Gist options
  • Select an option

  • Save ewilderj/6bce17b8f834fc4a371cf16c258e1d9d to your computer and use it in GitHub Desktop.

Select an option

Save ewilderj/6bce17b8f834fc4a371cf16c258e1d9d to your computer and use it in GitHub Desktop.
Auto-tint Ghostty terminal tabs by project directory and SSH host (zsh + Ghostty config)
# Ghostty terminal configuration
theme = dracula
font-family = FiraCode Nerd Font
font-size = 14
# Window chrome
window-padding-x = 4
window-padding-y = 4
window-decoration = auto
# Let our zsh hooks control tab titles (not Ghostty's built-in)
shell-integration-features = no-title
# ghostty-colors.zsh โ€” Auto-tint Ghostty tabs by project or SSH host
#
# Projects under ~/git/ get cool-toned background tints.
# SSH sessions get warm-toned tints. Colors are deterministic:
# the same project/host always gets the same color.
#
# Only activates inside Ghostty.
# Activate in Ghostty (local) or any capable terminal (remote/SSH)
case "$TERM" in
xterm-ghostty|xterm*|screen*|tmux*) ;;
*) [[ -z "$GHOSTTY_RESOURCES_DIR" ]] && return ;;
esac
# ---------------------------------------------------------------------------
# Palette โ€” subtle dark tints that pair well with Dracula
# ---------------------------------------------------------------------------
# Cool tones for local projects
typeset -a _GTC_PROJECT_COLORS=(
"#1e2535" # slate blue
"#1e2d2d" # deep teal
"#261e35" # plum
"#1e3526" # forest
"#2d1e2d" # mauve
"#1e2d35" # steel
"#2d2d1e" # olive
"#1e352d" # sea green
"#2d1e35" # violet
"#1e3535" # cyan
"#241e35" # indigo
"#1e3530" # jade
)
# Warm tones for SSH hosts
typeset -a _GTC_SSH_COLORS=(
"#352222" # brick
"#352d1e" # amber
"#35261e" # burnt orange
"#2d2222" # rosewood
"#352c1e" # golden brown
"#2d1e1e" # dark cherry
"#352d24" # copper
"#351e1e" # deep red
)
_GTC_DEFAULT_BG="#282a36" # Dracula default
# Colored circle emojis โ€” indexed by hash to visually match the tint
typeset -a _GTC_PROJECT_DOTS=( ๐Ÿ”ท ๐Ÿ€ ๐Ÿ”ฎ ๐ŸŒฐ โญ ๐Ÿ’Ž ๐ŸŒฟ ๐ŸŒ• ๐Ÿชป ๐ŸงŠ ๐ŸŽฏ ๐Ÿƒ )
typeset -a _GTC_SSH_DOTS=( ๐Ÿ”ฅ ๐ŸŠ ๐ŸŒ… ๐ŸŒน ๐ŸŒป ๐Ÿ’ ๐Ÿฅง โ™ฆ๏ธ )
# Track current context so precmd can re-assert the title
_GTC_CURRENT_TITLE=""
_GTC_SSH_ACTIVE=""
# ---------------------------------------------------------------------------
# Internals
# ---------------------------------------------------------------------------
_gtc_hash() {
local s="$1" h=0 i
for (( i=0; i<${#s}; i++ )); do
h=$(( (h * 31 + $(printf '%d' "'${s:$i:1}")) % 65536 ))
done
echo $h
}
# Shorten ~/git/foo/bar/baz โ†’ foo/bar/baz ; ~/other โ†’ ~/other
_gtc_short_cwd() {
if [[ "$PWD" == "$HOME/git/"* ]]; then
echo "${PWD#$HOME/git/}"
elif [[ "$PWD" == "$HOME"* ]]; then
echo "~${PWD#$HOME}"
else
echo "$PWD"
fi
}
_gtc_set() {
printf '\033]11;%s\007' "$1"
printf '\033]2;%s\007' "$2"
_GTC_CURRENT_TITLE="$2"
}
# Prefix for tab titles โ€” includes hostname when in an SSH session
if [[ -n "$SSH_CONNECTION" ]]; then
_GTC_HOST_PREFIX="${HOST%%.*}: "
else
_GTC_HOST_PREFIX=""
fi
_gtc_reset() {
local title="${_GTC_HOST_PREFIX}$(_gtc_short_cwd)"
printf '\033]11;%s\007' "$_GTC_DEFAULT_BG"
printf '\033]2;%s\007' "$title"
_GTC_CURRENT_TITLE="$title"
}
# ---------------------------------------------------------------------------
# Project coloring โ€” fires on every cd
# ---------------------------------------------------------------------------
_gtc_chpwd() {
[[ -n "$_GTC_SSH_ACTIVE" ]] && return
if [[ "$PWD" == "$HOME/git/"* ]]; then
local project="${PWD#$HOME/git/}"
project="${project%%/*}"
local subpath="$(_gtc_short_cwd)"
local idx=$(( $(_gtc_hash "$project") % ${#_GTC_PROJECT_COLORS[@]} + 1 ))
local dot="${_GTC_PROJECT_DOTS[$idx]}"
_gtc_set "${_GTC_PROJECT_COLORS[$idx]}" "$dot ${_GTC_HOST_PREFIX}$subpath"
else
_gtc_reset
fi
}
# ---------------------------------------------------------------------------
# precmd โ€” re-assert title before every prompt so running programs
# (gh copilot, etc.) can't permanently overwrite it
# ---------------------------------------------------------------------------
_gtc_precmd() {
[[ -n "$_GTC_CURRENT_TITLE" ]] && printf '\033]2;%s\007' "$_GTC_CURRENT_TITLE"
}
# ---------------------------------------------------------------------------
# SSH coloring โ€” wraps ssh to tint before connect, restore after
# ---------------------------------------------------------------------------
ssh() {
local host="" skip=false arg
for arg in "$@"; do
if $skip; then skip=false; continue; fi
case "$arg" in
-[bcDEeFIiJLlmOopQRSWw]) skip=true ;;
-*) ;;
*@*) host="${arg#*@}"; break ;;
*) [[ -z "$host" ]] && host="$arg"; break ;;
esac
done
if [[ -n "$host" ]]; then
local short="${host%%.*}"
local idx=$(( $(_gtc_hash "$short") % ${#_GTC_SSH_COLORS[@]} + 1 ))
local dot="${_GTC_SSH_DOTS[$idx]}"
_GTC_SSH_ACTIVE="$short"
_gtc_set "${_GTC_SSH_COLORS[$idx]}" "$dot $short"
fi
command ssh "$@"
local ret=$?
_GTC_SSH_ACTIVE=""
_gtc_chpwd
return $ret
}
# ---------------------------------------------------------------------------
# Hook registration + initial apply
# ---------------------------------------------------------------------------
autoload -Uz add-zsh-hook
add-zsh-hook chpwd _gtc_chpwd
add-zsh-hook precmd _gtc_precmd
_gtc_chpwd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment