gocli

package module
v0.3.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 9, 2026 License: MIT Imports: 5 Imported by: 0

README

Test Status

gocli 🦦

A lightweight, dependency-free CLI framework for Go.

Overview

gocli provides a fluent interface that allows you to define commands, subcommands, and flags in a single, readable format, unlike standard flag parsing. It handles help menu generation, alias mapping, argument validation, error handling, and many other things right out of the box, allowing you to focus on your business logic.

Installation

go get github.com/7ched7/gocli@latest

Quick Start

package main

import (
	"fmt"
	"os"

	"github.com/7ched7/gocli"
)

func main() {
	// Create a new App instance
	app := gocli.NewApp("mycli").WithVersion("0.1.0")

	nameFlag := gocli.NewStringFlag("name").WithAlias("n")

	app.
		AddGlobalFlag(nameFlag).
		WithMinArg(1).
		WithMaxArg(1).
		Action(func(ctx *gocli.Context) {
			name := ctx.String("name")
			message := ctx.Args()[0]

			if name != "" {
				fmt.Printf("Hey %s! %s\n", name, message)
			} else {
				fmt.Printf("Hey Guest! %s\n", message)
			}

		})

	os.Exit(app.Run())
}

Execution Example

$ mycli -nJohn "How are you?"
Hey John! How are you?

Features

Commands & Subcommands

This framework lets you define standalone commands and organize them hierarchically using subcommands.

To create a new command, you can simply use the NewCommand method provided by the API.

serverCmd := gocli.NewCommand("server")

Once defined, register the command by passing it to the AddCommand method of the app instance.

app.AddCommand(serverCmd)

If your project requires nested commands, you can register the command object directly within a parent command object using the AddSubcommand method.

startCmd := gocli.NewCommand("start").
	Action(func(ctx *gocli.Context) {
		fmt.Println("Server is up and running!")
	})

serverCmd.AddSubcommand(startCmd)

If you don't want to mess around with variables, simply call the NewCommand method directly inside the AddCommand method. This is the another way also.

app.AddCommand(gocli.NewCommand("server"))

Execution Example

$ mycli server start 
Server is up and running!
Flags

Flags are created using type-specific helper methods and then registered on a command using the AddFlag method.

ipFlag := gocli.NewStringFlag("ip")
startCmd.AddFlag(ipFlag)

You can also add flags globally. Simply pass the flag object to the AddGlobalFlag method of the app instance. No matter which command you run, the global flags will always be available.

verboseFlag := gocli.NewBoolFlag("verbose")
app.AddGlobalFlag(verboseFlag)

In this framework, flags are accessed in two main ways:

Variable Binding

With variable binding, the flag value is automatically stored in a predefined variable. This is useful when you want simple and direct access to the value.

var ip string = "127.0.0.1"

ipFlag := gocli.NewStringFlagVar("ip", &ip).WithAlias("i")

startCmd.AddFlag(ipFlag).
	Action(func(ctx *gocli.Context) {
		fmt.Printf("IP address: %s\n", ip) // Direct access
	})
Dynamic Access via Context

Another approach is to retrieve the flag value from the Context during execution. This is more flexible than binding approach and can be used when multiple flags are involved.

portFlag := gocli.NewIntFlag("port").WithAlias("p")

startCmd.AddFlag(portFlag).
	Action(func(ctx *gocli.Context) {
		port := ctx.Int("port") // Get flag value from context
		fmt.Printf("IP address: %s\n", ip)
		fmt.Printf("Port: %d\n", port)
	})

Execution Example

$ mycli server start -i 127.0.0.2 -p 8000
IP address: 127.0.0.2
Port: 8000
Custom Validator

Flags may need to be validated to ensure they meet specific conditions. In such cases, you can use the WithValidator method on the flag object to validate the flag value just before the action is triggered.

portFlag.WithValidator(func(ctx *gocli.Context, value int) error {
	if value < 1 || value > 65535 {
		return fmt.Errorf("invalid port number: %d\n", value)
	}
	return nil
})

Execution Example

$ mycli server start -i 127.0.0.1 -p 80000
invalid port number: 80000

The Context object allows you to write more complex controls by providing access to other flag values.

ip := ctx.String("ip")

if ip == "127.0.0.1" && value == 8080 {
	return fmt.Errorf("port already in use: %s:%d\n", ip, value)
}

