stack.menu

Go CLI + TUI

Command-line applications and terminal interfaces distributed as binaries.

Cobra · Bubble Tea when needed · GoReleaser

Complete guide (Markdown) · Structured record (JSON)

Original source review: 2026-10-10. Core guidance rechecked: 2026-10-13. Check scope. Dependency combinations and setup need project-specific qualification.

Use cases

Choose it when

Consider another path when

Working practices

Tools by job

Command parsing: Cobra

Command/help/completion structure plus event-driven terminal UI.

Keep noninteractive and machine-readable modes; test TTY absence, cancellation and terminal restoration.

Terminal UI: Bubble Tea only for interactive screens

Command/help/completion structure plus event-driven terminal UI.

Keep noninteractive and machine-readable modes; test TTY absence, cancellation and terminal restoration.

HTTP client: net/http Client

Standard client with contexts and transport reuse.

Set timeouts, bound responses and close bodies; retry only when operation semantics allow.

Persistence and migrations: None for stateless tools

Avoid introducing a database into a command wrapper.

Local durable state requires a separately selected storage/schema policy; never assume flat-file writes are atomic.

Configuration: Typed settings loaded with os.LookupEnv

Explicit startup validation and standard structured logs.

Define precedence; reject malformed required values; redact secrets. Environment access alone is not validation or secret management.

Application logging: log/slog

Explicit startup validation and standard structured logs.

Define precedence; reject malformed required values; redact secrets. Environment access alone is not validation or secret management.

Tests and static checks: testing; go vet; race detector; govulncheck

Standard toolchain feedback plus exercised concurrency and known-vulnerability checks.

Race detector requires supported target/toolchain and exercised code; no scanner proves absence of vulnerabilities.

Durable work: Delegate long jobs to a service; persist its job ID

Work survives the terminal process only through an explicit durable owner.

A goroutine or TUI background command dies with the process; reconnection needs a stable job identity.

Distribution: GoReleaser

Target builds and release artifact automation.

Review generated release actions, supported targets, signing and updater policy. cgo can complicate cross-building.

Machine-readable output: encoding/json/v2 on a supporting pinned Go toolchain

Stable JSON output lets scripts consume commands without parsing terminal text

Add an explicit --json/output mode and document schema/exit codes; reserve stdout for results, stderr for diagnostics, and disable interactive/color output for pipelines. Confirm API availability on the pinned Go version; v2 changes encoding/decoding defaults, so test schema/null/omission compatibility before migrating.

Cancellation and shutdown: signal.NotifyContext

User interrupts should cancel outbound work and leave terminal/files usable

Propagate cancellation through work; bound cleanup time and test interrupts during writes. Avoid adding an async runtime to a synchronous Rust CLI solely for signals.

Build with the stack’s strengths

Architecture and developer workflow.

Recommendation: keep the command tree as an adapter over testable application functions. A noninteractive command is a versioned automation interface; a Bubble Tea view is an optional interactive client of the same functions. The executable owns stream, exit-status, cancellation and configuration contracts.

Version scope: Go 1.27 toolchain documentation, Cobra/pflag current guide, Bubble Tea upstream API and GoReleaser v2 documentation. Pin compatible module/tool versions; Bubble Tea major/module-path changes need explicit review. No release matrix was built. · Reviewed 2026-10-11

Architecture boundaries

Tools and feedback

Translations to avoid

For an existing application

Keep the contracts while you change the stack.

These are documented options and proposed checks. Inspect the actual source application before adopting a transition.

CLI and pipe contracts

Inspect the source

Capture scripts consuming current flags, positional arguments, stdout/stderr, exit codes and completion output.

During coexistence

Recommendation: retain old subcommands/aliases as thin adapters while introducing an explicit JSON mode. Mark renamed flags deprecated through Cobra instead of silently changing their meaning.

Target design

Recommendation: Cobra RunE plus centralized result/error mapping; versioned JSON on stdout and diagnostics on stderr. Freeze documented application codes for success, usage and operational failure.

Rollback

Recommendation: install the preceding binary and continue serving the old protocol. Keep newly introduced machine schemas behind explicit versions so callers can choose a compatible response.

Benefits and prerequisites

A stable CLI protocol permits automation and humans to share one executable.
Requires: Consumer fixtures cover streams/status; formatting and error categories are explicit; deprecation schedule preserves callers.
Tradeoffs: Versioned output requires ongoing compatibility ownership; usage errors and remote failures may need different handling.

Checks before transfer

  • Run old calling scripts against the new binary and compare all three output channels.
  • Verify invalid flags perform no effects and produce the documented exit code.
  • Pipe JSON to a parser; help/progress/logging must not contaminate its data.
Data and schema

Inspect the source

Inventory config paths, default values, flag/environment precedence, secret fields and old readers.

During coexistence

Recommendation: parse both old and versioned schemas through adapters; display migration diagnostics on stderr and offer an explicit migration command with backup. Keep the old file untouched until conversion passes.

Target design

Recommendation: a typed versioned config decoded deliberately, with unknown-field policy and semantic validation. Write a same-directory temporary file, validate it and replace only after success; qualify filesystem/OS behavior and cross-process ownership.

Rollback

Recommendation: restore the backup and preceding executable together. Preserve old readable configuration throughout the downgrade window; do not roll back after newer-only values without an explicit mapping.

Benefits and prerequisites

A versioned configuration contract makes upgrades and later rollback predictable.
Requires: Old fixtures exist; migration preserves semantics and backups; one writer and tested replacement behavior are defined.
Tradeoffs: Strict unknown-field rejection can hinder mixed-version use; atomic replacement does not establish crash durability or coordinate concurrent writers.

Checks before transfer

  • Load representative old config, migrate and compare effective settings.
  • Reject unknown unsupported schema versions before modifying files.
  • Interrupt conversion and verify either the original or complete new file remains; test permissions on each target OS.
Jobs and schedules

Inspect the source

Preserve per-item effects, retry decisions, ordering and interrupt behavior for batch commands; a process-local queue has no restart history.

During coexistence

Recommendation: keep the sequential executor available and compare the new bounded executor on fixture inputs. Route one operation class at a time; reuse stable operation IDs across retries.

Target design

Recommendation: signal.NotifyContext plus errgroup limit or a fixed worker pool. Pass context through clients, close resources after workers finish, and persist a checkpoint/receipt when interrupted effects need later recovery.

Rollback

Recommendation: return to sequential execution using the same checkpoint contract. Reconcile ambiguous outcomes first; restarting from item zero is not a safe general rollback.

Benefits and prerequisites

Bounded fan-out can overlap independent I/O while maintaining a clear cancellation boundary.
Requires: Concurrency quota and total deadline are set; downstream calls honor cancellation; completed and ambiguous effects can be reconciled.
Tradeoffs: No throughput gain is measured; cancellation cannot undo effects; a retry can duplicate a write without provider or business idempotency.

Checks before transfer

  • Interrupt midway through a batch and verify completed, pending and ambiguous items are reported separately.
  • Simulate one failed item; verify the selected stop/continue policy and bounded parallelism.
  • Resume using stable IDs and prove acknowledged effects are not repeated.
Delivery and recovery

Inspect the source

Preserve command name, install path, OS/architecture support, update channel and downgrade compatibility.

During coexistence

Recommendation: produce snapshot artifacts beside the old release and smoke-test them without changing the default download. Review generated package-manager changes and publish channels only after target verification.

Target design

Recommendation: pinned GoReleaser v2 matrix with metadata/checksums, OS-specific install tests and an explicit signing path. CGO dependencies and macOS signing/notarization need separate toolchain/credential setup; the documented native package notarization flow is Pro; qualify the chosen binary or package flow separately.

Rollback

Recommendation: repoint the owned download/package channel to the previous verified release and keep its artifacts available. Restore compatible configuration with the binary; do not silently overwrite unrelated install locations.

Benefits and prerequisites

A repeatable artifact matrix reduces manual release assembly.
Requires: Build inputs/tool versions are pinned; each promised target is installed and exercised; signing credentials and package metadata are owned.
Tradeoffs: Cross-compilation is not execution evidence; CGO can require native toolchains; selected signing/notarization automation may require a paid tier.

Checks before transfer

  • Install on clean Linux, macOS and Windows hosts for every advertised architecture.
  • Verify version metadata, checksums, permissions and executable path.
  • Upgrade from the old package and downgrade with preserved config; inspect macOS Gatekeeper behavior for the actual downloaded artifact.

Read the migration workflow →

Setup

  1. Start in a source checkout; go mod init example.com/tool using its intended module path.
  2. Run go get github.com/spf13/cobra; resolve a supported Bubble Tea release only if a TUI is required.
  3. Build cmd/tool with injectable I/O, configuration validation, stable exit codes and explicit noninteractive behavior.
  4. Write command tests covering malformed input, stdout/stderr, cancellation and safe retries; use isolated temporary paths.
  5. Run goreleaser init, then review and pin the generated configuration and target matrix. No setup or publishing has been executed.

Verification

Run these in the configured application; they are instructions, not recorded passes.

gofmt -l .
go test ./...
go test -race ./...
go vet ./...
govulncheck ./...
go build ./cmd/tool
goreleaser check
goreleaser build --snapshot --clean

Open questions

Sources