Create small CLIs and scripts that use Charmbracelet Gum TUI components (choose, input, confirm, spin, style) with solid shell practices and non-interactive fallbacks.
This skill guides building small, pragmatic CLIs and scripts using the gum command (https://github.com/charmbracelet/gum) for TUI prompts and polished terminal output.
Use this skill when the user wants:
read/select.Do not force TUI if:
--json / plain output).bash with set -euo pipefail.--help--version--no-interactiveNO_COLOR=1 (and/or GUM_NO_COLOR=1 if the project uses it).gum is missing, plus install hints.gum choose, gum filtergum input, gum write (multiline)gum confirmgum spin, gum loggum style, gum table, gum pager, gum format, gum join130.Use this as the default structure unless the repo already has conventions:
#!/usr/bin/env bash
set -euo pipefail
VERSION="0.1.0"
usage() {
cat <<'EOF'
Usage:
mytool [options]
Options:
--name <name> Name to use
--no-interactive Never prompt; fail if required inputs are missing
-h, --help Show help
-v, --version Show version
EOF
}
die() { printf "error: %s\n" "$*" >&2; exit 1; }
have_tty() { [[ -t 0 && -t 1 ]]; }
need_cmd() {
command -v "$1" >/dev/null 2>&1 || die "missing dependency: $1"
}
NO_INTERACTIVE=0
NAME="${NAME:-}"
while [[ $# -gt 0 ]]; do
case "$1" in
--name) NAME="${2:-}"; shift 2 ;;
--no-interactive) NO_INTERACTIVE=1; shift ;;
-h|--help) usage; exit 0 ;;
-v|--version) printf "%s\n" "$VERSION"; exit 0 ;;
*) die "unknown argument: $1 (use --help)" ;;
esac
done
if [[ "$NO_INTERACTIVE" -eq 0 ]] && have_tty; then
need_cmd gum
fi
if [[ -z "$NAME" ]]; then
if [[ "$NO_INTERACTIVE" -eq 1 || ! have_tty ]]; then
die "missing --name (or NAME env) in non-interactive mode"
fi
NAME="$(gum input --prompt "Name: " --placeholder "Jane Doe")" || exit 130
fi
if [[ "$NO_INTERACTIVE" -eq 0 ]] && have_tty; then
gum confirm "Proceed with name '$NAME'?" || exit 130
fi
run() {
printf "Hello, %s\n" "$NAME"
}
if [[ "$NO_INTERACTIVE" -eq 0 ]] && have_tty; then
gum spin --title "Working..." -- run
else
run
fi
gum choose for small lists; gum filter for long lists.gum spin -- <cmd>.gum style to render a final "review" screen before executing destructive actions.0 success, 1 errors, 2 usage, 130 user cancel.gum confirm).--dry-run when actions change state.gum required for interactive mode.gum input --prompt "X: " --value "$X"gum choose "a" "b" "c"gum filter --placeholder "Search..." < <(printf "%s\n" "${items[@]}")gum confirm "Are you sure?"gum spin --title "Doing thing..." -- <cmd>gum style --border rounded --padding "1 2" "Title" "Body"gum table < file.tsvgum pager < file.txt