Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions rust/crates/runtime/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,22 @@ use std::sync::Mutex;
static EMITTED_CONFIG_WARNINGS: std::sync::OnceLock<Mutex<HashSet<String>>> =
std::sync::OnceLock::new();

/// When set to `true`, `emit_config_warning_once` silently drops all prose
/// deprecation warnings instead of writing them to stderr. Set this flag
/// before any settings load when `--output-format json` is active so that
/// JSON-mode machine consumers see empty stderr on success. (#824)
static SUPPRESS_CONFIG_WARNINGS_STDERR: std::sync::atomic::AtomicBool =
std::sync::atomic::AtomicBool::new(false);

/// Call this once at startup when `--output-format json` is active.
pub fn suppress_config_warnings_for_json_mode() {
SUPPRESS_CONFIG_WARNINGS_STDERR.store(true, std::sync::atomic::Ordering::Relaxed);
}

fn emit_config_warning_once(warning: &str) {
if SUPPRESS_CONFIG_WARNINGS_STDERR.load(std::sync::atomic::Ordering::Relaxed) {
return;
}
let set = EMITTED_CONFIG_WARNINGS.get_or_init(|| Mutex::new(HashSet::new()));
let mut guard = set.lock().unwrap_or_else(|e| e.into_inner());
if guard.insert(warning.to_string()) {
Expand Down
12 changes: 6 additions & 6 deletions rust/crates/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ pub use compact::{
get_compact_continuation_message, should_compact, CompactionConfig, CompactionResult,
};
pub use config::{
ConfigEntry, ConfigError, ConfigLoader, ConfigSource, McpConfigCollection,
McpManagedProxyServerConfig, McpOAuthConfig, McpRemoteServerConfig, McpSdkServerConfig,
McpServerConfig, McpStdioServerConfig, McpTransport, McpWebSocketServerConfig, OAuthConfig,
ProviderFallbackConfig, ResolvedPermissionMode, RuntimeConfig, RuntimeFeatureConfig,
RuntimeHookConfig, RuntimePermissionRuleConfig, RuntimePluginConfig, ScopedMcpServerConfig,
CLAW_SETTINGS_SCHEMA_NAME,
suppress_config_warnings_for_json_mode, ConfigEntry, ConfigError, ConfigLoader, ConfigSource,
McpConfigCollection, McpManagedProxyServerConfig, McpOAuthConfig, McpRemoteServerConfig,
McpSdkServerConfig, McpServerConfig, McpStdioServerConfig, McpTransport,
McpWebSocketServerConfig, OAuthConfig, ProviderFallbackConfig, ResolvedPermissionMode,
RuntimeConfig, RuntimeFeatureConfig, RuntimeHookConfig, RuntimePermissionRuleConfig,
RuntimePluginConfig, ScopedMcpServerConfig, CLAW_SETTINGS_SCHEMA_NAME,
};
pub use config_validate::{
check_unsupported_format, format_diagnostics, validate_config_file, ConfigDiagnostic,
Expand Down
10 changes: 10 additions & 0 deletions rust/crates/rusty-claude-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,16 @@ fn plugin_load_failure_json(failure: &plugins::PluginLoadFailure) -> Value {

fn run() -> Result<(), Box<dyn std::error::Error>> {
let args: Vec<String> = env::args().skip(1).collect();
// #824: suppress config deprecation prose warnings to stderr when JSON
// output mode is active. Scan the raw argv before parse_args so the
// suppression is in place before any settings file is loaded.
let json_mode = args
.windows(2)
.any(|w| w[0] == "--output-format" && w[1] == "json")
|| args.iter().any(|a| a == "--output-format=json");
if json_mode {
runtime::suppress_config_warnings_for_json_mode();
}
match parse_args(&args)? {
CliAction::DumpManifests {
output_format,
Expand Down
Loading