Gum - Terminal UI Toolkit
Gum provides highly configurable, ready-to-use utilities for building terminal UIs and interactive scripts.
Gum is a tool for building glamorous shell scripts with pre-built interactive components. Created by Charm, it requires no Go knowledge - just shell scripting.
Installation
brew install gum
Other options: pacman -S gum (Arch), winget install charmbracelet.gum (Windows), go install github.com/charmbracelet/gum@latest.
Styled Output
gum style
Apply colors, borders, padding, and alignment to text:
gum style --foreground 212 "Pikachu"
gum style --foreground 212 --bold "LEGENDARY"
gum style --border double --padding "1 2" "Pokemon Info"
Styled Headers
gum style \
--foreground 212 --border-foreground 212 --border double \
--align center --width 50 --margin "1 2" --padding "1 2" \
"Pokedex v1.0"
Color Functions
# Success/Error/Warning messages
gum style --foreground 42 "Caught Pikachu!" # Green
gum style --foreground 196 "Pokemon fled!" >&2 # Red
gum style --foreground 214 "Low HP warning" # Yellow
gum style --foreground 99 "Info message" # Purple
User Input
gum input
Single-line text input:
NAME=$(gum input --placeholder "Pokemon name")
echo "You entered: $NAME"
With validation and defaults:
gum input --placeholder "Enter HP" --value "100"
gum input --password --placeholder "API Key"
gum input --char-limit 20 --width 30
gum write
Multi-line text input (Ctrl+D to finish):
DESCRIPTION=$(gum write --placeholder "Pokemon description...")
Selection
gum choose
Select from a list of options:
TYPE=$(gum choose "Fire" "Water" "Grass" "Electric")
echo "Selected: $TYPE"
Multiple selection:
TYPES=$(gum choose --no-limit "Fire" "Water" "Grass" "Electric" "Flying")
With limit:
gum choose --limit 2 "Bulbasaur" "Charmander" "Squirtle"
From file or pipe:
cat pokemon.txt | gum choose
ls *.yaml | gum choose
gum filter
Fuzzy-searchable selection:
POKEMON=$(cat pokedex.txt | gum filter --placeholder "Search Pokemon...")
With options:
gum filter --limit 5 --height 10 < pokemon-list.txt
Confirmation
gum confirm
Yes/No prompts (exit code 0 = yes, 1 = no):
gum confirm "Delete Pikachu?" && rm pikachu.yaml || echo "Cancelled"
With default:
gum confirm --default=false "Are you sure?"
Practical pattern:
if gum confirm "Evolve Pikachu to Raichu?"; then
echo "Evolving..."
else
echo "Cancelled"
fi
Progress & Spinners
gum spin
Show a spinner during long operations:
gum spin --spinner dot --title "Catching Pokemon..." -- sleep 3
With output:
gum spin --show-output --title "Searching..." -- grep -r "Pikachu" .
Available spinners: line, dot, minidot, jump, pulse, points, globe, moon, monkey, meter, hamburger.
Formatting
gum format
Render markdown, code, and emojis:
echo "# Pikachu" | gum format
echo "**Electric** type" | gum format
Code highlighting:
cat script.sh | gum format -t code
Emoji support:
echo ':zap: Pikachu used Thunder! :boom:' | gum format -t emoji
Practical Examples
Interactive Pokemon Selector
#!/bin/bash
POKEMON=$(ls pokemon/*.yaml | xargs -n1 basename -s .yaml | gum filter)
if [ -n "$POKEMON" ]; then
cat "pokemon/$POKEMON.yaml"
fi
Pokemon Creator
#!/bin/bash
NAME=$(gum input --placeholder "Pokemon name")
TYPE=$(gum choose "Fire" "Water" "Grass" "Electric" "Psychic")
HP=$(gum input --placeholder "HP" --value "100")
LEGENDARY=$(gum confirm "Is it legendary?" && echo "true" || echo "false")
cat > "pokemon/$NAME.yaml" << EOF
name: $NAME
type: $TYPE
stats:
hp: $HP
legendary: $LEGENDARY
EOF
gum style --foreground 42 "Created $NAME!"
Batch Delete with Confirmation
#!/bin/bash
FILES=$(ls *.yaml | gum choose --no-limit)
if [ -n "$FILES" ]; then
echo "$FILES" | while read f; do
gum confirm "Delete $f?" && rm "$f"
done
fi
Styled Menu
#!/bin/bash
gum style --border double --padding "1 2" "Pokedex Menu"
ACTION=$(gum choose "List Pokemon" "Add Pokemon" "Search" "Exit")
case "$ACTION" in
"List Pokemon") ls pokemon/ ;;
"Add Pokemon") ./add-pokemon.sh ;;
"Search") gum filter < pokemon-names.txt ;;
"Exit") exit 0 ;;
esac
Handling Piped Input
When stdin is already in use, redirect gum from /dev/tty:
cat pokemon.txt | while read pokemon; do
gum confirm "Process $pokemon?" </dev/tty && echo "Processing $pokemon"
done
Customization
Set colours via flags or environment variables:
# Via flags
gum input --cursor.foreground "#FF0" --prompt.foreground "#0FF"
# Via environment
export GUM_INPUT_CURSOR_FOREGROUND="#FF0"
gum input
Tips
- Use
</dev/ttywhen piping data and need interactive input - Chain commands:
TYPE=$(gum choose ...) && gum confirm ... - Use
--no-limitfor multi-select with gum choose - Style error messages with
>&2to send to stderr - Combine with Yq and Jq for data manipulation
Resources
- GitHub: https://github.com/charmbracelet/gum
- Charm: https://charm.sh