Evaluating GoLang CLI Packages

Comparing survey, promptui, and go-prompt

Thomas Jay Rush
5 min readJan 15, 2025

Building effective command-line interfaces (such as chifra and khedra) requires choosing the right tools. While Go’s standard library provides basic support for CLIs, it lacks the advanced features necessary for modern, user-friendly CLIs.

A “Modern” Command Line Interface (actually, we used to build these in the 1980s)

This article examines three widely used Go libraries — survey, promptui, and go-prompt—to help you make the best choice for your project. We considered looking at another package called Bubble Tea, which is fantastic, but we felt that it might be overkill for our purposes.

The Packages

We evaluated four “packages.” Go’s standard library, a package called survey, another called promptui , and a third called go-prompt.

The Go standard library allows for basic input handling using packages such as bufio and os.Stdin; however, the standard library lacks features like validation, tab completion, or aesthetic customization. We stopped looking pretty early.

Third-party libraries such as survey, promptui, and go-prompt address these gaps, each offering distinct strengths and weaknesses. We used ChatGPT, which is excellent for wading through all the various options, to help us evaluate. We thought we’d share in the hopes it may help you’all.

In the end, we chose go-prompt for various reasons. Mainly because it has REPL-style capabilities and a more modern feel, which was one of our requirements. Your mileage may vary.

In this article, we briefly describe each package and show examples of how to use them. We then compare each package’s capabilities.

Survey:

https://github.com/AlecAivazis/survey

The first package we evaluated is called survey.

Survey provides an easy-to-use API with built-in validation, multi-select prompts, and several pre-designed input types. It’s an excellent choice for quick and user-friendly CLIs. In the end, we discovered its GitHub repo has recently been archived, which excluded it from further consideration.

Here’s an example of how to code with it.

package main

import (
"fmt"
"github.com/AlecAivazis/survey/v2"
)

func main() {
var name string
prompt := &survey.Input{
Message: "What is your name?",
}
survey.AskOne(prompt, &name)
fmt.Printf("Hello, %s!\n", name)
}

As you can see, survey is straightforward, which is why Chat thought it was suitable for quick and dirty command line tools. It has a lot of options, including pre-canned input types (passwords, radio selection, email input, input validation, etc.) According to Chat, it’s also very well documented. We chose not to use it because it’s been archived.

Promptui:

https://github.com/manifoldco/promptui

promptui excels at creating polished CLIs with customizable templates. While it lacks advanced features like tab completion, it is good at creating visually appealing CLIs. Again, this is a solid library, given its ease of programming, good documentation, community engagement, and features. It can support REPL-style interaction, but one must write custom code. Ultimately, this was the deciding factor against the package for us.

package main

import (
"fmt"
"github.com/manifoldco/promptui"
)

func main() {
prompt := promptui.Prompt{
Label: "What is your name?",
Validate: func(input string) error {
if len(input) == 0 {
return fmt.Errorf("Name cannot be empty")
}
return nil
},
}
name, err := prompt.Run()
if err != nil {
fmt.Printf("Prompt failed %v\n", err)
return
}
fmt.Printf("Hello, %s!\n", name)
}

Go-prompt

https://github.com/c-bata/go-prompt

For REPL-style interactivity, go-prompt offers advanced features such as tab completion, dynamic suggestions, and better rendering control. This is the library we ultimately selected because of its REPL-style interaction. (REPL means “Read-Eval-Print-Loop.”) We need REPL-style behavior to build a “wizard” interface that walks users through several steps. The library has its benefits and weak points — summarized below.

package mainimport (
"fmt"
"github.com/c-bata/go-prompt"
)
func completer(d prompt.Document) []prompt.Suggest {
suggestions := []prompt.Suggest{
{Text: "apple", Description: "A fruit"},
{Text: "banana", Description: "Another fruit"},
}
return prompt.FilterHasPrefix(suggestions, d.GetWordBeforeCursor(), true)
}
func main() {
fmt.Println("Please select a fruit:")
t := prompt.Input("> ", completer)
fmt.Printf("You selected %s\n", t)
}

Comparisons

In the following sections, we compare the packages. First, we show where each package excels and then where each could improve.

Where the Packages Excel

Here’s a list of the various capabilities and where each package excels. (Thanks Chat!)

Comparison of Strong Points for Each Package

This shows two points that ended up being part of our final consideration: REPL support and Interactive Multi-Line Input. (We need to build a wizard and allow users to copy a list of Ethereum addresses — one per line — into the wizard.) The lack of built-in validation concerns us, but the code must “handle” the user’s response anyway —so maybe that’s not a big deal.

survey: Multi-select support, built-in validation, simplicity.

prompt-ui: Polished templates, customizable prompts, and spinners for long-running tasks.

go-prompt: Tab completion, dynamic suggestions, advanced interactivity for REPLs.

Where the Packages are Weakest

The following table shows where the packages are weaker than they could be. (Again, thanks Chat!)

Relative Weaknesses for the Packages

promptui has a lot of red Xs. So does survey (and it’s also archived).

Three features stood out to us (all showing favor to go-prompt): Custom Rendering, REPL support, and Tab Completion — I don’t know about you, but tab completion is essential — at least to my mind.

survey: No tab completion, limited advanced features like REPL support.

prompt-ui: No multi-select support, lacks tab completion, limited for advanced CLIs.

go-prompt: No built-in validation, lacks multi-select, complex setup for simple CLIs.

Other Considerations

Here’s a final table comparing the three packages along less technical lines. Long-term support, community engagement, good documentation, etc., are also important when selecting a package.

Comparison on Less Technical Aspects of the Packages

(Again, we thank Chat. Thanks Chat!)

There’s not much to see here. All three packages are pretty equal on these terms; however, I think Chat made a mistake (Bad Chat!) The survey package recently announced that the repo would be archived. Other than that, they all have a lot of stars, a lot of forks, and active communities.

UpShot

In the end, our decision was rather simple. We chose go-prompt. Go-prompt met particular requirements that the other packages didn’t meet (REPL, customizability). This sealed the deal for us. Plus, we’ve used go-prompt before, so it’s familiar.

Thanks for reading. As always, the above works for us. Your mileage may vary. Have fun, and do check out Bubble Tea. It actually looks amaze-ballz.

Your Support is Welcome

TrueBlocks is funded from personal funds and grants from The Ethereum Foundation (2018, 2022, 2024), Optimism Retro PGF (2022, 2023), Moloch DAO (2021), Filecoin/IPFS (2021), Consensys (2019), and our lovely GitCoin donors.

If you like this article and wish to support our work, please donate to our GitCoin grant using ETH or any token. If you’re an Optimism badge holder, vote for our project in future Retro rounds. Or send us a tip directly at trueblocks.eth or 0xf503017d7baf7fbc0fff7492b751025c6a78179b.

--

--

Thomas Jay Rush
Thomas Jay Rush

Written by Thomas Jay Rush

Blockchain Enthusiast, Founder TrueBlocks, LLC and Philadelphia Ethereum Meetup, MS Computer Science UPenn

No responses yet