cli

Command-line interface for Radroots
git clone https://radroots.dev/git/cli.git
Log | Files | Refs | README | LICENSE

commit 871d0b548fb3f25cf0b6d4b45a7ae69c7d470a3f
parent 65a12e6f9d11efb56bcf9e1533dbf8414d4646db
Author: triesap <tyson@radroots.org>
Date:   Sat, 27 Jun 2026 06:59:32 +0000

cli: remove terminal color presentation mode

- remove no-color from the public argument surface
- delete terminal color and stream TTY render context fields
- drop output color from runtime config and config get output
- add parser and integration rejection coverage for removed flag

Diffstat:
Msrc/cli/global.rs | 1-
Msrc/cli/input.rs | 1-
Msrc/cli/mod.rs | 12++++++++----
Msrc/main.rs | 18++----------------
Msrc/ops/context.rs | 2--
Msrc/ops/exec/basket.rs | 1-
Msrc/ops/exec/core.rs | 2--
Msrc/ops/exec/farm.rs | 1-
Msrc/ops/exec/listing.rs | 1-
Msrc/ops/exec/market.rs | 1-
Msrc/ops/exec/runtime.rs | 1-
Msrc/ops/exec/trade.rs | 1-
Msrc/ops/mod.rs | 2--
Msrc/out/terminal/renderer.rs | 13-------------
Msrc/runtime/config.rs | 5-----
Msrc/runtime/provider.rs | 1-
Msrc/runtime/sdk.rs | 1-
Msrc/runtime/sync.rs | 1-
Msrc/view/runtime.rs | 1-
Mtests/target_cli.rs | 14+++++++++++++-
20 files changed, 23 insertions(+), 57 deletions(-)

diff --git a/src/cli/global.rs b/src/cli/global.rs @@ -29,7 +29,6 @@ pub struct RuntimeInvocationArgs { pub verbose: bool, pub trace: bool, pub dry_run: bool, - pub no_color: bool, pub no_input: bool, pub yes: bool, pub log_filter: Option<String>, diff --git a/src/cli/input.rs b/src/cli/input.rs @@ -17,7 +17,6 @@ pub fn runtime_invocation_args_from_target(args: &TargetCliArgs) -> RuntimeInvoc verbose: args.verbose, trace: args.trace, dry_run: args.dry_run, - no_color: args.no_color, no_input: args.no_input, yes: false, log_filter: None, diff --git a/src/cli/mod.rs b/src/cli/mod.rs @@ -100,8 +100,6 @@ pub struct TargetCliArgs { pub verbose: bool, #[arg(long = "trace", global = true, action = ArgAction::SetTrue)] pub trace: bool, - #[arg(long = "no-color", global = true, action = ArgAction::SetTrue)] - pub no_color: bool, #[command(subcommand)] pub command: TargetCommand, } @@ -367,7 +365,6 @@ mod tests { "approval_test", "--no-input", "--quiet", - "--no-color", "workspace", "get", ]) @@ -386,11 +383,18 @@ mod tests { assert_eq!(parsed.approval_token.as_deref(), Some("approval_test")); assert!(parsed.no_input); assert!(parsed.quiet); - assert!(parsed.no_color); assert_eq!(parsed.command.operation_id(), "workspace.get"); } #[test] + fn target_parser_rejects_removed_no_color_flag() { + let error = TargetCliArgs::try_parse_from(["radroots", "--no-color", "workspace", "get"]) + .expect_err("removed no-color flag should be rejected"); + + assert_eq!(error.kind(), clap::error::ErrorKind::UnknownArgument); + } + + #[test] fn target_parser_accepts_account_attach_secret_inputs() { let parsed = TargetCliArgs::try_parse_from([ "radroots", diff --git a/src/main.rs b/src/main.rs @@ -7,7 +7,7 @@ mod registry; mod runtime; mod view; -use std::io::{IsTerminal, Write}; +use std::io::Write; use std::process::ExitCode; use std::sync::atomic::{AtomicU64, Ordering}; use std::time::{SystemTime, UNIX_EPOCH}; @@ -29,7 +29,7 @@ use crate::ops::{ use crate::out::envelope::{CliExitCode, OutputEnvelope, OutputError}; use crate::out::terminal::registry::terminal_renderer_registry; use crate::out::terminal::renderer::{ - TerminalColorPolicy, TerminalRenderContext, TerminalVerbosity, render_terminal_document, + TerminalRenderContext, TerminalVerbosity, render_terminal_document, }; use crate::registry::{NetworkRequirement, network_requirement, requires_local_signer_mode}; use crate::runtime::config::{ @@ -549,10 +549,7 @@ fn render_config_from_target_args( }, terminal: TerminalRenderContext { verbosity: terminal_verbosity_from_flags(args.quiet, args.verbose, args.trace), - color: terminal_color_policy(!args.no_color), width: 80, - stdout_is_tty: std::io::stdout().is_terminal(), - stderr_is_tty: std::io::stderr().is_terminal(), dry_run: args.dry_run, }, } @@ -567,10 +564,7 @@ fn render_config_from_runtime(config: &RuntimeConfig) -> EnvelopeRenderConfig { }, terminal: TerminalRenderContext { verbosity: terminal_verbosity_from_runtime(config.output.verbosity), - color: terminal_color_policy(config.output.color), width: 80, - stdout_is_tty: config.interaction.stdout_tty, - stderr_is_tty: std::io::stderr().is_terminal(), dry_run: config.output.dry_run, }, } @@ -597,14 +591,6 @@ fn terminal_verbosity_from_runtime(verbosity: Verbosity) -> TerminalVerbosity { } } -fn terminal_color_policy(color: bool) -> TerminalColorPolicy { - if color { - TerminalColorPolicy::Auto - } else { - TerminalColorPolicy::Never - } -} - fn render_envelope( envelope: &OutputEnvelope, config: &EnvelopeRenderConfig, diff --git a/src/ops/context.rs b/src/ops/context.rs @@ -74,7 +74,6 @@ pub struct OperationContext { pub quiet: bool, pub verbose: bool, pub trace: bool, - pub color: bool, } impl OperationContext { @@ -105,7 +104,6 @@ impl OperationContext { quiet: args.quiet, verbose: args.verbose, trace: args.trace, - color: !args.no_color, } } diff --git a/src/ops/exec/basket.rs b/src/ops/exec/basket.rs @@ -1855,7 +1855,6 @@ mod tests { output: OutputConfig { format: OutputFormat::Terminal, verbosity: Verbosity::Normal, - color: true, dry_run: false, }, interaction: InteractionConfig { diff --git a/src/ops/exec/core.rs b/src/ops/exec/core.rs @@ -201,7 +201,6 @@ impl OperationService<ConfigGetRequest> for CoreOperationService<'_> { "output": { "format": self.config.output.format.as_str(), "verbosity": self.config.output.verbosity.as_str(), - "color": self.config.output.color, "dry_run": self.config.output.dry_run, }, "interaction": { @@ -1320,7 +1319,6 @@ mod tests { output: OutputConfig { format: OutputFormat::Terminal, verbosity: Verbosity::Normal, - color: true, dry_run: false, }, interaction: InteractionConfig { diff --git a/src/ops/exec/farm.rs b/src/ops/exec/farm.rs @@ -845,7 +845,6 @@ mod tests { output: OutputConfig { format: OutputFormat::Terminal, verbosity: Verbosity::Normal, - color: true, dry_run: false, }, interaction: InteractionConfig { diff --git a/src/ops/exec/listing.rs b/src/ops/exec/listing.rs @@ -556,7 +556,6 @@ mod tests { output: OutputConfig { format: OutputFormat::Terminal, verbosity: Verbosity::Normal, - color: true, dry_run: false, }, interaction: InteractionConfig { diff --git a/src/ops/exec/market.rs b/src/ops/exec/market.rs @@ -620,7 +620,6 @@ mod tests { output: OutputConfig { format: OutputFormat::Terminal, verbosity: Verbosity::Normal, - color: true, dry_run: false, }, interaction: InteractionConfig { diff --git a/src/ops/exec/runtime.rs b/src/ops/exec/runtime.rs @@ -300,7 +300,6 @@ mod tests { output: OutputConfig { format: OutputFormat::Terminal, verbosity: Verbosity::Normal, - color: true, dry_run: false, }, interaction: InteractionConfig { diff --git a/src/ops/exec/trade.rs b/src/ops/exec/trade.rs @@ -1742,7 +1742,6 @@ mod tests { output: OutputConfig { format: OutputFormat::Terminal, verbosity: Verbosity::Normal, - color: true, dry_run: false, }, interaction: InteractionConfig { diff --git a/src/ops/mod.rs b/src/ops/mod.rs @@ -77,7 +77,6 @@ mod tests { "--quiet", "--verbose", "--trace", - "--no-color", "workspace", "get", ]) @@ -99,7 +98,6 @@ mod tests { assert!(context.quiet); assert!(context.verbose); assert!(context.trace); - assert!(!context.color); let envelope_context = context.envelope_context("req_test"); let actor = envelope_context.actor.expect("account actor"); diff --git a/src/out/terminal/renderer.rs b/src/out/terminal/renderer.rs @@ -15,20 +15,10 @@ pub enum TerminalVerbosity { Trace, } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum TerminalColorPolicy { - Auto, - Always, - Never, -} - #[derive(Debug, Clone, PartialEq, Eq)] pub struct TerminalRenderContext { pub verbosity: TerminalVerbosity, - pub color: TerminalColorPolicy, pub width: usize, - pub stdout_is_tty: bool, - pub stderr_is_tty: bool, pub dry_run: bool, } @@ -36,10 +26,7 @@ impl Default for TerminalRenderContext { fn default() -> Self { Self { verbosity: TerminalVerbosity::Normal, - color: TerminalColorPolicy::Auto, width: 80, - stdout_is_tty: false, - stderr_is_tty: false, dry_run: false, } } diff --git a/src/runtime/config.rs b/src/runtime/config.rs @@ -119,7 +119,6 @@ impl Verbosity { pub struct OutputConfig { pub format: OutputFormat, pub verbosity: Verbosity, - pub color: bool, pub dry_run: bool, } @@ -642,7 +641,6 @@ impl RuntimeConfig { workspace_config.as_ref(), )?, verbosity: resolve_verbosity(args)?, - color: !args.no_color, dry_run: args.dry_run, }; let logging = LoggingConfig { @@ -2018,7 +2016,6 @@ mod tests { output_format: Some(RuntimeOutputFormatArg::Terminal), verbose: true, dry_run: true, - no_color: true, log_filter: Some("debug".to_owned()), log_stdout: false, identity_path: Some(PathBuf::from("custom-identity.json")), @@ -2073,7 +2070,6 @@ mod tests { OutputConfig { format: OutputFormat::Terminal, verbosity: Verbosity::Verbose, - color: false, dry_run: true, } ); @@ -2226,7 +2222,6 @@ mod tests { OutputConfig { format: OutputFormat::Json, verbosity: Verbosity::Normal, - color: true, dry_run: false, } ); diff --git a/src/runtime/provider.rs b/src/runtime/provider.rs @@ -275,7 +275,6 @@ mod tests { output: OutputConfig { format: OutputFormat::Terminal, verbosity: Verbosity::Normal, - color: true, dry_run: false, }, interaction: InteractionConfig { diff --git a/src/runtime/sdk.rs b/src/runtime/sdk.rs @@ -1351,7 +1351,6 @@ mod tests { output: OutputConfig { format: OutputFormat::Json, verbosity: Verbosity::Normal, - color: false, dry_run: false, }, interaction: InteractionConfig { diff --git a/src/runtime/sync.rs b/src/runtime/sync.rs @@ -2223,7 +2223,6 @@ mod tests { output: OutputConfig { format: OutputFormat::Terminal, verbosity: Verbosity::Normal, - color: true, dry_run: false, }, interaction: InteractionConfig { diff --git a/src/view/runtime.rs b/src/view/runtime.rs @@ -201,7 +201,6 @@ pub struct LegacyPathRuntimeView { pub struct OutputRuntimeView { pub format: String, pub verbosity: String, - pub color: bool, pub dry_run: bool, } diff --git a/tests/target_cli.rs b/tests/target_cli.rs @@ -2820,7 +2820,6 @@ fn terminal_global_presentation_flags_are_deterministic() { for args in [ &["workspace", "get"][..], &["--quiet", "workspace", "get"][..], - &["--no-color", "workspace", "get"][..], ] { let output = radroots().args(args).output().expect("run terminal flag"); @@ -2847,6 +2846,19 @@ fn terminal_global_presentation_flags_are_deterministic() { } #[test] +fn removed_no_color_flag_is_rejected() { + let output = radroots() + .args(["--no-color", "workspace", "get"]) + .output() + .expect("run removed no-color flag"); + + assert_eq!(output.status.code(), Some(2)); + assert!(output.stdout.is_empty()); + let stderr = String::from_utf8(output.stderr).expect("utf8 stderr"); + assert!(stderr.contains("unexpected argument '--no-color'")); +} + +#[test] fn human_output_format_is_rejected() { let output = radroots() .args(["--format", "human", "workspace", "get"])