Kingpin

A Go command line argument parser. Features fluent interface and POSIX/GNU convention support.

goclifluent-interfaceposix

Framework

Kingpin

Overview

Kingpin is a Go command line argument parser. It features fluent interface and POSIX/GNU convention support. It provides a simple and intuitive API, making it easy to build complex command-line structures. It's currently in maintenance mode, and other options are recommended for new projects.

Details

Kingpin has been a proven CLI library used by the Go community for many years. Its fluent interface enables highly readable command definitions and has been adopted by many open source projects. However, active development has now ended and it has moved to maintenance mode. For new projects, using more actively developed libraries like cobra or urfave/cli is recommended.

Key Features

  • Fluent Interface: Intuitive API through method chaining
  • POSIX/GNU Convention Support: Compliant with standard command-line conventions
  • Subcommands: Supports hierarchical command structures
  • Custom Validation: Enables implementation of custom value validation logic
  • Shell Completion: Supports completion for Bash, Zsh, Fish, and PowerShell
  • Environment Variable Support: Can retrieve flag default values from environment variables
  • Help Generation: Automatic generation of help messages and usage

Pros and Cons

Pros

  • Readability: Easy-to-understand code through fluent interface
  • Rich Features: Covers all features needed for full-fledged CLI applications
  • Standards Compliant: Consistent behavior conforming to POSIX/GNU conventions
  • Flexibility: Enables implementation of custom validation and value parsers
  • Track Record: Adoption record in many projects

Cons

  • Maintenance Status: Currently in maintenance mode with new feature development stopped
  • Community: Limited active community support
  • Future Viability: Concerns about long-term support
  • Learning Cost: Other options are recommended for new projects

Key Links

Example Usage

package main

import (
	"fmt"
	"net"
	"os"
	"strings"
	"time"

	"github.com/alecthomas/kingpin/v2"
)

var (
	// Global flags
	debug   = kingpin.Flag("debug", "Enable debug mode").Bool()
	timeout = kingpin.Flag("timeout", "Timeout waiting for ping").
		Default("5s").
		Envar("PING_TIMEOUT").
		Short('t').
		Duration()
	
	// Arguments
	ip    = kingpin.Arg("ip", "IP address to ping").Required().IP()
	count = kingpin.Arg("count", "Number of packets to send").Int()
)

func main() {
	// Set version
	kingpin.Version("0.0.1")
	
	// Parse arguments
	kingpin.Parse()
	
	// Execute
	fmt.Printf("Would ping: %s with timeout %s and count %d\n", *ip, *timeout, *count)
	
	if *debug {
		fmt.Println("Debug mode enabled")
	}
}

// Example with subcommands
func withSubcommands() {
	var (
		app = kingpin.New("chat", "A command-line chat application")
		
		// Global flags
		serverIP = app.Flag("server", "Server address").Default("127.0.0.1").IP()
		debug    = app.Flag("debug", "Enable debug mode").Bool()
		
		// register command
		register     = app.Command("register", "Register a new user")
		registerNick = register.Arg("nick", "Nickname for user").Required().String()
		registerName = register.Arg("name", "Name of user").Required().String()
		
		// post command
		post        = app.Command("post", "Post a message to a channel")
		postChannel = post.Arg("channel", "Channel to post to").Required().String()
		postText    = post.Arg("text", "Text to post").Strings()
		postImage   = post.Flag("image", "Image to post").File()
	)
	
	switch kingpin.MustParse(app.Parse(os.Args[1:])) {
	case register.FullCommand():
		fmt.Printf("Register user: %s (%s)\n", *registerNick, *registerName)
		
	case post.FullCommand():
		fmt.Printf("Posting to channel %s\n", *postChannel)
		if *postImage != nil {
			fmt.Println("With image attachment")
		}
		if len(*postText) > 0 {
			fmt.Printf("Message: %s\n", strings.Join(*postText, " "))
		}
	}
}