Execution Example

$ mycli server start -i 127.0.0.1 -p 8080
port already in use: 127.0.0.1:8080
Custom Types

This framework doesn’t support every type out of the box. Instead, it lets you define and integrate custom types by implementing the FlagValue interface, which closely mirrors Go’s standard flag.Value.

The first step is to wrap your desired data type within a struct. This struct acts as a container that the framework will interact with during the flag lifecycle.

type IP struct {
	value net.IP
}

The Set(string) method is the core of your custom type. The framework calls this method whenever it encounters your flag in the CLI. It is responsible for converting the raw string input into your internal data type.

func (i *IP) Set(value string) error {
	if ip := net.ParseIP(value); ip != nil {
		i.value = ip
		return nil
	}
	return fmt.Errorf("invalid IP address: %s\n", value)
}

To retrieve the processed data back, you need to implement the Get() method. This returns the underlying value as any type.

func (i *IP) Get() any { 
	return i.value 
}

The String() method is implemented to satisfy the Stringer interface. It represents either the current value or a hint about the expected format.

func (i *IP) String() string { 
	return i.value.String() 
}

Once your struct satisfies the FlagValue interface, you can integrate it into the flag using the NewCustomFlagVar method provided by the API. Simply create a typed variable and bind it.

var ip IP
ipFlag := gocli.NewCustomFlagVar("ip", &ip)

Execution Example

$ mycli server start -i 256.168.1.1
invalid IP address: 256.168.1.1
Custom Messages

One of the core features of this framework is its flexible message handling. You can override the default behavior for various CLI events to provide more user-friendly messages.

Simply specify one of the predefined events using the HandleMessage method and return the message you want to display.

app.HandleMessage(gocli.MsgUnknownCommand, func(msgCtx gocli.MessageContext) string {
	return "invalid command\n"
})

Execution Example

$ mycli servr
invalid command

The MessageContext object can be used to generate more advanced messages. You can access information about the event and other objects.

unkCommand := msgCtx.Msg().Data()["command"] // Access the entered invalid command
commands := msgCtx.App().Commands() // All registered commands in app instance

var sb strings.Builder

sb.WriteString("invalid command: ")
sb.WriteString(unkCommand)
sb.WriteString("\navailable commands:\n")

for _, cmd := range commands {
	sb.WriteString("- ")
	sb.WriteString(cmd.Name())
	sb.WriteString("\n")
}

return sb.String()

Execution Example

$ mycli servr
invalid command: servr
available commands:
- server

See the documentation for more information.

Documentation

Index

Constants

View Source
const (
	MsgHelp messageType = iota
	MsgCommandHelp
	MsgVersion
	MsgNoCommand
	MsgUnknownCommand
	MsgSubcommandRequired
	MsgInvalidFlag
	MsgFlagValueMissing
	MsgUnexpectedArgument
	MsgTooFewArguments
	MsgTooManyArguments
	MsgUnsupportedFlagType
)

Variables

This section is empty.

Functions

This section is empty.

Types

type App

type App struct {
	// contains filtered or unexported fields
}

App represents the main CLI application. It manages application commands, global flags, configurations, and I/O streams.

func NewApp added in v0.2.0

func NewApp(name string) *App

NewApp creates and returns a new App instance with the given name and default settings.

func (*App) Action added in v0.3.0

func (a *App) Action(fn func(ctx *Context)) *App

Action assigns the default action to be executed when the application is run without specifying any command.

func (*App) AddCommand added in v0.2.0

func (a *App) AddCommand(command *Command) *App

AddCommand registers a top-level command to the application.

func (*App) AddGlobalFlag added in v0.3.0

func (a *App) AddGlobalFlag(flag FlagInfo) *App

AddGlobalFlag registers a global flag to the application. Global flags apply to all commands.

func (*App) CommandHelp added in v0.2.0

func (a *App) CommandHelp(cmd *Command) string

CommandHelp generates and returns a help menu for a specific command. It includes the full command path, command description, registered subcommands and flags.

func (*App) Commands

func (a *App) Commands() []*Command

Commands returns all registered top-level commands.

func (*App) Description added in v0.2.0

func (a *App) Description() string

Description returns the description of the application.

func (*App) GlobalFlags added in v0.3.0

func (a *App) GlobalFlags() []FlagInfo

GlobalFlags returns all registered global flags.

func (*App) HandleMessage added in v0.2.0

func (a *App) HandleMessage(messageType messageType, fn func(msgCtx MessageContext) string) *App

HandleMessage registers a custom message handler for a specific message type. The handler function runs whenever an event of the given type occurs.

func (*App) Help added in v0.2.0

func (a *App) Help() string

Help generates and returns the global help menu for the application. It includes usage instructions, application description, registered commands and global flags.

func (*App) MaxArg added in v0.3.0

func (a *App) MaxArg() int

MaxArg returns the maximum number of positional arguments allowed for the application. If not set, it returns 0.

func (*App) MinArg added in v0.3.0

func (a *App) MinArg() int

MinArg returns the minimum number of positional arguments required by the application. If not set, it returns 0.

func (*App) Name

func (a *App) Name() string

Name returns the display name of the application.

func (*App) Run

func (a *App) Run() int

Run starts the application with os.Args. It is the main entry point when the CLI is executed.

func (*App) RunWithArgs

func (a *App) RunWithArgs(args []string) int

RunWithArgs starts the application with a custom set of arguments. It is useful for testing or integrating the CLI with another program.

func (*App) Stderr

func (a *App) Stderr() io.Writer

Stderr returns the output writer used for standard error. If nil, it falls back to os.Stderr.

func (*App) Stdout

func (a *App) Stdout() io.Writer

Stdout returns the output writer used for standard output. If nil, it falls back to os.Stdout.

func (*App) Version

func (a *App) Version() string

Version returns the version of the application.

func (*App) WithDescription added in v0.2.0

func (a *App) WithDescription(description string) *App

WithDescription sets the description for the application. The description is shown in application help menu.

func (*App) WithMaxArg added in v0.3.0

func (a *App) WithMaxArg(max int) *App

WithMaxArg sets the maximum number of positional arguments allowed for the application.

func (*App) WithMinArg added in v0.3.0

func (a *App) WithMinArg(min int) *App

WithMinArg sets the minimum number of positional arguments required by the application.

func (*App) WithStderr added in v0.2.0

func (a *App) WithStderr(err io.Writer) *App

WithStderr sets the writer used for error output.

func (*App) WithStdout added in v0.2.0

func (a *App) WithStdout(out io.Writer) *App

WithStdout sets the writer used for standard output.

func (*App) WithVersion added in v0.2.0

func (a *App) WithVersion(version string) *App

WithVersion sets the version for the application. This value is displayed when the version flag is used.

type CLIMessage added in v0.3.0

type CLIMessage struct {
	// contains filtered or unexported fields
}

CLIMessage represents a message object used by the CLI. It includes an exit code, message, message type, and optional command pointer, as well as extra metadata.

func (*CLIMessage) Code added in v0.3.0

func (m *CLIMessage) Code() int

Code returns the exit code associated with the event.

func (*CLIMessage) Command added in v0.3.0

func (m *CLIMessage) Command() *Command

Command returns the command where the event occured.

func (*CLIMessage) Data added in v0.3.0

func (m *CLIMessage) Data() map[string]string

Data returns a map of metadata related to the event.

func (*CLIMessage) Message added in v0.3.0

func (m *CLIMessage) Message() string

Message returns the message of the event.

func (*CLIMessage) MessageType added in v0.3.0

func (m *CLIMessage) MessageType() messageType

MessageType returns the categorized type of the event.

type Command

type Command struct {
	// contains filtered or unexported fields
}

Command represents a single CLI command. It includes command name, alias, descriptions, subcommands, flags, argument constraints, and an action function called when the command is run.

func NewCommand added in v0.3.0

func NewCommand(name string) *Command

NewCommand creates a new command with the given name.

func (*Command) Action added in v0.2.0

func (c *Command) Action(fn func(ctx *Context)) *Command

Action assigns the function to be executed when the command is run. The handler receives a Context containing positional arguments and parsed flags.

func (*Command) AddFlag added in v0.2.0

func (c *Command) AddFlag(flag FlagInfo) *Command

AddFlag registers a flag to the command.

func (*Command) AddSubcommand added in v0.2.0

func (c *Command) AddSubcommand(subcommand *Command) *Command

AddSubcommand registers a subcommand to the current command.

func (*Command) Alias

func (c *Command) Alias() string

Alias returns the alias of the command. If not set, it returns an empty string.

func (*Command) Flags added in v0.2.0

func (c *Command) Flags() []FlagInfo

Flags returns the list of flags registered for the command.

func (*Command) Long

func (c *Command) Long() string

Long returns the long description of the command. If not set, it returns an empty string.

func (*Command) MaxArg

func (c *Command) MaxArg() int

MaxArg returns the maximum number of positional arguments allowed for the command. If not set, it returns 0.

func (*Command) MinArg

func (c *Command) MinArg() int

MinArg returns the minimum number of positional arguments required by the command. If not set, it returns 0.

func (*Command) Name

func (c *Command) Name() string

Name returns the name of the command.

func (*Command) Parent added in v0.2.0

func (c *Command) Parent() *Command

Parent returns the parent command in the hierarchy. If the command has no parent command, it returns nil.

func (*Command) Short

func (c *Command) Short() string

Short returns the short description of the command. If not set, it returns an empty string.

func (*Command) Subcommands added in v0.2.0

func (c *Command) Subcommands() []*Command

Subcommands returns all subcommands registered under the command.

func (*Command) WithAlias added in v0.2.0

func (c *Command) WithAlias(alias string) *Command

WithAlias sets the short alias for the command. Alias provides alternative way for users to run the command.

func (*Command) WithLong added in v0.2.0

func (c *Command) WithLong(long string) *Command

WithLong sets the detailed description for the command. This is shown in command help menu.

func (*Command) WithMaxArg added in v0.2.0

func (c *Command) WithMaxArg(max int) *Command

WithMaxArg sets the maximum number of positional arguments allowed for the command.

func (*Command) WithMinArg added in v0.2.0

func (c *Command) WithMinArg(min int) *Command

WithMinArg sets the minimum number of positional arguments required by the command.

func (*Command) WithShort added in v0.2.0

func (c *Command) WithShort(short string) *Command

WithShort sets the short description for the command. This is shown in commands section within help menu.

type Context added in v0.3.0

type Context struct {
	// contains filtered or unexported fields
}

Context holds positional arguments and parsed flags for a command execution.

func (*Context) App added in v0.3.0

func (c *Context) App() *App

App returns the application instance.

func (*Context) Args added in v0.3.0

func (c *Context) Args() []string

Args returns the positional arguments passed to the command.

func (*Context) Bool added in v0.3.0

func (c *Context) Bool(name string) bool

Bool returns the named flag as bool. It panics if not found or invalid type.

func (*Context) Command added in v0.3.0

func (c *Context) Command() *Command

Command returns the executed command.

func (*Context) Flags added in v0.3.0

func (c *Context) Flags() map[string]FlagValue

Flags returns all parsed flags as key-value pairs.

func (*Context) Float64 added in v0.3.0

func (c *Context) Float64(name string) float64

Float64 returns the named flag as float64. It panics if not found or invalid type.

func (*Context) Int added in v0.3.0

func (c *Context) Int(name string) int

Int returns the named flag as int. It panics if not found or invalid type.

func (*Context) Lookup added in v0.3.0

func (c *Context) Lookup(name string) FlagValue

Lookup returns the FlagValue interface of the flag with the given name.

func (*Context) String added in v0.3.0

func (c *Context) String(name string) string

String returns the named flag as string. It panics if not found or invalid type.

func (*Context) StringSlice added in v0.3.0

func (c *Context) StringSlice(name string) []string

StringSlice returns the named flag as []string. It panics if not found or invalid type.

type Flag added in v0.2.0

type Flag[T any] struct {
	// contains filtered or unexported fields
}

Flag represents a single flag for the CLI. It includes flag name, alias, parsed value, description, metavariable, and an optional validator function.

func NewBoolFlag added in v0.3.0

func NewBoolFlag(name string) *Flag[bool]

NewBoolFlag creates a new bool flag with the given name.

func NewBoolFlagVar added in v0.3.0

func NewBoolFlagVar(name string, variable *bool) *Flag[bool]

NewBoolFlagVar creates a new bool flag using the provided variable.

func NewCustomFlagVar added in v0.3.0

func NewCustomFlagVar(name string, variable FlagValue) *Flag[FlagValue]

NewCustomFlagVar creates a new flag using custom FlagValue implementations.

func NewFloatFlag added in v0.3.0

func NewFloatFlag(name string) *Flag[float64]

NewFloatFlag creates a new float64 flag with the given name.

func NewFloatFlagVar added in v0.3.0

func NewFloatFlagVar(name string, variable *float64) *Flag[float64]

NewFloatFlagVar creates a new float64 flag using the provided variable.

func NewIntFlag added in v0.3.0

func NewIntFlag(name string) *Flag[int]

NewIntFlag creates a new int flag with the given name.

func NewIntFlagVar added in v0.3.0

func NewIntFlagVar(name string, variable *int) *Flag[int]

NewIntFlagVar creates a new int flag using the provided variable.

func NewStringFlag added in v0.3.0

func NewStringFlag(name string) *Flag[string]

NewStringFlag creates a new string flag with the given name.

func NewStringFlagVar added in v0.3.0

func NewStringFlagVar(name string, variable *string) *Flag[string]

NewStringFlagVar creates a new string flag using the provided variable.

func NewStringSliceFlag added in v0.3.0

func NewStringSliceFlag(name string) *Flag[[]string]

NewStringSliceFlag creates a new string slice flag with the given name.

func NewStringSliceFlagVar added in v0.3.0

func NewStringSliceFlagVar(name string, variable *[]string) *Flag[[]string]

NewStringSliceFlagVar creates a new string slice flag using the provided variable.

func (*Flag[T]) Alias added in v0.2.0

func (f *Flag[T]) Alias() string

Alias returns the alias of the flag. If not set, it returns an empty string.

func (*Flag[T]) Description added in v0.2.0

func (f *Flag[T]) Description() string

Description returns the description of the flag. If not set, it returns an empty string.

func (*Flag[T]) Metavar added in v0.3.0

func (f *Flag[T]) Metavar() string

Metavar returns the metavariable of the flag.

func (*Flag[T]) Name added in v0.2.0

func (f *Flag[T]) Name() string

Name returns the name of the flag.

func (*Flag[T]) Validate added in v0.3.0

func (f *Flag[T]) Validate(ctx *Context) error

Validate runs the flag validator function, if set.

func (*Flag[T]) Value added in v0.3.0

func (f *Flag[T]) Value() FlagValue

Value returns the value of the flag.

func (*Flag[T]) WithAlias added in v0.3.0

func (f *Flag[T]) WithAlias(alias string) *Flag[T]

WithAlias sets the alias for the flag.

func (*Flag[T]) WithDescription added in v0.3.0

func (f *Flag[T]) WithDescription(description string) *Flag[T]

WithDescription sets the description for the flag. This is shown in flags section within help menu.

func (*Flag[T]) WithMetavar added in v0.3.0

func (f *Flag[T]) WithMetavar(metavar string) *Flag[T]

WithMetavar sets the metavariable for the flag. This is shown next to the flag and indicates the type of the flag value.

func (*Flag[T]) WithValidator added in v0.3.0

func (f *Flag[T]) WithValidator(fn func(ctx *Context, value T) error) *Flag[T]

WithValidator registers a validation function for the flag.

type FlagInfo added in v0.3.0

type FlagInfo interface {
	Name() string                // Name returns the name of the flag.
	Alias() string               // Alias returns the optional alias of the flag.
	Value() FlagValue            // Value returns the parsed value of the flag.
	Description() string         // Description returns the description of the flag.
	Metavar() string             // Metavar returns the metavariable of the flag.
	Validate(ctx *Context) error // Validate runs the flag validator function, if set.
}

FlagInfo provides access to flag metadata and behaviour.

type FlagValue added in v0.3.0

type FlagValue interface {
	Set(value string) error // Set parses and assigns the given string to the underlying typed value.
	Get() any               // Get returns the underlying typed value.
	String() string         // String returns the string representation of the value.
}

FlagValue defines an interface for all flag values.

type MessageContext added in v0.3.0

type MessageContext struct {
	// contains filtered or unexported fields
}

MessageContext holds the application instance and message object providing details about the event.

func (*MessageContext) App added in v0.3.0

func (m *MessageContext) App() *App

App returns the application instance.

func (*MessageContext) Msg added in v0.3.0

func (m *MessageContext) Msg() *CLIMessage

Msg returns the message object providing details about the event.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL