Skip to content

Rust CLI: exit 2 for usage errors, matching the Node CLI - #331

Closed
poiley wants to merge 4 commits into
rust-cli-portfrom
rust-cli-usage-exit-2
Closed

Rust CLI: exit 2 for usage errors, matching the Node CLI#331
poiley wants to merge 4 commits into
rust-cli-portfrom
rust-cli-usage-exit-2

Conversation

@poiley

@poiley poiley commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to the Rust CLI port: align usage-error exit codes with the Node CLI.

The port exited 1 for every failure, while the Node CLI (oclif) exits 2 for usage errors and 1 for runtime failures. Scripts and agents that branch on that distinction would silently break when switching CLIs, and the parity fixtures had to encode the divergence in 11 expectByRunner waivers (all 11 were node: exitCode 2 vs rust: exitCode 1).

What changed

  • New transparent UsageError marker + usage_err! macro in cli-rust/src/config.rs (lives there so the include-style integration tests resolve it), re-exported from lib.rs. main_entry picks the exit code by inspecting the error chain, so stderr output is byte-identical to before; only the exit code changes.
  • Converted to exit 2: generated-command invocation parsing and parameter validation (execute_operation boundary), unknown command/subcommand/alias resolution across all command families, unknown-flag and missing-flag-value parsers, send body-source conflicts, and functions logs --follow/--cursor conflict.
  • Deliberately left at exit 1 (the Node CLI also exits 1 there, per the existing fixtures): describe unknown operation, config mutation validation, doctor failures.
  • Fixtures: the 11 waivers now assert exitCode: 2 on both runners. Where the node and rust expectations became identical the waiver is collapsed into the shared expect block (expectByRunner count 84 -> 77).
  • Added unit tests: usage vs runtime exit-code selection, marker survival through context() wrapping, Display pass-through.

Validation

  • make rust-cli-check (fmt, clippy -D warnings, doc, tests)
  • make cli-parity green: 315/315 cases, command-surface parity, operation coverage, help sweep with --compare-flags
  • make node-check cli-check go-check shared-check
  • make rust-cli-full-check

🤖 Generated with Claude Code

etbyrd and others added 2 commits July 18, 2026 14:32
…tion

The Rust port exited 1 for every failure, while the Node CLI exits 2 for
usage errors (unknown command, unknown flag, missing flag value, invalid
or conflicting inputs) and 1 for runtime failures. Scripts that branch on
that distinction would silently break when switching CLIs, and the parity
fixtures had to encode the divergence in 11 expectByRunner waivers.

Adds a transparent UsageError marker in config.rs (shared with the
include-style integration tests) plus a usage_err! macro; main_entry picks
the exit code by inspecting the error chain, so stderr output is unchanged.
Converted sites: generated-command invocation parsing and parameter
validation, unknown command/subcommand/alias resolution across all command
families, unknown flag and missing flag value parsers, send body-source
conflicts, and the functions logs --follow/--cursor conflict. Validation
paths where the Node CLI also exits 1 (describe unknown operation, config
mutations, doctor) are intentionally left at 1.

The 11 fixture waivers now assert exitCode 2 on both runners; waivers whose
node and rust expectations became identical are collapsed into the shared
expect block (expectByRunner 84 -> 77).

Validation: make rust-cli-check, cli-parity (315 cases), node-check,
cli-check, go-check, shared-check, rust-cli-full-check.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Jul 20, 2026

Copy link
Copy Markdown

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
cli-rust/src/auth_commands.rs Auth command parsing now marks invalid argument forms with the usage-error path.
cli-rust/src/config.rs Adds the usage-error marker, macro, and exit-code helper used by the Rust CLI.
cli-rust/src/lib.rs Wires the Rust CLI entry path to choose the process exit code from the error chain.

Reviews (3): Last reviewed commit: "Mark post-parse invocation-shape errors ..." | Re-trigger Greptile

Comment thread cli-rust/src/auth_commands.rs Outdated
Comment thread cli-rust/src/auth_commands.rs Outdated
Greptile review: missing-value and bool-with-inline-value branches in the
hand-rolled per-command parsers (and api.rs parse_invocation, called
directly by payments) still returned unmarked errors and exited 1. Convert
Missing value for --X, Flag --X does not take a value, Flag --X expects a
value, Expected a boolean for --X, and Unexpected argument to usage errors
so every invalid-invocation path exits 2.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread cli-rust/src/auth_commands.rs
Greptile round 2: validation that runs after flag parsing succeeds but
still rejects the invocation shape (missing or extra positionals, missing
required companion flags like --accept-terms or an email address for
--signup-code, conflicting verification-code sources, --code-from-stdin on
a TTY, config use arity, functions init arity, Unexpected argument across
all hand-rolled parsers) now carries the usage marker and exits 2.

State-dependent failures intentionally stay at exit 1: pending-auth email
mismatch, no pending signup found, not logged in, unreadable
--code-from-file targets, unset --code-from-env variables, and browser
login denial, matching the Node CLI per the existing parity fixtures.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@poiley

poiley commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #332. The base branch was force-rebased (18e9f0c -> f1b5005) which made this PR unmergeable, and the rebased port already includes a CliError usage-error mechanism covering part of what this PR did. #332 rebuilds the remainder on the new base: ~100 uncovered parse/validation sites, auth post-parse checks, and chain-walking exit-code detection.

@poiley poiley closed this Jul 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants