Help us shape the future of Go! Take the 2026 Go Developer Survey

cliutil

package
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package cliutil holds small helpers shared across forge's CLI surface.

The package's first inhabitant is the user-facing error helper. Forge errors that bubble up to the CLI boundary follow a consistent shape so users (humans + LLM agents) always know:

  1. Which subcommand surfaced the error (the context).
  2. What concretely failed (the message).
  3. Optionally, where in the source tree the failure points (file:line).
  4. A one-line suggestion for the next action (the Fix clause).

The shape:

<context>: <what failed> (at <file:line>). Fix: <one-line suggestion>.

`at <file:line>` and `Fix: ...` are both optional; UserErr drops the clause entirely when its argument is empty rather than padding the message with `at unknown` or `Fix: see docs`. Internal errors (helper → helper) are NOT expected to use this helper — the wrapper's job is only to format the final user-visible boundary.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Heartbeat added in v1.0.0

func Heartbeat(w io.Writer, label string) (stop func())

Heartbeat reports that label is still running, on w, every 15 seconds until the returned stop is called. A step that finishes inside the first interval prints nothing. Output goes to w (stderr at every call site), never stdout: a --json document or a verdict line stays alone there.

stop := cliutil.Heartbeat(os.Stderr, "generate: buf generate")
err := run()
stop()

stop is idempotent and waits for the reporter to exit, so no line can land after the step's own output.

func HeartbeatEvery added in v1.0.0

func HeartbeatEvery(w io.Writer, label string, interval time.Duration) (stop func())

HeartbeatEvery is Heartbeat with an explicit interval, for a caller (a test) that cannot wait 15 seconds.

func StdinIsTTY

func StdinIsTTY() bool

StdinIsTTY reports whether forge's standard input is connected to an interactive terminal.

Forge is an LLM-first tool: the common driver is an agent or CI runner, neither of which has a TTY on stdin. Any code path that would otherwise block on an interactive prompt MUST gate on this helper first. When it returns false the command must NOT prompt — it either applies a safe default (for non-destructive actions) or fails fast with an actionable error that names the flag which avoids the prompt (for destructive ones).

Centralising the check here keeps the TTY policy consistent across the CLI surface and gives us a single seam to override in tests if needed.

func UserErr

func UserErr(context, what, at, fix string) error

UserErr formats a user-facing CLI error as:

<context>: <what> (at <at>). Fix: <fix>.

Both `at` and `fix` are optional; pass "" to omit the corresponding clause cleanly. `context` and `what` are required.

Example:

return cliutil.UserErr("forge pack add api-key",
    "pack 'api-key' depends on 'audit-log' which is not installed",
    "",
    "run 'forge pack add audit-log api-key' (auto-installs in topological order)",
)

func UserErrf

func UserErrf(context, format string, args ...any) error

UserErrf is the printf-style sibling of UserErr — `what` is rendered with fmt.Sprintf(format, args...). Use this when the message needs dynamic interpolation (e.g. the failing component name); use UserErr when the message is a literal string.

func WrapUserErr

func WrapUserErr(context, what, at, fix string, inner error) error

WrapUserErr wraps an underlying error with the standard user-facing shape, preserving `errors.Is` / `errors.As` semantics on the inner error. Use this when the inner error already has a meaningful message (e.g. an io.ErrClosedPipe, or a forge/pkg/* sentinel) and you only need to add the context/fix wrapping.

The result reads as:

<context>: <what>: <inner>. Fix: <fix>.

`at` and `fix` may be empty — the corresponding clause drops cleanly.

Types

This section is empty.

Jump to

Keyboard shortcuts

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