# gum brings terminal prompts to your shell scripts without a line of Go

> A Charm tool that turns fuzzy finders, menus, confirmations and styled text into ordinary shell commands, so dotfile aliases and scripts can ask real questions.

**charmbracelet/gum** — A tool for glamorous shell scripts 🎀

- Repository: https://github.com/charmbracelet/gum
- Stars: 24,398 · Forks: 548
- Language: Go
- License: MIT
- Published: 2026-10-06 · Updated: 2026-10-06 · Language: en
- Canonical page: https://hysenlabs.com/projects/charmbracelet-gum

## Installing gum across the package managers you already have

The README documents an unusually wide set of install paths, which tells you something about who uses this. Homebrew covers macOS and Linux, with separate notes for Arch, Fedora and EPEL 10, Nix, Flox, WinGet and Scoop on Windows, plus pkg and ports for FreeBSD. There is a documented Debian and Ubuntu path that adds the Charm apt repository:

```bash
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://repo.charm.sh/apt/gpg.key | sudo gpg --dearmor -o /etc/apt/keyrings/charm.gpg
echo "deb [signed-by=/etc/apt/keyrings/charm.gpg] https://repo.charm.sh/apt/ * *" | sudo tee /etc/apt/sources.list.d/charm.list
sudo apt update && sudo apt install gum
```

There is also a Go install path, which is the shortest option if you already have a Go toolchain:

```bash
go install charm.land/gum/v2@latest
```

Prebuilt binaries exist for Linux, macOS, Windows, FreeBSD, OpenBSD and NetBSD, and release packages come in Debian, RPM and Alpine formats. Note that the module path in `go.mod` is `charm.land/gum/v2`, not the older `github.com/charmbracelet/gum`, a change that arrived with the v2.0.0 release on 2026-08-20. The last push was on 2026-09-11 and v2.0.1 followed that day.

## The command set is thirteen small programs, not a framework

Gum's structure is the main thing to understand. There is no plugin API and no library you call. The repository has one directory per command, `choose/`, `confirm/`, `input/`, `write/`, `filter/`, `file/`, `table/`, `style/`, `format/`, `join/`, `pager/`, `spin/` and `log/`, plus `completion/` and `man/` for the generated shell completions and man pages. That is thirteen commands, each usable on its own.

The README's point is that this lets you compose scripts from commands instead of writing a program. `choose` picks from a list, `confirm` asks a yes or no question, `input` prompts for a line, `write` prompts for multi-line text ending on ctrl+d, `filter` does fuzzy matching over stdin, `spin` shows a spinner while a command runs, and `style` applies colour, borders and spacing to text.

The practical consequence is that gum scripts stay scripts. There is no build step, no runtime to install on the target machine beyond the binary, and no language binding in the way.

## A commit helper assembled from four commands

The README builds a Conventional Commits helper for dotfiles, and the example is worth reading because it shows the composition pattern rather than any single feature. Pick a commit type:

```bash
gum choose "fix" "feat" "docs" "style" "refactor" "test" "chore" "revert"
```

The README flags the obvious issue itself: this prints to stdout, which is only useful if you capture it. Then prompt for the scope and the summary, pre-filling the value so the type and scope are already in place:

```bash
gum input --placeholder "scope"
gum input --value "$TYPE$SCOPE: " --placeholder "Summary of this change"
gum write --placeholder "Details of this change"
```

And gate the commit on a confirmation:

```bash
gum confirm "Commit changes?" && git commit -m "$SUMMARY" -m "$DESCRIPTION"
```

The complete version lives at `examples/commit.sh`. Scripts for staging and branching exist alongside it in the same directory, plus language wrappers for Python, Ruby and JavaScript. The `&&` before `git commit` is the whole safety story: gum decides, git does the writing.

## Fuzzy filtering over stdin with selectable results

`gum filter` is the command that most often replaces an existing tool, because it gives you fzf-style fuzzy matching without needing fzf. It reads a list and writes one selection:

```bash
gum filter < flavors.txt > selection.txt
```

Multi-select uses the same flag shape as `choose`, with a limit rather than a single answer:

```bash
cat flavors.txt | gum filter --limit 2
cat flavors.txt | gum filter --no-limit
```

The README documents the key bindings: tab or ctrl+space to toggle an item, enter to confirm. Redirecting output to a file, as in the first example, is worth noticing. It turns the interactive prompt into a step in a pipeline, and it is also how you avoid a program blocking forever when the script runs somewhere with no terminal attached.

