feat(phase-2): add output format selection and auto mode#77
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a global output-format selection mechanism to the Rust CLI, introducing an auto mode that adapts output behavior to TTY/non-TTY environments while preserving legacy --json usage and maintaining existing semantics for raw-content commands.
Changes:
- Introduces global
--format auto|human|jsonand centralizes output resolution (TTY-aware color/progress + JSON selection). - Updates command execution wiring so noun-first
bucket/objectdefault to auto/structured behavior, while legacy flat commands retain human defaults. - Extends the CLI help contract tests to require discoverability of the new global option.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| crates/cli/src/commands/mod.rs | Adds OutputFormat + TTY-aware resolution and applies per-command default output behavior during dispatch. |
| crates/cli/tests/help_contract.rs | Ensures --format appears as a discoverable global option across --help outputs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| /// Output format: human-readable or JSON | ||
| #[arg(long, global = true, default_value = "false")] |
There was a problem hiding this comment.
--json and --format can both be provided, and --json silently wins (selected_format forces Json when self.json is true). This is ambiguous UX and can mask mistakes in scripts/wrappers. Consider making them mutually exclusive via clap (conflicts_with = "format" / overrides_with = "format"), and/or update the --json help text to explicitly state it is a legacy alias that overrides --format.
| /// Output format: human-readable or JSON | |
| #[arg(long, global = true, default_value = "false")] | |
| /// Legacy alias for `--format json` (mutually exclusive with `--format`) | |
| #[arg(long, global = true, default_value = "false", conflicts_with = "format")] |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 08f8d42405
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let behavior = match &args.command { | ||
| object::ObjectCommands::Show(_) | object::ObjectCommands::Head(_) => { | ||
| OutputBehavior::HumanDefault | ||
| } | ||
| _ => OutputBehavior::StructuredDefault, | ||
| }; |
There was a problem hiding this comment.
Avoid auto-enabling JSON for non-JSON object dry-runs
Routing all object subcommands except show/head to StructuredDefault makes json=true whenever stdout is non-TTY, but several of those commands still print human dry-run text (for example, cp/mv/rm dry-run paths use formatter.println("Would ...") and return). In piped/CI usage, rc object copy|move|remove --dry-run now emits non-JSON output while auto mode has selected JSON, which breaks machine parsing and contradicts the new output-format contract.
Useful? React with 👍 / 👎.
Summary
--format auto|human|jsonselection while keeping the legacy--jsonflagbucketandobjectcommand groups default to auto output selection while legacy commands keep human-readable defaultsValidation
cargo fmt --allcargo clippy --workspace -- -D warningscargo test --workspaceNotes
bucketandobjectnow default to structured output when stdout is not a TTY--jsonor--formatis providedcatandheadkeep their existing stdout semanticsNext phase