@@ -168,7 +168,6 @@ class CLILogger {
168168 */
169169 void StopProgress () noexcept {
170170 if (showing_progress_) {
171- LoggingWriteGuard guard;
172171 if (!progress_completed_) {
173172 // Clear the in-place progress line only if not completed
174173 std::cerr << " \r " ;
@@ -255,8 +254,7 @@ class CLILogger {
255254 const int percentage = static_cast <int >(progress * 100 );
256255 std::string progress_text = bar + std::string (" " ) + std::to_string (percentage) + " %" ;
257256 if (!message.empty ()) progress_text += std::string (" - " ) + message;
258- // Write in-place on the same console line using stderr, guarded to bypass interception
259- LoggingWriteGuard guard;
257+ // Write in-place on the same console line using stderr; let interceptor handle quiet mode
260258 std::cerr << " \r " << progress_text;
261259 // Clear any remnants from a longer previous line
262260 int pad = std::max (0 , progress_last_width_ - static_cast <int >(progress_text.size ()));
@@ -460,6 +458,11 @@ namespace {
460458 // a newline (commonly used for in-place progress updates coming from
461459 // external libraries). We bypass the logger to preserve terminal state.
462460 if (buffer_.find (' \r ' ) != std::string::npos) {
461+ // Respect quiet mode: suppress CLI output entirely when disabled
462+ if (!g_initialized || !g_backend || !g_backend->GetConfig ().enable_cli_output ) {
463+ buffer_.clear ();
464+ return ;
465+ }
463466 if (original_) {
464467 original_->sputn (buffer_.data (), static_cast <std::streamsize>(buffer_.size ()));
465468 }
@@ -469,16 +472,34 @@ namespace {
469472
470473 // If line looks like our own logger output (e.g., starts with '[' or begins with ANSI then '['), pass through
471474 if (!buffer_.empty () && (buffer_[0 ] == ' [' || (buffer_[0 ] == ' \033 ' && buffer_.find (" [" ) != std::string::npos))) {
475+ // Respect quiet mode: suppress CLI output when disabled
476+ if (!g_initialized || !g_backend || !g_backend->GetConfig ().enable_cli_output ) {
477+ buffer_.clear ();
478+ return ;
479+ }
480+ // Heuristic: if it looks like a progress bar (e.g., contains '%'), render in-place without newline
481+ bool looks_like_progress = (buffer_.find (' %' ) != std::string::npos);
472482 if (original_) {
473- original_->sputn (buffer_.data (), static_cast <std::streamsize>(buffer_.size ()));
474- original_->sputc (' \n ' );
483+ if (looks_like_progress) {
484+ original_->sputc (' \r ' );
485+ original_->sputn (buffer_.data (), static_cast <std::streamsize>(buffer_.size ()));
486+ // Do not append newline; UpdateProgressDisplay will manage padding and final newline
487+ } else {
488+ original_->sputn (buffer_.data (), static_cast <std::streamsize>(buffer_.size ()));
489+ original_->sputc (' \n ' );
490+ }
475491 }
476492 buffer_.clear ();
477493 return ;
478494 }
479495
480496 // Route or suppress external prints
481497 if (kind_ == StreamKind::StdOut) {
498+ // Respect quiet mode: suppress CLI output entirely when disabled
499+ if (!g_initialized || !g_backend || !g_backend->GetConfig ().enable_cli_output ) {
500+ buffer_.clear ();
501+ return ;
502+ }
482503 if (StartsWith (buffer_, " File: " )) {
483504 // Treat noisy OBJ path echoes as debug-only
484505 hydroc::debug::LogDebug (buffer_);
@@ -492,6 +513,11 @@ namespace {
492513 hydroc::cli::LogInfo (buffer_);
493514 }
494515 } else { // StdErr
516+ // Respect quiet mode: suppress CLI output entirely when disabled
517+ if (!g_initialized || !g_backend || !g_backend->GetConfig ().enable_cli_output ) {
518+ buffer_.clear ();
519+ return ;
520+ }
495521 if (buffer_.find (" Cannot open colormap data file" ) != std::string::npos) {
496522 // Collect for Warnings section only; avoid inline duplication
497523 hydroc::cli::CollectWarning (buffer_);
0 commit comments