Skip to content

CLI ergonomics polish: -h/--version, typo suggestions, examples, machine-readable output #39

@dolph

Description

@dolph

Summary

A grab-bag of small UX papercuts a first-time user of connectivity hits at the terminal. Each is minor in isolation; together they make the tool feel less polished than it is. Most can be addressed in passing when #25 lands, but they're decisions independent of the parser choice and worth tracking explicitly so they aren't forgotten.

These are scoped to user-visible CLI surface and do not overlap with #25 (parser refactor), #5 (URL-drop bug), #3 (color), or #27 (contributor docs).

Papercuts

1. No -h / --help / -v / --version short flags

Currently only the help and version subcommands work. Every Unix CLI a developer reaches for — git, kubectl, docker, curl, jq, terraform — accepts -h/--help and --version. Today:

$ connectivity --help
# falls through to "unknown subcommand" + exit 2
$ connectivity --version
# same
$ connectivity -h
# same

This is the single most surprising thing a new user hits. Fix: accept -h, --help, -v, --version at the top level, and -h/--help on each subcommand.

2. No typo suggestions

connectivity chcek https://example.com prints the full usage with exit 2 but no "did you mean check?". For a CLI with only 6 subcommands this is cheap (Levenshtein-1 across a fixed list) and a nice touch. Many CLI libraries (cobra, urfave/cli) give it for free.

3. help <subcommand> shows usage but no examples

connectivity help check prints:

Usage: connectivity check [urls]

This is useful when you want to externally orchestrate other processes by
quickly validating connectivity.

The README has concrete examples (connectivity check icmp://example.com tcp://example.com:443 https://example.com/health) that don't make it into the per-command help. A copy-pasteable example block ("Examples:") under each subcommand would close the gap between --help and reading the README.

4. version output is not single-line greppable

Today:

Version: v1.2.3
Commit SHA: abc1234
Go Version: go1.22.0
Built: 2025-...
OS/Arch: linux/amd64

Five lines of free-form text. Scripts that want just the semver (connectivity version | head -1 | cut -d' ' -f2) work but are brittle, and there is no machine-readable form. Two cheap fixes:

  • Make the first line connectivity v1.2.3 (no Version: prefix) so it greps cleanly — matches git --version, kubectl version --short, etc.
  • Optionally add version --json for full structured output.

5. validate-config has no machine-readable output

validate-config prints ShowDestinations() to logs (timestamps and all) — fine for humans, but a config-linting use case in CI ("is my config syntactically valid?") really wants either:

  • A clean exit code with no log output on success (today it always prints), or
  • --json listing the parsed destinations.

6. waitfor alias is undocumented and unflagged

waitfor is accepted as a synonym for wait (connectivity.go:53), and PrintCommandUsage references it as [wait|waitfor], but PrintUsage() only lists wait. Decide: either drop it (it's not in the public help so probably no one uses it), or mark it explicitly deprecated with a stderr warning that points to wait. Today it's in a limbo where it works but isn't discoverable.

7. Inconsistent subcommand naming

validate-config is kebab-case; every other subcommand (check, wait, monitor, version, help) is a single word. Either accept the inconsistency or alias validateconfig / validate_config. Low-priority; flagging only because a hand-rolled parser is the moment to decide.

8. No shell completion

No bash_completion, zsh, or fish completions installed or generatable. With only 6 subcommands and a small set of URL schemes, even a hand-written bash file would be useful. cobra would generate this automatically; with stdlib flag it's a 30-line bash script. Related to the parser decision in #25.

9. No man page

connectivity --man does nothing; no man connectivity. Optional — many Go CLIs skip this — but worth noting for completeness.

Suggested approach

If #25 lands with cobra, items 1, 2, 8 come for free and items 3, 4, 5 become trivial flag additions. If #25 lands with stdlib flag, items 1–3 need explicit handling. Either way these decisions are independent of the parser refactor.

Out of scope

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions