███████╗ ██╗ ██╗███╗ ███╗ ██╔════╝ ██║ ██║████╗ ████║ ███████╗ ██║ ██║██╔████╔██║ ██═══██║ ██║ ██║██║╚██╔╝██║ ███████║ ╚██████╔╝██║ ╚═╝ ██║ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝
A blazingly fast, elegant, and dependency-free library for building command-line interfaces in Go.
gum provides a powerful, fluent API that makes defining complex command-line applications simple and readable. It is built from the ground up with performance and developer experience as first-class citizens.
- Fluent, Chainable API: Structure your CLI in a natural, declarative way.
- Zero Dependencies: Keep your applications light and your builds fast. No external modules needed.
- Blazingly Fast: Optimized for minimal memory allocations and high performance. See the benchmarks below.
- Automatic Help Generation: Beautiful, detailed, and context-aware help text for all commands.
- Built-in Shell Completion: Add Bash and Zsh completion with a single line of code.
- Powerful Middleware: Use
UnsureActionto create logging, metrics, or validation layers that don't halt execution. - Robust & Battle-Tested: A comprehensive test suite ensures reliability.
gum is designed to be exceptionally fast. Benchmarks run on a standard Intel(R) Core(TM) i5-5200U show just how little overhead the library adds.
| Benchmark Task | Time / Operation | Memory / Operation | Allocations / Operation |
|---|---|---|---|
| Simple Parse | ~2,565 ns/op |
864 B/op |
11 allocs/op |
| Complex Parse | ~2,644 ns/op |
1088 B/op |
10 allocs/op |
| Help Text Generation | ~10,529 ns/op |
2984 B/op |
59 allocs/op |
This means gum can parse even complex commands with subcommands and multiple flags in ~2.6 microseconds while allocating just over 1KB of memory.
First, add gum to your project:
go get github.com/devmdo/gumNext, create a simple main.go file. This example demonstrates a root command with a flag and a subcommand in just a few lines.
// main.go
package main
import (
"fmt"
"github.com/devmdo/gum"
)
func main() {
app := gum.NewApp("git").
Description("A simple git-like example app").
Version("1.0.0").
Option("-v, --verbose", "Enable verbose output") // Global flag
// Define the 'clone' command
app.Command("clone, c").
Description("Clone a repository into a new directory").
Arg("repository", "The repository to clone").
Option("-b, --branch", "Branch to checkout", "main").
Action(func(args *gum.Args) error {
repo := args.Arg(0)
branch := args.String("branch")
fmt.Printf("Cloning repository '%s' on branch '%s'...\n", repo, branch)
if args.Bool("verbose") {
fmt.Println("Verbose mode enabled.")
}
return nil
})
// Run the application
app.Run()
}Try it out!
# Build the application
go build .
# Run the subcommand
./git clone https://github.com/my/repo
# Output: Cloning repository 'https://github.com/my/repo' on branch 'main'...
# Use aliases, flags, and global flags
./git -v c https://github.com/my/repo --branch dev
# Output: Cloning repository 'https://github.com/my/repo' on branch 'dev'...
# Verbose mode enabled.
# Get automatically generated help
./git clone --helpThe core of gum is the Command. You can chain .Command() calls to create nested subcommands. Provide a comma-separated string to define a primary name and its aliases.
func main() {
app := gum.NewApp("docker")
// Command with aliases
app.Command("run, r").
Description("Run a command in a new container")
// Nested subcommands
remote := app.Command("remote").
Description("Manage remote connections")
remote.Command("add").
Description("Add a new remote")
remote.Command("rm, remove").
Description("Remove a remote")
app.Run()
}gum supports positional arguments and a rich set of flag types.
- Positional Arguments: Use
.Arg()to define arguments for documentation in the help text.app.Command("clone"). Arg("repository", "The repository to clone"). Arg("directory", "The destination directory (optional)")
- Options (Flags): Use
.Option()to define flags.// Boolean flag (present or not) app.Option("-v, --verbose", "Enable verbose output") // Flag that takes a value app.Option("-o, --output", "Specify output file") // Flag with a default value app.Option("--port", "The port to listen on", "8080")
- Parsing Formats:
gumhandles all common formats automatically:--flag value--flag=value-f value-abc(for combined boolean flags)
The .Action() method is where your command's logic lives. It receives an *Args object to access parsed values.
app.Command("commit").
Option("-m, --message", "The commit message").
Option("-a, --all", "Stage all changed files").
Action(func(args *gum.Args) error {
// BTW you can count args by args.Len()
// Check for boolean flag
if args.Bool("all") {
fmt.Println("Staging all files...")
}
// Get string value from a flag (works with -m or --message)
message := args.String("message")
if message == "" {
return errors.New("commit message is required")
}
// Get positional arguments by index
// e.g., for a command `my-app get user 123`
resource := args.Arg(0) // "user"
idStr := args.Arg(1) // "123"
// Type conversion helpers
id, err := args.Int("id") // Also supports Float64()
if err != nil {
return err
}
fmt.Printf("Committing with message: %s\n", message)
return nil
})gum generates beautiful and useful help text automatically. Simply run your command with --help or provide no action for a command that has subcommands.
You can customize the output with:
.Description(string): Set the main description..Example(string): Provide a specific usage example..ExtraUsage(string): Add a free-form text block at the end of the help message.
Example output for ./git clone --help:
A test CLI application.
USAGE:
test-cli clone <repo> [options]
ARGUMENTS:
repo The repository URL.
OPTIONS:
--branch, -b The branch to checkout (default: "main")
--config Path to a custom config file (default: "default.json")
-v Enable verbose output
-R Recursive
--version Print version information and exit
EXAMPLE:
test-cli clone my-repo --branch dev
Provides a first-class user experience by adding shell completion for bash and zsh.
Your users can enable it with a simple command:
Bash:
eval "$(your-app completion bash)"
```**Zsh:**
```bash
eval "$(your-app completion zsh)"This project is licensed under the MIT License. See the LICENSE file for details.