## Padding, styling and environment variable configuration

Every command accepts flags for appearance and behaviour, and the same settings can come from environment variables with a command prefix. Flags win over the environment. This is a real convenience in dotfiles, where you set the look once in your shell profile:

```bash
export GUM_INPUT_CURSOR_FOREGROUND="#FF0"
export GUM_INPUT_PROMPT_FOREGROUND="#0FF"
export GUM_INPUT_PLACEHOLDER="What's up?"
export GUM_INPUT_WIDTH=80
```

Spacing works the way CSS padding does, which the v0.17.0 release notes spell out: one value applies to all sides, two apply vertically then horizontally, four apply top, right, bottom, left. Padding is available on `choose`, `confirm`, `file`, `filter`, `input`, `pager`, `spin`, `style`, `table` and `write`.

The `style` command handles colour, borders and spacing for arbitrary text rather than for a prompt, which is what you want when a script prints a heading before its output.

## What the Go dependencies say about the rendering layer

`go.mod` is more informative about the project than the README is. The module targets Go 1.26.7 and depends on `charm.land/bubbletea/v2`, `charm.land/bubbles/v2`, `charm.land/lipgloss/v2` and `charm.land/glamour/v2`, which is the Charm terminal UI stack, plus `github.com/sahilm/fuzzy` for matching, `github.com/alecthomas/kong` for the command line parser, and `github.com/charmbracelet/colorprofile` and `github.com/charmbracelet/x/ansi` for terminal capability detection.

The v2.0.0 release notes are worth a look because they explain a version bump rather than a feature: gum moved to Bubble Tea v2 and Lip Gloss v2, with the release noting faster and more accurate rendering as the practical effect, and the module path changed to `charm.land/gum/v2` at the same time. The v2.0.1 patch that followed on 2026-09-11 fixed stray symbols leaking into output from keyboard protocol handling, which is the kind of bug you hit on unusual terminals.

Running against a library that is itself pre-1.0 in places is the main thing to weigh. Bubbletea v2 and the `charm.land` module path both suggest an ecosystem still settling, and the v2.0.0 to v2.0.1 sequence is short enough to be reassuring about responsiveness rather than proof of stability.

## Conclusion

gum works because it stays out of the way. Each capability is a separate subcommand, every one writes to stdout, and the only dependency is a binary you install once. That means a script using `gum choose` and `gum confirm` is still a shell script you can read, and a teammate without Go installed can run it. The cost is that you are depending on a terminal UI library being happy inside your automation: output that assumes a human at a keyboard will misbehave when it is redirected, so pipe to a file when the answer is not going to a person. For interactive commit helpers, dotfile menus and any prompt that was previously three lines of fragile `read` and `echo`, the fit is close to exact.

## FAQ

### What is gum in Linux?

Gum is a Go program that exposes Charm's terminal interface libraries as shell commands, so scripts and dotfile aliases can prompt, choose, filter and style without writing Go. On Linux it installs with `dnf install gum`, `pacman -S gum`, Homebrew, the documented apt repository, or a prebuilt binary. Each subcommand such as `gum filter` and `gum confirm` reads from stdin and writes to stdout.

### How do I install gum on Arch Linux?

The README gives the Arch command directly: `pacman -S gum`. It also lists Homebrew, dnf for Fedora and EPEL 10, Nix, Flox, WinGet and Scoop, a documented apt repository for Debian and Ubuntu, pkg and ports for FreeBSD, and `go install charm.land/gum/v2@latest` if you have a Go toolchain. Prebuilt binaries cover Linux, macOS, Windows, FreeBSD, OpenBSD and NetBSD.

### Is gum a replacement for fzf in shell scripts?

`gum filter` covers the part of fzf most scripts use, which is fuzzy matching over stdin with tab or enter to select. Fzf also offers preview panes, arbitrary key binding and history, so gum is not a complete substitute for it. Where gum differs is breadth: a script that needs a fuzzy finder plus a confirmation plus a menu can reach for one binary instead of three.

## Sources

- [charmbracelet/gum on GitHub](https://github.com/charmbracelet/gum)
- [Issues](https://github.com/charmbracelet/gum/issues)
- [License: MIT](https://github.com/charmbracelet/gum/blob/main/LICENSE)
- [README](https://github.com/charmbracelet/gum/blob/main/README.md)
- [Releases](https://github.com/charmbracelet/gum/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/charmbracelet-gum
