As a developer constantly juggling between production, staging, and development servers through SSH, I've often found myself running dangerous commands on the wrong server. The visual monotony of terminal windows makes it dangerously easy to confuse environments. What we need is automatic terminal theming based on SSH destinations.
We'll implement this through a combination of SSH configuration tricks and shell scripting. The core components are:
1. ~/.ssh/config host definitions
2. Terminal escape sequences for color changes
3. Bash PROMPT_COMMAND or ZSH hooks
4. Local configuration files for color schemes
First, let's set up our SSH config with identifiable host aliases:
# ~/.ssh/config
Host prod-web
HostName 192.168.1.100
User admin
IdentityFile ~/.ssh/prod_key
SetEnv TERM_COLOR_SCHEME=red
Host staging-db
HostName staging.example.com
User dbadmin
SetEnv TERM_COLOR_SCHEME=blue
We'll use ANSI escape codes to modify terminal colors. Create a script called ~/.terminal_colors
:
#!/bin/bash
case $TERM_COLOR_SCHEME in
red)
printf "\033]11;#330000\033\\" # background
printf "\033]10;#ffdddd\033\\" # foreground
;;
blue)
printf "\033]11;#000033\033\\"
printf "\033]10;#ddddff\033\\"
;;
*)
printf "\033]11;#000000\033\\" # default
printf "\033]10;#ffffff\033\\"
;;
esac
For bash users, add this to your ~/.bashrc
:
function set_term_color() {
if [ -n "$TERM_COLOR_SCHEME" ]; then
source ~/.terminal_colors
fi
}
PROMPT_COMMAND="set_term_color;$PROMPT_COMMAND"
For zsh users, add to ~/.zshrc
:
autoload -U add-zsh-hook
add-zsh-hook precmd set_term_color
For more complex setups, create JSON configuration files:
// ~/.terminal_themes/prod-web.json
{
"background": "#330000",
"foreground": "#ffdddd",
"cursor": "#ff0000",
"highlight": "#550000"
}
Then modify your script to parse these:
#!/bin/bash
if [ -n "$TERM_COLOR_SCHEME" ]; then
CONFIG_FILE="$HOME/.terminal_themes/${TERM_COLOR_SCHEME}.json"
if [ -f "$CONFIG_FILE" ]; then
bg=$(jq -r '.background' "$CONFIG_FILE")
fg=$(jq -r '.foreground' "$CONFIG_FILE")
printf "\033]11;${bg}\033\\"
printf "\033]10;${fg}\033\\"
fi
fi
For Windows users with WSL or Git Bash, use these escape sequences instead:
printf "\e]4;0;$bg_color\a" # background
printf "\e]4;1;$fg_color\a" # foreground
Be cautious when:
- Allowing servers to set TERM_COLOR_SCHEME via AcceptEnv
- Using untrusted JSON parsers for theme files
- Making color schemes too distinctive (could expose sensitive info)
If colors aren't changing:
1. Verify $TERM_COLOR_SCHEME is set: echo $TERM_COLOR_SCHEME
2. Check escape sequence support: echo -e "\033]11;#ff0000\033\\"
3. Confirm PROMPT_COMMAND is working: echo $PROMPT_COMMAND
4. Test script directly: source ~/.terminal_colors
For tmux users, you can theme entire sessions:
# ~/.tmux.conf
bind-key -n M-c run-shell "tmux set-window-option window-status-current-style bg=$TMUX_COLOR"
Then set TMUX_COLOR in your SSH config like we did with TERM_COLOR_SCHEME.
As a developer constantly hopping between servers, I've found myself in situations where I accidentally typed production commands in a staging environment - all because my terminal windows looked identical. This isn't just about aesthetics; it's about preventing costly mistakes.
The most elegant solution leverages your ~/.ssh/config
file combined with terminal emulator features. Here's how to implement it in iTerm2 (macOS) or compatible terminals:
# ~/.ssh/config example
Host production-*
HostName %h.example.com
User deploy
RemoteCommand echo -e "\033]50;SetProfile=Production\a"
RequestTTY force
Host staging-*
HostName %h.staging.example.com
User developer
RemoteCommand echo -e "\033]50;SetProfile=Staging\a"
RequestTTY force
For iTerm2 Users
Create color profiles named "Production" (red background) and "Staging" (yellow background) in iTerm preferences. The escape sequence \033]50;SetProfile=ProfileName\a
triggers the switch.
Gnome Terminal Solution
# In your ~/.bashrc or server-side profile
if [ -n "$SSH_CONNECTION" ]; then
case "$HOSTNAME" in
production*) printf "\e]11;#400000\a" ;;
staging*) printf "\e]10;#000000\a\e]11;#FFFFCC\a" ;;
esac
fi
For more control, create a wrapper script:
#!/bin/bash
# ssh-theme.sh
case "$1" in
prod*)
telliterm "Production"
ssh -t user@production-server "$2"
telliterm "Default"
;;
stage*)
telliterm "Staging"
ssh -t user@staging-server "$2"
telliterm "Default"
;;
esac
function telliterm() {
echo -ne "\033]50;SetProfile=$1\a"
}
If you use tmux across sessions, set different status bar colors:
# In ~/.tmux.conf
bind-key P select-pane -P 'bg=colour52,fg=white'
bind-key S select-pane -P 'bg=colour58,fg=white'
Remember that any server-side color changes could potentially be exploited (like hiding malicious commands in white text). Client-side solutions are generally safer.