Source-verified skills for the Charm terminal stack: Bubble Tea v2, Bubbles v2, Lip Gloss v2, Huh v2, Log v2, Glamour v2, plus the gum and vhs CLIs.
99
98%
Does it follow best practices?
Impact
100%
1.02xAverage score across 9 eval scenarios
Passed
No findings from the security scan
Add prompts, pickers, spinners, tables, and styled output to Bash scripts with the gum CLI, with exact flags, keys, and exit codes so scripts handle cancellation correctly.
Written from gum 2.0.2 (its source, gum --help, and each subcommand's help),
the baseline for this skill; run gum --version first (2.x prints
gum version 2.0.2) and confirm a flag with gum <cmd> --help on the
installed version before relying on it.
If the request names a subcommand, go straight to it. Full flags and keys for every subcommand are in references/commands.md.
gum --version, or guard the script with
gum version-check '>=2.0.0' || exit 1, which exits 1 outside the range.choose for a short list, filter past a couple dozen
items, confirm for yes/no, input or write for text, file for a
path, spin around a slow command, style, join, format, table,
pager, or log for output.$(...) and chain || exit 1 so an abort stops
the script; then check for an empty result where the command allows one.bash -n script.sh to catch syntax errors before running it.$(...)
and the UI still shows.table (in filter, the first Esc only leaves the
search box). The exit status is the reliable signal: some commands can
still print a preselected value on abort, so test $? (or chain
|| exit 1) before using the captured variable. gum table is the
exception: Esc or q exits 0 with an empty line, so check the captured row
as well.GUM_CHOOSE_CURSOR and
GUM_INPUT_PLACEHOLDER; check the subcommand help for the exact names.
Selection flags such as choose --limit and --no-limit have no env
binding. gum style uses bare names (FOREGROUND, BORDER, PADDING).--<part>.foreground, --<part>.background,
and often --padding "0 1". Colors are ANSI indexes or hex.style, join, format, and table --print write through a color
profile writer: when stdout is not a terminal (a pipe, a file, or $(...))
the ANSI styling is stripped and the borders and layout stay.
CLICOLOR_FORCE=1 keeps the colors and NO_COLOR=1 removes them.--timeout 30s ends an interactive command after the duration. confirm
then returns its default; the other prompts print "timed out" and exit 124.--output-delimiter.# pick one, or several (x or tab toggles, a selects all)
format=$(gum choose --header "Format" JSON YAML TOML) || exit 1
tasks=$(printf '%s\n' "List files" "Show size" | \
gum choose --no-limit --selected='*' --ordered --header "Tasks") || exit 1
[[ -n $tasks ]] || exit 0 # --no-limit allows confirming an empty selection
# fuzzy search over a long list
file=$(find . -type f -name '*.md' | gum filter --placeholder "Which Markdown file?") || exit 1
# text
name=$(gum input --placeholder "project name" --header "Name") || exit 1
msg=$(gum write --header "Commit message" --placeholder "what changed?" --char-limit 500) || exit 1
# a directory (needs at least one subdirectory to choose from)
dir=$(gum file . --directory --file=false --all) || exit 1
# yes or no
if gum confirm "List files in the current directory?"; then
ls -la .
ficonfirm exits 0 for the affirmative and 1 for the negative or Esc. Ctrl+c
returns a nonzero status. An if branch runs only on success. In write,
Enter submits and Ctrl+J inserts a newline.
gum spin --spinner dot --show-output --title "Listing files" -- find . -type f
gum spin --show-output --title "Measuring directory" -- du -sh .The command's exit status is gum's exit status. --show-output streams both
stdout and stderr. With --show-output alone, a failing command's output is
discarded; add --show-error to print it. These flags apply only when stdout
is a terminal. When stdout is a pipe, a file, or $(...), gum hands it to the
command directly, so its stdout is captured with or without --show-output,
even when it fails. --timeout makes gum stop waiting and exit 124, but the
command keeps running; wrap it in timeout(1) when it must stop.
gum style --foreground 212 --border double --padding "1 3" "Project tasks"
gum join --horizontal --align top "$left" "$right"
gum format < README.md
gum table --print --border rounded --file status.csv
gum pager < CHANGELOG.md
gum log --structured --level info "task completed" task "List files"Read references/commands.md for the style flags and
env defaults, join layouts, format types (code, template, emoji) and
themes, interactive table row selection, pager search, and log levels,
formatters, and time layouts.
#!/usr/bin/env bash
set -euo pipefail
gum style --border rounded --padding "0 2" --foreground 212 "Project tasks"
tasks=$(gum choose --no-limit --selected='*' --ordered --header "Tasks" \
"List files" "Show size") || exit 1
[[ -n $tasks ]] || { gum log --level warn "No tasks selected"; exit 0; }
dir=$(gum file . --directory --file=false --all) || exit 1
gum confirm "Run the selected tasks in $dir?" || exit 1
while IFS= read -r task; do
case "$task" in
"List files") gum spin --show-output --show-error --title "$task" -- ls -la "$dir" ;;
"Show size") gum spin --show-output --show-error --title "$task" -- du -sh "$dir" ;;
*) printf 'Unknown task: %s\n' "$task" >&2; exit 1 ;;
esac
gum log --structured --level info "task completed" task "$task" directory "$dir"
done <<<"$tasks"The examples use Bash syntax. The complete recipe was exercised with gum
2.0.2, including cancellation, a declined confirm, and an empty selection. It
uses set -euo pipefail and a here string. For fish, adapt the assignments,
loops, and error handling to fish syntax. A complete fish recipe is not
included; fish and Zsh versions have not been tested.
[ -n "$choice" ] but not the exit status. An aborted prompt can
still print a preselected value in some commands; check $?.gum input without --width panics and exits 124 with "timed out".choose. Quote each option,
or feed them on stdin one per line.--no-limit and then wondering why only one item comes back.gum choose or Ctrl+Space in gum filter.
Use x or tab in choose and tab in filter.gum spin for a command that needs the TTY (an editor, a login
prompt). spin captures the command's output; run those directly.brew install gum,
nix-env -iA nixpkgs.gum), and go install charm.land/gum/v2@latest
builds the current release. The old path github.com/charmbracelet/gum
stops at 0.17.0.gum --version on 0.17.0 printed the version with a leading v; 2.x
prints it without one (gum version 2.0.2).choose in 0.17.0 and do nothing in 2.x.filter in 0.17.0; 2.x uses tab.format kept its colors when piped; 2.x strips them like
style and join.