Building a CLI Tool in Go: Part 2 - Commands & Config

SERIES · BUILDING A CLI TOOL IN GO
2 / 3 View series

In Part 1, we set up the skeleton. Now let’s give it bones.

We’ll add a scan command that reads a config file and does something marginally useful.

Adding a Subcommand

// cmd/scan.go
package cmd

import (
	"fmt"

	"github.com/spf13/cobra"
	"github.com/spf13/viper"
)

var scanCmd = &cobra.Command{
	Use:   "scan [path]",
	Short: "Scan a directory for issues",
	Args:  cobra.ExactArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		path := args[0]
		verbose, _ := cmd.Flags().GetBool("verbose")

		if verbose {
			fmt.Printf("Scanning %s with config: %s\n", path, viper.ConfigFileUsed())
		}

		return runScan(path)
	},
}

func init() {
	scanCmd.Flags().BoolP("verbose", "v", false, "enable verbose output")
	rootCmd.AddCommand(scanCmd)
}

Configuration with Viper

Viper gives us config file support, environment variable binding, and flag overrides — all with zero drama:

// cmd/config.go
package cmd

import (
	"github.com/spf13/viper"
)

func initConfig() {
	viper.SetConfigName(".ddd")
	viper.SetConfigType("yaml")
	viper.AddConfigPath(".")
	viper.AddConfigPath("$HOME")
	viper.AutomaticEnv()
	viper.SetEnvPrefix("DDD")

	_ = viper.ReadInConfig()
}
# .ddd.yaml
scan:
  exclude:
    - vendor/
    - .git/
  max_depth: 10
output:
  format: "json"
  color: true

Testing Commands

// cmd/scan_test.go
package cmd

import (
	"bytes"
	"testing"
)

func TestScanCommand(t *testing.T) {
	buf := new(bytes.Buffer)
	rootCmd.SetOut(buf)
	rootCmd.SetArgs([]string{"scan", ".", "--verbose"})

	if err := rootCmd.Execute(); err != nil {
		t.Fatalf("unexpected error: %v", err)
	}
}

Up Next

In Part 3, we’ll add proper integration tests and set up GoReleaser for automated releases.

fparch/ddd-cli View the complete source on GitHub

Building internal tools or developer platforms? I help teams ship faster. fitzpatricksoftware.com

I help teams modernize legacy systems with AI-assisted development guardrails that keep the agents productive and the production safe. fitzpatricksoftware.com