ANSI escape codes in Bash / shell
Bash has two reliable ways to emit escape bytes: printf with \033 / \x1b (POSIX-portable), and tput (terminfo-driven, the safest because it adapts to $TERM). echo -e works in bash but breaks in dash / sh; avoid it in portable scripts. The literal $'\e[...' ANSI-C quoting form is bash/zsh-only but very readable.
Recommended libraries
- tput
ncurses-bundled binary:
tput setaf 1emits red foreground escape for the current$TERM. Use this in scripts that need to work on dumb / 16-colour / 256-colour terminals alike. - gum (charmbracelet)
Pre-styled shell primitives —
gum style,gum spin,gum choose,gum confirm. Wraps lipgloss / bubbletea for shell scripts. - dialog / whiptail
Classic full-screen menus / inputs / progress over curses.
whiptailis the lighter, BSD-licensed clone shipped with Debian. - ncurses
C library, but bash scripts can call helper binaries like
clear,reset,tput,infocmpthat ship with it.
Idiomatic patterns
printf '\033[1;31m%s\033[0m %s\n' 'error:' 'permission denied'RED=$(tput setaf 1)
BOLD=$(tput bold)
RESET=$(tput sgr0)
printf '%s%serror:%s permission denied\n' "$BOLD" "$RED" "$RESET"red=$'\e[31m'
reset=$'\e[0m'
echo "${red}error${reset}: permission denied"if [ -t 1 ] && [ -z "${NO_COLOR:-}" ]; then
RED=$'\e[31m'; RESET=$'\e[0m'
else
RED=""; RESET=""
fi
printf '%serror:%s permission denied\n' "$RED" "$RESET"