A template for new Go CLI projects
| cmd | feat: Refactor build, update module path, and dependencies | |
| internal | feat: Refactor build, update module path, and dependencies | |
| pkg | feat: Refactor build, update module path, and dependencies | |
| .envrc.example | initial commit | |
| .gitignore | initial commit | |
| go.mod | update go | |
| go.sum | update go | |
| justfile | update go | |
| main.go | feat: Refactor build, update module path, and dependencies | |
| PROJECT_SUMMARY.md | feat: Refactor build, update module path, and dependencies | |
| README.md | feat: Refactor build, update module path, and dependencies | |
| TEMPLATE_GUIDE.md | feat: Refactor build, update module path, and dependencies | |
Go CLI Application Template
This is a template for creating Go CLI applications based on the gndb project structure (commit be23ee4).
Features
- Configuration Management: Viper-based config with precedence: CLI flags > env vars > config.yaml > defaults
- Structured Logging: slog-based JSON logging with configurable levels and destinations
- XDG-Compliant Directories: Automatic creation of config, cache, and log directories
- Cobra CLI Framework: Professional command-line interface with subcommands
- Functional Options Pattern: Clean, type-safe configuration updates
Project Structure
.
├── cmd/ # CLI commands
│ ├── root.go # Root command with bootstrap logic
│ └── example.go # Example subcommand
├── internal/ # Internal packages (not importable)
│ ├── iofs/ # Filesystem operations
│ │ ├── iofs.go # Directory/file creation
│ │ ├── config.yaml # Embedded config template
│ │ └── errors.go # Error definitions
│ └── iologger/ # Logging initialization
│ ├── logger.go # Logger setup
│ └── errors.go # Error definitions
├── pkg/ # Public API packages
│ ├── config/ # Configuration management
│ │ ├── config.go # Config struct and defaults
│ │ ├── options.go # Option functions
│ │ └── vars.go # Directory paths
│ └── version.go # Version info
├── main.go # Application entry point
├── go.mod # Go module definition
└── README.md # This file
Getting Started
1. Customize the Template
Replace all instances of placeholder names:
# In all files, replace:
# - example.org/yourorg/appname → your module path
# - appname → your application name
# - APPNAME → your env var prefix
# - "Your Name" → your name
# - your.email@example.com → your email
# Quick find/replace:
find . -type f -name "*.go" -o -name "*.mod" -o -name "*.yaml" | \
xargs sed -i 's/yourname\/appname/yourorg\/yourapp/g'
find . -type f -name "*.go" -o -name "*.mod" -o -name "*.yaml" | \
xargs sed -i 's/appname/yourapp/g'
find . -type f -name "*.go" | \
xargs sed -i 's/APPNAME/YOURAPP/g'
2. Install Dependencies
go mod tidy
3. Build and Run
# Build
go build -o bin/appname
# Run
./bin/appname --help
./bin/appname example
./bin/appname example --message "Hello!"
Configuration
The application uses XDG-compliant directories:
- Config:
~/.config/appname/config.yaml - Logs:
~/.local/share/appname/logs/appname.log - Cache:
~/.cache/appname/
Configuration Precedence
- CLI flags (highest priority)
- Environment variables (
APPNAME_*) - Config file (
~/.config/appname/config.yaml) - Built-in defaults (lowest priority)
Environment Variables
export APPNAME_LOG_LEVEL=debug
export APPNAME_LOG_FORMAT=text
export APPNAME_LOG_DESTINATION=stdout
export APPNAME_JOBS_NUMBER=4
Adding New Commands
- Create a new file in
cmd/(e.g.,cmd/mycommand.go) - Define a
getMyCommandCmd()function that returns*cobra.Command - Add it to root:
rootCmd.AddCommand(getMyCommandCmd())
Example:
packagecmdimport("github.com/gnames/gn""github.com/spf13/cobra")funcgetMyCommandCmd()*cobra.Command{return&cobra.Command{Use:"mycommand",Short:"Description of mycommand",RunE:func(cmd*cobra.Command,args[]string)error{gn.Info("Running mycommand")returnnil},}}Adding Configuration Fields
- Add field to
Configstruct inpkg/config/config.go - Create
Opt*function inpkg/config/options.go - Add to
ToOptions()if it should be persisted to config.yaml - Bind environment variable in
cmd/root.goinitEnvVars() - Update
internal/iofs/config.yamltemplate
Testing
# Run tests
go test ./...
# Run with coverage
go test -cover ./...
License
MIT License - See LICENSE file for details