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 1` emits 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. `whiptail` is the lighter, BSD-licensed clone shipped with Debian.
- ncurses
C library, but bash scripts can call helper binaries like `clear`, `reset`, `tput`, `infocmp` that 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"