CLIs Made Simple : Guide to writing a beautiful CLI in GoLang
Tags: tutorials, go, cli, codenewbie
Published: 2021-08-20 14:16:28

---
title: CLIs Made Simple : Guide to writing a beautiful CLI in GoLang
published: true
date: 2021-08-20 14:05:22 UTC
tags: tutorials,golang,cli,codenewbie
canonical_url: https://shanmukhsista.com/cli-made-simple-guide-to-writing-a-cli-in-golang/
---

Over the last few years, i've been fascinated by the type of Applications and services one could write in Go. Using GoLang I've implemented RPC Services, REST APIs, Web UIs and Cloud Functions using extremely simple programming paradigms. The main reason i enjoy GoLang is the simplicity it has to offer. At the same time, it's extremely powerful to write a wide variety of applications. It is known to be a systems language, but it's not limited in any way.

In this article, i'll guide you through a simple CLI app that can be written in less than 30 minutes in GoLang. Before we dive deeper, here are the requirements to work on this.

1. GoLang  ( 1.16 -[https://golang.org/doc/install](https://golang.org/doc/install) ) 
2. Text Editor ( [https://code.visualstudio.com/](https://code.visualstudio.com/) ) 

This guide doesn't go in the details of Coding in GoLang. It gives a high level overview of implementing a CLI as a starting point to your application.

## Create a New Project

This is the first step for our application. To setup a new project, create a new folder on your system. Execute the commands below to get started.

```
mkdir cliapp
# Create a Go Project.
go mod init github.com/shanmukhsista/cliapp
```

This creates a new Go Project. A file named `go.mod` should be created after this.

We'll be using Cobra ( https://github.com/spf13/cobra ) to create our CLI. Another awesome library that helps with this whole process, and provides a lot of capabilities out of the box ( help text, cli argument parsing ...  )

Run the following command to add Cobra as a Dependency.

```
go get -u github.com/spf13/cobra
```

## Initialize Cobra CLI Project

```
cobra init --pkg-name github.com/shanmukhsista/cliapp
Your Cobra applicaton is ready at ...
```

![](https://shanmukhsista.com/content/images/2021/08/cli-folder-structure.png)

Upon successful execution, your folder structure should look like the image shown above. Below is a summary of these files.

- `main.go` - This is the entry point for our app. Any initialization before the CLI runs can be done within this file. 
- `cmd` Folder - This folder contains all the commands, and sub commands as separate go files. Try executing the following command, and see how the folder structure changes. 

```
# Add a root command 
cobra add setup
# Add a child command to the root command.
cobra add tests -p setupCmd
```

### Time to Test our app!

So far, our application doesn't have any specific logic. Let's build the app and see how our CLI looks like at this point. Run the following command to build and run.

```
# Build our app with 
go build -o cliapp main.go
./cliapp

$ ./cliapp
A longer description that spans multiple lines and likely contains
examples and usage of using your application. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.

Usage:
  cliapp [command]

Available Commands:
  completion generate the autocompletion script for the specified shell
  help Help about any command
  setup A brief description of your command

Flags:
      --config string config file (default is $HOME/.cliapp.yaml)
  -h, --help help for cliapp
  -t, --toggle Help message for toggle

Use "cliapp [command] --help" for more information about a command.
```

This is the output that is generated by Cobra when your command is executed. Notice that the setup command is generated as a top level command. Try executing another command

```
./cliapp setup -h
A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.

Usage:
  cliapp setup [flags]
  cliapp setup [command]

Available Commands:
  tests A brief description of your command

Flags:
  -h, --help help for setup
```

## Add Some Logic And Parameters

Until now, our application doesn't really do anything. Cobra gives  specific starting points where code can be written and application logic can be executed.

Let's write some code within the setup method.

It can be seen that all of the commands have their own files within the `cmd` folder. To write some logic to the `setup` command, try opening the file `cmd/setup.go` and add code within the ( `Run: func(cmd *cobra.Command, args []string)` block :

```
// setupCmd represents the setup command
var setupCmd = &cobra.Command{
	Use: "setup",
	Short: "A brief description of your command",
	Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
	Run: func(cmd *cobra.Command, args []string) {
		
        // Add any custom code here.
        // This gets executed whenever this command is called.
        
        fmt.Println("setup called")
	},
}
```

This is where all the logic can go. In a production setting, this can act as an entry point to the package where the actual logic exists.

### Parameters

Practically speaking, every CLI app takes in one or more than one command line argument. Let's try to add one to our setup method. In this case, let's take an argument `--app-name` as our argument. We'll print out this when our command executes.

Define a new variable in `cmd/setup.go`

```

import (
	"fmt"

	"github.com/spf13/cobra"
)

var AppName string // Store App Name Argument
```

The goal here is to parse `--app-name` argument, and automatically assign it to the variable defined above. To do so, add the following command to the init method.

```

func init() {
	rootCmd.AddCommand(setupCmd)
	// Define a new flag for App Name
	setupCmd.Flags().StringVarP(&AppName, "app-name", "a", "", "App Name")
	
}

```

Now use this variable in the actual execution logic. In this case, we print the app name within the Run Method.

```
Run: func(cmd *cobra.Command, args []string) {
		
        // Add any custom code here.
        // This gets executed whenever this command is called.
        
        fmt.Println("setup called with app name " + AppName)
	},
```

Build and run the program to view App Name printed on the screen.

```
go build -o cliapp main.go
./cliapp setup --app-name "New CLI App"
setup called with app name New CLI App
```

This process can be repeated for any number of arguments, commands, and child commands. Cobra really simplifies a building CLIs to enable some powerful applications that can run in any environment. Built executables can be copied and run on any target system without any underlying VM / service.