feat(output): output-contract polish — TTY-aware format, detail view, partial-failure exit 7, actionable errors#230
Merged
Conversation
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…gate Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolve the effective output format in PersistentPreRunE: explicit --output wins, then config default_output, then auto (terminal -> table, piped -> json). Disable color whenever stdout is not a terminal so ANSI never leaks into a pipe. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A single-object response now renders as a FIELD/VALUE detail layout instead of an unreadable 1-row table (and fixes Print(map) previously emitting Go's %v map repr). Arrays, even of length one, still render as tables. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
--compact now keeps high-signal scalars only: an identity/allowlist of leaf fields plus any scalar present in >=80% of list rows; single objects keep scalars except a verbose blocklist. Rare noise fields are dropped (use --select for specific fields). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…t-out Handwritten bulk operations (group membership, policy enable/disable, MDM send-command) now return exit code 7 when some items succeed and some fail, distinguishing partial from total failure. --allow-partial-failure downgrades to a warning + exit 0. Total failures propagate the underlying error code. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When some objects export and some fail, backup now returns exit code 7 instead of a generic error. --allow-partial-failure downgrades to a warning + exit 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…l failure Both modern and classic generated bulk-delete loops (--from-file and --group) now continue past per-item failures, tally results, and return exit code 7 via a package-local batchDeleteError helper when some succeed and some fail. Previously they aborted at the first failure. --allow-partial-failure downgrades to a warning + exit 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…in JSON Move per-status remediation out of the message and into exitcode.Error.Hint via a pure httpStatusError helper. main prints a "hint:" line for human output; the JSON envelope gains hint, exitCodeName, and any structured details. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Enable cobra command suggestions (SuggestionsMinimumDistance) and add a FlagErrorFunc that prints "hint: did you mean --X?" for the nearest known flag, then classifies the failure as a usage error (exit 2). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Releases are the single source of truth for version history; point readers there rather than maintaining a duplicate CHANGELOG.md that would drift. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…as usage Two fixes to the actionable-error feature, found during live testing: - suggestFlag gated only on edit distance < 3, so short typos matched unrelated flags by alphabetical tie-break (--fld -> --all, --id -> --wide). Now require a shared first letter and cap distance relative to the typo length, so --fld -> --field and --id produces no misleading hint. - Unknown commands returned a plain cobra error (exit 1) while unknown flags exited 2. Add ClassifyError to wrap unknown-command errors as usage (exit 2), applied in main before formatting so the JSON envelope and exit code agree; cobra's "did you mean" suggestion is preserved. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Cobra rejects unknown subcommands only on the root command (legacyArgs in Find), so `pro buildings lst` printed help and exited 0 rather than erroring. A non-runnable command also short-circuits to help before arg validation, so an Args validator never runs on a pure group. guardUnknownSubcommands walks the tree and attaches a RunE to every non-root group parent: a bare invocation still shows help, while an unknown subcommand returns a usage error (exit 2) with a "did you mean" suggestion, matching the root behavior. Guarded parents are annotated so PersistentPreRunE skips auth — a group parent never calls an API itself. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Walks the full command tree and verifies each group parent (279 today) is guarded: it carries the group-parent annotation and returns a usage exit code on an unknown subcommand. This covers new command groups automatically — a future generated or hand-written group that slips past guardUnknownSubcommands fails this test instead of silently printing help and exiting 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
neilmartin83
approved these changes
May 31, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Polishes the CLI's output and error contract so it behaves like a well-mannered Unix tool: human-friendly in a terminal, machine-clean in a pipe, with actionable failures and consistent exit codes.
User-facing changes
table; piped/redirected/--out-filedefaults tojson. Explicit-oand configdefault_outputstill win.getrenders a verticalFIELD / VALUElayout in table mode instead of an unreadable one-row table.--compact— keeps identity + fields common across rows, drops sparse/nested noise.7when some items fail;--allow-partial-failuredowngrades to0.hint:on stderr andhint/exitCodeNamein the JSON error envelope; "did you mean" suggestions for command and flag typos.Fixes found during live testing
--fld→--field(not--all) and--idproduces no misleading hint.2(usage) to match the unknown-flag path.pro buildings lst) now error with a suggestion and exit2instead of silently printing help and exiting0.Testing
go test ./...,gofumpt,go vet, andmake verify-generatedall clean.main(1.18.0); coexists with--no-hints.🤖 Generated with Claude Code