agentsclimarketplace

Go cli

Skill Tanq16/claudex/skills/go-cli

Use when implementing CLI commands with Cobra - covers root command setup, subcommand patterns, flags, output lifecycle patterns, and TUI output with bubbletea/lipglossFrom its SKILL.md

Install
npx -y skills add Tanq16/claudex --skill go-cli

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

9.9 KB, ~2.5k tokens by cl100k_base, as published. Nobody here has run it

Go CLI

Cobra command patterns and terminal UI for CLI tools.

When to Use

Use this skill when:

  • Setting up Cobra root command
  • Adding new commands or subcommands
  • Implementing CLI flags
  • Showing sequential progress with running/done lifecycle (phases, single-ops, checks)
  • Creating terminal UI output
  • Adding --debug or --for-ai flag behavior

Requires: go-foundations for project layout and utils package.

Start here — required reading

Read the Always file now, in full, before writing command output — it carries the output-lifecycle rules you'll be held to. Read the When file before the sub-task it names; a subagent may read it if you delegate that work.

Always:

  • ./references/output-lifecycle-patterns.md — phase/single-op/check/progress patterns every command follows

When scaffolding main.go, cmd/root.go, a command, a subcommand package, or cmd/login.go:

  • ./references/command-templates.md — full code for those files plus the lipgloss color palette

Project Type Context

CLI Only and Web Only projects have different root command setups (CLI + Web hybrids use the CLI Only setup, plus a serve command):

AspectCLI OnlyWeb Only
Root commandFull: zerolog, utils, --debug, --for-ai, setupLogsSimplified: just rootCmd, Execute(), init() with AddCommand
Loggingzerolog via setupLogs()Standard log package (no setupLogs)
Flags--debug and --for-ai global flagsNo debug/for-ai flags
UtilsFull utils/ package importedNO utils import — use log.Printf/log.Fatalf
OutputThree-tier: debug/AI/human via utils.Print*log.Printf with manual prefixes

Root Command Setup

main.go only calls cmd.Execute(). The root command differs by project type:

CLI OnlyWeb Only
Importszerolog, utils, subcommand pkgscobra + subcommand pkgs only
Flags--debug, --for-ai (mutually exclusive)none
LoggingsetupLogs() configures zerolog; --debug/--for-ai toggle levels and utils.Global*Flagstandard log, no setup
init()hides help/completion, registers flags, cobra.OnInitialize(setupLogs), adds commandshides help/completion, adds commands

Both set Use, Short, Version (from AppVersion ldflag), and HiddenDefaultCmd: true. Full main.go and both cmd/root.go templates are in ./references/command-templates.md.

Command Patterns

  • Simple command (no subcommands): define directly in cmd/ with its own flag struct and init(). CLI Only (and a hybrid's CLI subcommands) use u.Print*/u.PrintFatal; Web Only (and a hybrid's serve/server) uses log.Printf/log.Fatalf.
  • Subcommand group: create a package under cmd/ (e.g. cmd/feature-cmd/) with an exported parent command (no Run) and unexported subcommands (each with Run). Wire them in the package's init().

Full serve and subcommand-package templates are in ./references/command-templates.md.

Flag Patterns

Flag Types

// String with short flag
cmd.Flags().StringVarP(&flags.name, "name", "n", "default", "Description")

// Int with short flag
cmd.Flags().IntVarP(&flags.count, "count", "c", 10, "Number of items")

// Bool with short flag
cmd.Flags().BoolVarP(&flags.all, "all", "a", false, "Include all items")

// String slice
cmd.Flags().StringSliceVarP(&flags.tags, "tag", "t", []string{}, "Tags (can specify multiple)")

// Duration
cmd.Flags().DurationVarP(&flags.timeout, "timeout", "T", 30*time.Second, "Request timeout")

Required Flags

cmd.Flags().StringVarP(&flags.input, "input", "i", "", "Input file (required)")
cmd.MarkFlagRequired("input")

Environment Variable Defaults

// Read env var as default value
defaultToken := os.Getenv("GITHUB_TOKEN")
cmd.Flags().StringVarP(&flags.token, "token", "t", defaultToken, "GitHub token (or GITHUB_TOKEN env)")

Mutually Exclusive Flags

cmd.MarkFlagsMutuallyExclusive("file", "stdin")

Run Function Pattern (CLI Only)

Run: func(cmd *cobra.Command, args []string) {
    // 1. Validate flags
    if flags.required == "" {
        u.PrintFatal("--required flag is required", nil)
    }

    // 2. Build config struct
    cfg := internal.Config{
        Field1: flags.field1,
        Field2: flags.field2,
    }

    // 3. Call internal package
    result, err := internal.DoThing(cfg)
    if err != nil {
        u.PrintFatal("Failed to do thing", err)
    }

    // 4. Output result
    u.PrintSuccess("Thing completed")
    u.PrintGeneric(result)
}

Login Command Pattern (CLI Only)

For CLI tools with OAuth authentication, the login command uses mutually exclusive flags (--device-login, --manual) to select the login mode. The auth logic lives in internal/auth/ (see go-backend); the command just maps flags to a mode string, calls auth.Login(config, mode), and handles output.

Modes:

  • appname login — default, opens browser with localhost callback
  • appname login --device-login — shows URL + code for headless/SSH
  • appname login --manual — paste authorization code (last resort when device flow unsupported)

If the provider does not support device authorization (RFC 8628), omit --device-login. Full cmd/login.go template is in ./references/command-templates.md.

Output Lifecycle Patterns (CLI Only)

For sequential operations that need running/done progress, line clearing, and phase grouping. This is the simple counterpart to the Highway pattern (used for concurrent multi-job pipelines).

Four lifecycle types:

LifecycleWhenPattern
PhaseGroup of sequential sub-tasksRunning header → indented results → clear → summary
Single-operationOne task, no sub-stepsRunning → clear → result
Multi-stepMultiple sequential stepsRunning → clear → running → clear → ... → final result
CheckRead-only scan of multiple itemsRunning → clear → summary with indented findings

Key functions: PrintRunning, PrintIndented{Success,Error,Warn,Running}, ClearLines(n), ClearPreviousLine(), PrintProgress(label, percent).

ClearLines count rule: Always ClearLines(lineCount + 1)+1 for the running header.

Progress bar: Goroutine-driven braille-dot bar that overwrites a single line. Use atomic.Bool to guard the final clear (prevents eating the wrong line if work completes before first tick).

See ./references/output-lifecycle-patterns.md for full patterns and examples.

TUI Patterns (Bubbletea + Lipgloss) (CLI Only)

Terminal Colors (Lipgloss)

Use ANSI standard color indices (0-15) instead of hardcoded hex values. These indices are remapped by the user's terminal theme, so output adapts to Dracula, Catppuccin, Solarized, or any custom scheme automatically. Hardcoded hex colors (e.g. #89b4fa) bypass the theme and force a specific palette regardless of user preference. Prefer bright variants (8-15) for foreground text.

The full lipgloss.ANSIColor palette and common style definitions are in ./references/command-templates.md (Terminal Colors section).

Selection Prompts

For interactive choices, reuse the utils selector helpers rather than hand-rolling a bubbletea model per command:

  • PromptSelect(label, options) (int, error) — single-choice list; arrow / j / k to move, enter to pick, esc / ctrl+c to cancel. Returns the chosen index, or -1 when cancelled.
  • PromptMultiSelect(label, options) (map[int]bool, error) — multi-choice list; space toggles, enter confirms. Returns the selected indices, or nil when cancelled.

Both branch on --for-ai: instead of a TUI they read a line from stdin — a 1-based index for PromptSelect, and a comma-separated list of indices (or none) for PromptMultiSelect — so choices stay scriptable (echo "2" | tool cmd --for-ai). Always treat the cancel path (idx < 0 / nil map) as a clean no-op abort.

Output Tier Behavior (CLI Only)

--debug and --for-ai are mutually exclusive (enforced via MarkFlagsMutuallyExclusive).

When neither flag is set (human mode):

  • utils.Print* functions render styled ANSI output via lipgloss
  • Tables render with box-drawing borders
  • Input prompts launch bubbletea TUI

When --debug is set:

  • utils.GlobalDebugFlag = true
  • Print functions route to zerolog with timestamps and full error details
  • zerolog level set to DebugLevel

When --for-ai is set:

  • utils.GlobalForAIFlag = true
  • zerolog disabled (zerolog.Disabled) to prevent stray log output
  • See "AI Mode Behavior" below for details

AI Mode Behavior (--for-ai) (CLI Only)

The --for-ai global flag enables AI-agent-friendly I/O. When set:

Output changes:

  • Print functions emit prefixed plain text instead of styled ANSI:
    • [OK] (success), [ERROR] (error/fatal), [WARN] (warning), [INFO] (info)
  • Tables render as markdown (| col | col |) instead of lipgloss box-drawing
  • No spinners, no color codes, no interactive TUI elements

Input changes:

  • PromptInput() and PromptPassword() read from stdin pipe via ReadPipedInput()
  • No bubbletea TUI launched — enables echo "data" | toolname cmd --for-ai

Note: --debug and --for-ai are mutually exclusive — Cobra enforces this at the flag level.

See go-foundations for the three-tier utils implementation.

References

FileTypePurpose
./references/command-templates.mdTemplateFull code: main.go, both cmd/root.go variants, simple commands, subcommand package, cmd/login.go, and lipgloss colors/styles
./references/output-lifecycle-patterns.mdPatternPhase, single-op, multi-step, check, and progress indicator lifecycle patterns with code examples

What ships with it: 2 files

19.1 KB alongside SKILL.md

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.