A simple, fast, and fun package for building command line apps in Go

cli

GoDoc codebeat Go Report Card codecov

cli is a simple, fast, and fun package for building command line apps in Go. The goal is to enable developers to write fast and distributable command line applications in an expressive way.

Usage Documentation

Usage documentation exists for each major version. Don't know what version you're on? You're probably using the version from the master branch, which is currently v2.

Guides for migrating to newer versions:

Installation

Using this package requires a working Go environment. See the install instructions for Go.

Go Modules are required when using this package. See the go blog guide on using Go Modules.

Using v2 releases

$ GO111MODULE=on go get github.com/urfave/cli/v2
...
import (
  "github.com/urfave/cli/v2" // imports as package "cli"
)
...

Using v1 releases

$ GO111MODULE=on go get github.com/urfave/cli
...
import (
  "github.com/urfave/cli"
)
...

GOPATH

Make sure your PATH includes the $GOPATH/bin directory so your commands can be easily used:

export PATH=$PATH:$GOPATH/bin

Supported platforms

cli is tested against multiple versions of Go on Linux, and against the latest released version of Go on OS X and Windows. This project uses Github Actions for builds. To see our currently supported go versions and platforms, look at the ./.github/workflows/cli.yml.

Owner
I love you so very much.
null
Comments
  • Required Flags

    Required Flags

    It would be really nice to have required flags and required arguments. I'm mostly putting this here as a place holder to discuss although I would be willing to put some work in on this if we can talk about how we would like to implement it.

    I was thinking the easiest would just add a new field to the struct called "Required". Internally we could have some checking and fail if the required flag is not set.

    type Flag interface {
        fmt.Stringer
        Required bool
        // Apply Flag settings to the given flag set
        Apply(*flag.FlagSet)
        getName() string
    }
    
    func (f *Flag) IsRequired() bool {
      return f.Required
    }
    
  • maint: release 2.X

    maint: release 2.X

    If anyone is interested in the work of merging the master branch into v2, add let us know here with a "🤚I'm interested in working on this" comment!


    The comments below describe a random assortment of release 2.X concerns 📝

  • Support required and optional arguments

    Support required and optional arguments

    I supported a new field, Args, to cli.Command to specify required and optional arguments.

    For example, we can write like this.

    Name: "get",
    Args: "<name> [id]",  // name is required, id is optional
    Action: func(c *cli.Context) {
            name, _ := c.ArgFor("name")
            id, b := c.ArgFor("id")  // b is false if 2nd arg is not given
    },
    

    And the usage text appears like this.

    USAGE:
       command get <name> [id]
    

    I'm not sure whether the field name Args is good or not. I'm OK to change any names I added if you guys hope it.

    Best,

  • Release 1.22.1

    Release 1.22.1

    Summary

    I wanted these PRs to be a part of 1.22.0 but owing to certain dependency issues it was not possible. With 1.22.0 in place, I would like to propose this minor release that would include the new build system and support for Go 1.13 in our latest stable version.

    Let me know if we can include anything else.

    Included PRs

    #883 #885

  • Before callback affects bash completions

    Before callback affects bash completions

    my urfave/cli version is

    v1.22.2, v1.22.3

    Checklist

    • [x] Are you running the latest v1 release? The list of releases is here.
    • [x] Did you check the manual for your release? The v1 manual is here
    • [x] Did you perform a search about this problem? Here's the Github guide about searching.

    Dependency Management

    • My project is using go modules.

    Describe the bug

    I wanted to introduce pre-check (with .Before callback) that would be run if the command is being executed. But it seems like the pre-check is also executed when I want to only show the completions for a given command what breaks the completions output if the .Before has printed anything (in particular the error).

    To reproduce

    package main
    
    import (
    	"errors"
    	"fmt"
    	"log"
    	"os"
    
    	"github.com/urfave/cli"
    )
    
    func main() {
    	app := cli.NewApp()
    	app.Name = "example"
    	app.EnableBashCompletion = true
    	app.Before = func(_ *cli.Context) error { return errors.New("uups") }
    	app.Commands = []cli.Command{{
    		Name:   "cmd",
    		Action: func(c *cli.Context) error { return nil },
    		Flags:  []cli.Flag{cli.StringFlag{Name: "abc"}},
    		BashComplete: func(c *cli.Context) {
    			fmt.Println("--abc")
    		},
    	}}
    	app.Action = func(c *cli.Context) error {
    		fmt.Println("Hello friend!")
    		return nil
    	}
    
    	err := app.Run(os.Args)
    	if err != nil {
    		log.Fatal(err)
    	}
    }
    
    1. Build the code above.
    2. Enable completions
    3. example cmd [TAB]

    Observed behavior

    $ example cmd ......2020/03/25 11:53:14 uups
    $ example cmd
    GLOBAL OPTIONS  COMMANDS  USAGE  NAME  --
                                                                                    example - A new cli application                                           uups
       --help, -h  show help                                                        example [global options] command [command options] [arguments...]
       cmd                                                                          help, h  Shows a list of commands or help for one command
    

    Expected behavior

    Show completions for the given cmd:

    $ example cmd [TAB]
    --abc
    

    Additional context

    Looking at the code I've noticed that the commands are parsed/visited hierarchically and this also applies for the completions. But I'm not sure if the order should be as it is now. To me completions should be executed first even if the command is nested.

    Run go version and paste its output here

    go version go1.14 darwin/amd64
    
  • Relax ordering requirements for flags/commands to improve upon cli ergonomics

    Relax ordering requirements for flags/commands to improve upon cli ergonomics

    Checklist

    • [X ] Are you running the latest v2 release? The list of releases is here.
    • [X ] Did you check the manual for your release? The v2 manual is here
    • [ X] Did you perform a search about this feature? Here's the Github guide about searching.

    What problem does this solve?

    CLI ergonomics when editing/adding flags to command are very bad.

    Quick example, consider how many times you have to move cursor back in commandline to go from

    $ cmd query users
    

    to

    $ cmd --out=csv query --filter "project=kittens" users --with-permission=Deploy
    

    vs

    $ cmd query users --with-permission=Deploy  --filter  "project=kittens", --out=csv 
    

    It also "reads" worse: "output CSV on query project kittens on users with permissions to deploy: vs " query users that can deploy in project kittens, output csv"

    Without forced ordering you can add a flag at the end at any point so ad-hoc usage of commands is much more streamlined, it also allows writing CLI scripts with arguments grouped by what makes more sense, not by how program author structured it.

    Now the long winded example, consider the following:

    • App has global flags applicable to all subcommands like
      • change output type (for example switch between machine-parseable and user-frien
      • server address
      • config/credentials pass
      • environment
      • etc
    • Application has subcommand with their own flags user might want to iterate

    Let's say app has a subcommand to query systems state

    cmd query
    

    Which has --filter string option, and this command have subcommands for various parts of system

    cmd query nodes
    cmd query services
    cmd query users
    

    with various sub-subcommand specific switches. Let's say user wants to only see stuff about a certain project. No worries, we have --filter flag for it

    $ cmd query --filter project=kittens
    

    User now wants to see who has access to that project. But we have options just for that

    $ cmd query --filter project=kittens users 
    

    So far so good. Let's see which of them can deploy the application

    $ cmd query --filter project=kittens users --with-permission=Deploy
    

    Okay, now let's compare it with another project...

    $ cmd query --filter project=dogs users --with-permission=Deploy
    

    Now we need to go back 4 words (4x C-b) and we can start changing it. But we have few more projects to check? How about just move filter at the end ?

    $ cmd query  users --with-permission=Deploy --filter project=dogs
    flag provided but not defined: -filter
    

    Okay, we can't. Bit annoying but it is only few commands.

    $ for project in kittens dogs otters ducks ; do cmd query --filter "project=$project" users --with-permission=Deploy ; done
    

    Right, it does what we wanted. Now onto writing that report. There is a csv output format so it should be trivial.

    $ for project in kittens dogs otters ducks ; do cmd query --filter "project=$project" users --with-permission=Deploy --out=csv; done
    flag provided but not defined: -out
    

    Oh, right, go C-b NINE times because that needs to be after a command but before subcommand.

    $ for project in kittens dogs otters ducks ; do cmd --out=csv query --filter "project=$project" users --with-permission=Deploy ; done
    

    Want to bump it to verbose or enable debug ? Go back nearly to the start of the line. Want to set environment or target server ? Same. Only real option to have convenient ability to change the parameters used in whole app is duplicating them as command-local variables.

    The migration manual mentions something that "it is more POSIX-like" but POSIX conventions never had a notion of subcommands in the first place, the "stuff after options" was not a subcommand but also command's parameters (usually file to operate on), and even now most of the say coreutils tools allow for having options in any place just for convenience (GNU's ls -la /tmp and ls /tmt -la have same effect for example)

    Solution description

    Every --option in commandline should be considered for a flag, from closest "leaf" subcommand to the root

    so

    $ cmd --env=dev query --filter type=sqldb
    $ cmd query --filter type=sqldb --env=dev
    

    should be equivalent. Sometimes even having options before subcommand makes sense, like

    $ cmd --filter="type=sqldb" query users
    $ cmd --filter="type=sqldb" query nodes
    $ cmd --filter="type=sqldb" query services
    

    Describe alternatives you've considered

    Copying every flag to local "works" but it isn't exactly elegant, and messes up with generated help.

  • Add word-wrap support, with wrap length provided by the user

    Add word-wrap support, with wrap length provided by the user

    What type of PR is this?

    • feature

    What this PR does / why we need it:

    The help text is difficult to read when the lines are long. This patch attempts to wrap long lines, if the user provides a terminal width to wrap at.

    Which issue(s) this PR fixes:

    Updated version of #1044.

    Refers to #287.

    Testing

    Added a unit test (which can be expanded).

    Release Notes

    The help text is now wrapped to fit the terminal window.
    
  • Add an `App.ProgramName`

    Add an `App.ProgramName`

    Motivation & Context

    I have the following code:

    app := cli.NewApp()
    app.Name = "myprogramname"
    

    I then add a sub command with the name "foo", and in that sub command I run:

    func fooAction(c *cli.Context) error {
    	program := c.App.Name
    	log.Printf("program is: %s", program)
    }
    

    Unfortunately this prints "program is: myprogramname foo" instead of leaving out the "foo". This is unexpected, particularly because the "program" did not change. If it is desired to have some sort of variable that appends the sub command names on it, then it should be something different. I use this variable to ascertain the "base name" of the program reliably, for log messages, etc...

    Requested Change

    Add an app.ProgramName, that is always myprogramname, regardless of whether or not a particular subcommand is being executed.


    heavily edited by @lynncyrin!

  • merge altsrc with main package

    merge altsrc with main package

    What type of PR is this?

    • cleanup

    What this PR does / why we need it:

    This is one of the first goals for the v3 release (via https://github.com/urfave/cli/issues/833#issue-476467837). This helps condense the public API by reducing two exposed packages from before into a single package.

    Release Notes

    - Remove `altsrc` package
    - Add `FlagInputSourceExtension` interface to allow a value to be set on existing parsed flags through alternate sources like `JSON` or `TOML` etc.
    
  • Recieve and handle ctrl + c and exit application

    Recieve and handle ctrl + c and exit application

    Fixes #945

    We were correctly receiving ctrl+c signal and cancelling our application context. The missing piece of the puzzle was not listening for context cancellation and exiting the program.

    Since ctrl+c is a non standard program termination, I have used a non zero exit code i.e. 1 for the moment. Please let me know if we want to give the user an option to set a exit code themselves in case of ctrl+c exit. We can then add an option in the App for that then.

  • Allow global flags after command

    Allow global flags after command

    This is just a suggestion, but to me it seems logical to allow global flags after the command as well, not only before it.

    For example, if you have a verbose flag, -v: myapp -v server vs. myapp server -v

    To me the second one does visually make more sense. Are there cases when this is a bad idea (and therefore the reason to why this is not how it is currently implemented)?

  • Feature:(issue_1215) Allow calling commands by shorthand

    Feature:(issue_1215) Allow calling commands by shorthand

    What type of PR is this?

    (REQUIRED)

    • feature

    What this PR does / why we need it:

    (REQUIRED)

    Allows closest match calling of command

    Which issue(s) this PR fixes:

    (REQUIRED)

    Fixes #1215

    Special notes for your reviewer:

    (fill-in or delete this section)

    Testing

    (fill-in or delete this section)

    Release Notes

    (REQUIRED)

    
    
  • Add StringMap flag for altsrc

    Add StringMap flag for altsrc

    My urfave/cli version is

    ( Put the version of urfave/cli that you are using here ) 2.x

    Checklist

    • [x ] Are you running the latest v2 release? The list of releases is here.
    • [ x] Did you check the manual for your release? The v2 manual is here
    • [ x] Did you perform a search about this problem? Here's the GitHub guide about searching.

    Dependency Management

    • My project is using go modules.
    • My project is using vendoring.
    • My project is automatically downloading the latest version.
    • I am unsure of what my dependency management setup is.

    Describe the bug

    Extend #1580 for altsrc flags

    To reproduce

    Describe the steps or code required to reproduce the behavior

    Observed behavior

    What did you see happen immediately after the reproduction steps above?

    Expected behavior

    What would you have expected to happen immediately after the reproduction steps above?

    Additional context

    Add any other context about the problem here.

    If the issue relates to a specific open source GitHub repo, please link that repo here.

    If you can reproduce this issue with a public CI system, please link a failing build here.

    Want to fix this yourself?

    We'd love to have more contributors on this project! If the fix for this bug is easily explained and very small, feel free to create a pull request for it.

    Run go version and paste its output here

    # paste `go version` output in here
    

    Run go env and paste its output here

    # paste `go env` output in here
    
  • Fix:(issue_1277) Remove default text for version/help flags

    Fix:(issue_1277) Remove default text for version/help flags

    What type of PR is this?

    (REQUIRED)

    • bug
    • documentation
    • feature

    What this PR does / why we need it:

    (REQUIRED)

    Remove default text for help/version flags

    Which issue(s) this PR fixes:

    (REQUIRED)

    Fixes #1277

    Special notes for your reviewer:

    (fill-in or delete this section)

    Testing

    (fill-in or delete this section)

    make test

    Release Notes

    (REQUIRED)

    
    
  • Required=true in StringFlag allows empty string

    Required=true in StringFlag allows empty string

    My urfave/cli version is

    v2.23.7

    Checklist

    • [x] Are you running the latest v2 release? The list of releases is here.
    • [x] Did you check the manual for your release? The v2 manual is here
    • [x] Did you perform a search about this problem? Here's the GitHub guide about searching.

    Dependency Management

    • My project is using go modules.
    • My project is automatically downloading the latest version.

    Describe the bug

    When a StringFlag has Required=true set, setting an empty String is still possible by explicitly setting to empty string (see observed section below).

    I don't see a use case where a Required string flag would allow setting an empty string. I mean, I want that the user provides a value in the first place, why should empty strings be allowed? If an empty string is allowed, then it shouldn't be Required in the first place, therefore I consider this a bug.

    To reproduce

    MWE:

    package main
    
    import (
    	"fmt"
    	"os"
    
    	"github.com/urfave/cli/v2"
    )
    
    func main() {
    	app := cli.App{
    		Flags: []cli.Flag{
    			&cli.StringFlag{
    				Name:     "flag",
    				EnvVars:  []string{"FLAG"},
    				Required: true,
    			},
    		},
    		Action: func(context *cli.Context) error {
    			flag := context.String("flag")
    			fmt.Fprintf(os.Stdout, "Flag value is %q\n", flag)
    			return nil
    		},
    	}
    	err := app.Run(os.Args)
    	if err != nil {
    		fmt.Println(err)
    	}
    }
    

    Observed behavior

    $ FLAG= go run .
    Flag value is ""
    
    # or
    $ go run . --flag=
    Flag value is ""
    
    # if set, as expected
    $ go run . --flag=example
    Flag value is "example"
    
    # if unset
    $ go run .
    ...
       --flag value   [$FLAG]
       --help, -h    show help (default: false)
    Required flag "flag" not set
    

    Expected behavior

    I would expect that the StringFlag with Required=true would check if a value is actually given:

    $ FLAG= go run .
    Required flag "flag" not set
    

    Additional context

    To workaround the check that the value is non-empty, I have to add a flag action like this:

    		Action: func(ctx *cli.Context, s string) error {
    			if s == "" {
    				return fmt.Errorf(`Required flag "flag" not set`)
    			}
    			return nil
    		},
    

    However, IMO this should be covered by the Required=true setting in the cli package already when parsing the flags.

    Want to fix this yourself?

    I might be able to provide a fix, if the maintainers agree that this behavior is indeed a bug, and not "by design" or considered a breaking change.

    Run go version and paste its output here

    go version go1.19.4 linux/amd64
    

    Run go env and paste its output here

    I don't see how it's relevant here.

  • Feature:(issue_1222) Add support for mutually exclusive groups

    Feature:(issue_1222) Add support for mutually exclusive groups

    What type of PR is this?

    (REQUIRED)

    • feature

    What this PR does / why we need it:

    (REQUIRED)

    Which issue(s) this PR fixes:

    (REQUIRED)

    Fixes #1222

    Special notes for your reviewer:

    (fill-in or delete this section)

    Testing

    (fill-in or delete this section)

    Add new tests.

    Release Notes

    (REQUIRED)

    
    
  • Allow `any` instead of custom `*Author` type

    Allow `any` instead of custom `*Author` type

    What type of PR is this?

    • cleanup

    What this PR does / why we need it:

    Drop the custom *Author type and allow any with the assumption that it either implements fmt.Stringer or can otherwise be safely Sprintf'd via %s.

    Which issue(s) this PR fixes:

    Supports #1586 given the *Author type was defined in app.go which is slated for removal.

Go package to make lightweight ASCII line graph ╭┈╯ in command line apps with no other dependencies.
Go package to make lightweight ASCII line graph ╭┈╯ in command line apps with no other dependencies.

asciigraph Go package to make lightweight ASCII line graphs ╭┈╯. Installation go get github.com/guptarohit/asciigraph Usage Basic graph package main

Jan 8, 2023
CLI - A package for building command line app with go
CLI - A package for building command line app with go

Command line interface Screenshot Key features Lightweight and easy to use. Defines flag by tag, e.g. flag name(short or/and long), description, defau

Dec 23, 2022
Simple and complete API for building command line applications in Go

Simple and complete API for building command line applications in Go Module cli provides a simple, fast and complete API for building command line app

Nov 23, 2022
A simple library to build golang command line (cli / cmd)apps

A simple library to build golang command line (cli / cmd)apps

Jan 11, 2022
Creating a simple CLI tool in the Go Programming Language for personal learning and fun

Creating a simple CLI tool in the Go Programming Language for personal learning and fun Open to feedback :) Build docker dev environment docker build

Dec 12, 2021
A command line tool that builds and (re)starts your web application everytime you save a Go or template fileA command line tool that builds and (re)starts your web application everytime you save a Go or template file

# Fresh Fresh is a command line tool that builds and (re)starts your web application everytime you save a Go or template file. If the web framework yo

Nov 22, 2021
Package command provide simple API to create modern command-line interface

Package command Package command provide simple API to create modern command-line interface, mainly for lightweight usage, inspired by cobra Usage pack

Jan 16, 2022
Start Go command line apps with ease
Start Go command line apps with ease

Start Start Go command line apps with ease Executive Summary The start package for Go provides two basic features for command line applications: Read

Oct 29, 2021
An open-source GitLab command line tool bringing GitLab's cool features to your command line
An open-source GitLab command line tool bringing GitLab's cool features to your command line

GLab is an open source GitLab CLI tool bringing GitLab to your terminal next to where you are already working with git and your code without switching

Dec 30, 2022
A command line tool to prompt for a value to be included in another command line.

readval is a command line tool which is designed for one specific purpose—to prompt for a value to be included in another command line. readval prints

Dec 22, 2021
A Go library for building command line applications

gocmd A Go library for building command line applications. Features Advanced command line arguments handling Subcommand handling Short and long comman

Dec 21, 2022
Watcher - A simple command line app to watch files in a directory for changes and run a command when files change!

Watcher - Develop your programs easily Watcher watches all the files present in the directory it is run from of the directory that is specified while

Mar 27, 2022
Hosty is a command-line utility that allows for fast inspection and editing of /etc/hosts-like files

Hosty Description Hosty is a command-line utility that allows for fast inspection and editing of /etc/hosts-like files. It is written in golang and us

Sep 3, 2021
git-xargs is a command-line tool (CLI) for making updates across multiple Github repositories with a single command.
git-xargs is a command-line tool (CLI) for making updates across multiple Github repositories with a single command.

Table of contents Introduction Reference Contributing Introduction Overview git-xargs is a command-line tool (CLI) for making updates across multiple

Dec 31, 2022
git-xargs is a command-line tool (CLI) for making updates across multiple GitHub repositories with a single command
git-xargs is a command-line tool (CLI) for making updates across multiple GitHub repositories with a single command

git-xargs is a command-line tool (CLI) for making updates across multiple GitHub repositories with a single command. You give git-xargs:

Feb 5, 2022
A command line tool for simplified docker volume command built with go

dockervol A command line tool for simplified docker volume command built with go. Features: Remove anonymous volume (beta) Remove volume by matching n

Dec 18, 2021
✍ A package and command line tool to generate Lorem Ipsum
✍ A package and command line tool to generate Lorem Ipsum

Lorelai A package and command line tool to generate Lorem ipsum. Install go get github.com/UltiRequiem/lorelai/pkg Examples Generating Text func print

Jul 27, 2022
Package varflag implements command-line flag parsing into vars.Variables for easy type handling with additional flag types.

varflag Package flag implements command-line flag parsing into vars.Variables for easy type handling with additional flag types. varflag Flags String

Aug 2, 2022
Package osargs provides functions to parse command line arguments

osargs About Package osargs provides functions to parse command line arguments. It is published on https://github.com/vbsw/osargs and https://gitlab.c

May 8, 2022