Skip to content

sphere-cli UX consistency: unified currency input, human-friendly default output, complete --help, autocomplete, auto-help on invalid input #32

Description

@vrogojin

Streamline the sphere-cli command-line UX so every command, subcommand, and sub-subcommand behaves consistently in how it takes input and how it presents output. This is a follow-up to the post-#397/#401 cleanup pass; the user will pick it up after a fresh-context session, so this issue is deliberately self-contained.

Scope — five concrete consistency goals

1. Unified currency input across all commands

Canonical syntax: human-friendly fractional amount separated from the coin symbol by a space.

sphere payments send <recipient> 100.5 UCT
sphere invoice create --target @alice --asset "7 UCT" --asset "0.001 BTC"
sphere swap propose --to @bob --offer "7 UCT" --want "2 ETH"
sphere invoice return <id> --recipient @bob --asset "100000 UCT"

Today this mostly works (src/legacy/legacy-cli.ts:425 parseAssetArg already handles "<amount> <symbol>" and several commands consume it), but coverage is incomplete and the argument shape diverges:

  • payments send <recipient> <amount> <coin> uses positional amount + coin (separate tokens)
  • invoice-create --asset "<amount> <coin>" uses quoted compound form
  • swap-propose --offer "<amount> <coin>" matches invoice-create
  • invoice-return --asset "<amount> <coin>" matches invoice-create

Required: every command that takes amount-plus-coin must accept the same form. Pick one canonical syntax (recommendation: positional <amount> <coin> mirrors payments send's shape and avoids the quote-juggling), document it once, and adapt every other site to accept it. NFT (--nft <tokenId>) input rules also need to be consistent across invoice-create / swap-propose / payments send.

2. Human-friendly default output (not raw JSON)

Most commands today print a raw JSON.stringify(result, null, 2) blob. Inventory in src/legacy/legacy-cli.ts:

Line Command
3093 nametag resolve/check
3129 / 3142 identity / address inspection
4166 invoice-list
4261 invoice-status (one of two sites)
4309 invoice-import
4383 invoice-deliver
4494 / 5266 invoice-status
4618 invoice-pay
4688 invoice-return
4722 invoice-cancel / similar

…plus ~17 more JSON.stringify outputs at lines 1798, 1894, 3015, 3093, 3177, 3195, 3216, etc.

Required: default output for end-user-facing commands should be a prettified table or labelled key-value block (see invoice-status line 4446 which already does ID: ... / Status: ... labelling — that style should be the template). Raw JSON output should be opt-in via a --json flag (machine-readable mode for scripts / pipes).

Acceptance: running e.g. sphere invoice create --target @alice --asset \"7 UCT\" and sphere invoice deliver <id> --to @bob should produce a readable table by default; --json should still emit the existing structured form for backwards compatibility with anyone scripting against the CLI.

3. Help works for every command, subcommand, sub-subcommand

Today the --help / -h / help handler is wired at a single top-level entrypoint (src/legacy/legacy-cli.ts:1716 and a second branch at line 1723), but the dispatch through to specific subcommands is patchy. Symptoms:

  • sphere wallet --help may not print wallet-specific help
  • sphere invoice deliver --help may not print deliver-specific help
  • sphere swap propose --help likewise

Required: every command in the COMMANDS registry (search src/legacy/legacy-cli.ts for usage: — 57+ entries) should respond to --help / -h / help by printing its own usage + flag table + examples. Common idiom in similar CLIs: a single helper printHelpFor(commandName) that the early-dispatch path calls before any side-effecting work runs.

4. Bash/zsh autocompletion

A completion generator already exists at src/legacy/legacy-cli.ts:5599+ (sphere-cli completions bash), but the user reports autocompletion is not working at all in practice. Two likely causes, both worth verifying:

  1. The generator output may not match the actual command shape (e.g. it's stale vs the current COMMANDS table at line 533+).
  2. Installing the completion file requires a system path (/etc/bash_completion.d/sphere-cli) which needs sudo. The setup step may not be documented as part of sphere init / installation.

Required:

  • Verify the generated completion is correct against the current command/flag inventory.
  • Document the installation step in the README (sudo path) and offer a no-sudo per-user fallback (~/.bash_completion.d/ / zsh $fpath).
  • If kernel/system-level setup is required, defer the actual install step but ship the verified-correct generator so the user can do the install themselves later.

5. Auto-help on invalid input

Today, invalid input typically falls through to console.error('Usage: ...') followed by process.exit(1). The single-line usage string isn't enough — it omits flag descriptions and examples. Recommended: on any parse failure (unknown subcommand, missing required arg, bad asset spec), the CLI should:

  1. Print a one-line "Error: " message
  2. Print the full help block for the closest matching subcommand
  3. Exit non-zero

Common in modern CLIs (Cargo, kubectl, gh). Concrete example today: passing sphere invoice create with no --asset flag should print the full invoice-create help, not just the one-line usage.

Suggested phasing (for the implementer)

  1. Pass A — output: route every JSON.stringify(result, ...) site through a shared formatOutput(payload, { json }) helper. Add --json to the global flag set so it applies everywhere. Define table formatters for the common payload shapes (Invoice, InvoiceStatus, TransferResult, Asset[], Token[], PeerInfo).
  2. Pass B — input: pick the canonical <amount> <coin> syntax and write one parseAssetArg (the existing one at line 425 is a good base) that every command uses. Update help strings + examples in lockstep.
  3. Pass C — help: add printHelpFor(commandName) and a single early-dispatch shim at the top of runCli() that catches --help / -h / help <cmd> / missing-required-arg cases and prints help instead of running the command.
  4. Pass D — completion: verify generator output, document install (with sudo + no-sudo paths), add a CI smoke that diffs the generator output against a golden file so it can't drift.

Each pass is mergeable independently. Pass A delivers the most visible user win and should land first.

Out of scope

  • Cosmetic redesign (colors, ASCII art, etc.) — focus is consistency, not theming.
  • Migrating off the legacy-cli.ts monolith — that's its own refactor; this issue can land within the existing file structure.
  • Daemon-mode commands (sphere daemon ...) — separate UX surface; consistency goals apply but daemon-output formats can be tackled in a follow-up if needed.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions