use crate::VerbosityLevel;
use claude_runner_core::EffortLevel;
use error_tools::{ Error, Result };
use super::parse::{ CliArgs, ExpectStrategy, parse_u8_bounded };
pub( super ) fn env_bool( var : &str ) -> bool
{
std::env::var( var ).ok()
.is_some_and( | v | matches!( v.to_lowercase().as_str(), "1" | "true" ) )
}
pub( super ) fn env_str( var : &str ) -> Option< String >
{
std::env::var( var ).ok().filter( | v | !v.is_empty() )
}
#[ allow( clippy::too_many_lines ) ] pub( crate ) fn apply_env_vars( parsed : &mut CliArgs ) -> Result< () >
{
if parsed.message.is_none() { parsed.message = env_str( "CLR_MESSAGE" ); }
if !parsed.print_mode { parsed.print_mode = env_bool( "CLR_PRINT" ); }
if parsed.model.is_none() { parsed.model = env_str( "CLR_MODEL" ); }
if !parsed.verbose { parsed.verbose = env_bool( "CLR_VERBOSE" ); }
if !parsed.no_skip_permissions { parsed.no_skip_permissions = env_bool( "CLR_NO_SKIP_PERMISSIONS" ); }
if !parsed.interactive { parsed.interactive = env_bool( "CLR_INTERACTIVE" ); }
if !parsed.new_session { parsed.new_session = env_bool( "CLR_NEW_SESSION" ); }
if parsed.dir.is_none() { parsed.dir = env_str( "CLR_DIR" ); }
if parsed.max_tokens.is_none()
{
if let Some( v ) = env_str( "CLR_MAX_TOKENS" ) { parsed.max_tokens = v.parse::< u32 >().ok(); }
}
if parsed.session_dir.is_none() { parsed.session_dir = env_str( "CLR_SESSION_DIR" ); }
if !parsed.dry_run { parsed.dry_run = env_bool( "CLR_DRY_RUN" ); }
if parsed.verbosity.is_none()
{
if let Some( v ) = env_str( "CLR_VERBOSITY" )
{
if let Ok( level ) = v.parse::< VerbosityLevel >() { parsed.verbosity = Some( level ); }
}
}
if !parsed.trace { parsed.trace = env_bool( "CLR_TRACE" ); }
if !parsed.no_ultrathink { parsed.no_ultrathink = env_bool( "CLR_NO_ULTRATHINK" ); }
if parsed.system_prompt.is_none() { parsed.system_prompt = env_str( "CLR_SYSTEM_PROMPT" ); }
if parsed.append_system_prompt.is_none(){ parsed.append_system_prompt = env_str( "CLR_APPEND_SYSTEM_PROMPT" ); }
if parsed.effort.is_none()
{
if let Some( v ) = env_str( "CLR_EFFORT" ) { parsed.effort = v.parse::< EffortLevel >().ok(); }
}
if !parsed.no_effort_max { parsed.no_effort_max = env_bool( "CLR_NO_EFFORT_MAX" ); }
if !parsed.no_chrome { parsed.no_chrome = env_bool( "CLR_NO_CHROME" ); }
if !parsed.no_persist { parsed.no_persist = env_bool( "CLR_NO_PERSIST" ); }
if parsed.json_schema.is_none() { parsed.json_schema = env_str( "CLR_JSON_SCHEMA" ); }
if parsed.mcp_config.is_empty()
{
if let Some( v ) = env_str( "CLR_MCP_CONFIG" ) { parsed.mcp_config.push( v ); }
}
if parsed.file.is_none() { parsed.file = env_str( "CLR_FILE" ); }
if !parsed.strip_fences { parsed.strip_fences = env_bool( "CLR_STRIP_FENCES" ); }
if !parsed.keep_claudecode { parsed.keep_claudecode = env_bool( "CLR_KEEP_CLAUDECODE" ); }
if parsed.subdir.is_none()
{
if let Some( v ) = env_str( "CLR_SUBDIR" )
{
if !v.contains( '/' ) { parsed.subdir = Some( v ); }
}
}
if parsed.output_file.is_none() { parsed.output_file = env_str( "CLR_OUTPUT_FILE" ); }
if parsed.expect.is_none() { parsed.expect = env_str( "CLR_EXPECT" ); }
if parsed.expect_strategy.is_none()
{
if let Some( v ) = env_str( "CLR_EXPECT_STRATEGY" )
{
parsed.expect_strategy = Some(
v.parse::< ExpectStrategy >().map_err( | e |
Error::msg( format!( "CLR_EXPECT_STRATEGY: {e}" ) )
)?
);
}
}
if parsed.max_sessions.is_none()
{
if let Some( v ) = env_str( "CLR_MAX_SESSIONS" )
{
parsed.max_sessions = v.parse::< u32 >().ok();
}
}
if parsed.retry_on_transient.is_none()
{
if let Some( v ) = env_str( "CLR_RETRY_ON_TRANSIENT" )
{
parsed.retry_on_transient = v.parse::< u8 >().ok();
}
}
if parsed.transient_delay.is_none()
{
if let Some( v ) = env_str( "CLR_TRANSIENT_DELAY" )
{
parsed.transient_delay = v.parse::< u32 >().ok();
}
}
if parsed.timeout.is_none()
{
if let Some( v ) = env_str( "CLR_TIMEOUT" )
{
parsed.timeout = v.parse::< u32 >().ok();
}
}
if parsed.retry_on_account.is_none()
{
if let Some( v ) = env_str( "CLR_RETRY_ON_ACCOUNT" )
{
parsed.retry_on_account = v.parse::< u8 >().ok();
}
}
if parsed.account_delay.is_none()
{
if let Some( v ) = env_str( "CLR_ACCOUNT_DELAY" )
{
parsed.account_delay = v.parse::< u32 >().ok();
}
}
if parsed.retry_on_auth.is_none()
{
if let Some( v ) = env_str( "CLR_RETRY_ON_AUTH" )
{
parsed.retry_on_auth = v.parse::< u8 >().ok();
}
}
if parsed.auth_delay.is_none()
{
if let Some( v ) = env_str( "CLR_AUTH_DELAY" )
{
parsed.auth_delay = v.parse::< u32 >().ok();
}
}
if parsed.retry_on_service.is_none()
{
if let Some( v ) = env_str( "CLR_RETRY_ON_SERVICE" )
{
parsed.retry_on_service = v.parse::< u8 >().ok();
}
}
if parsed.service_delay.is_none()
{
if let Some( v ) = env_str( "CLR_SERVICE_DELAY" )
{
parsed.service_delay = v.parse::< u32 >().ok();
}
}
if parsed.retry_on_process.is_none()
{
if let Some( v ) = env_str( "CLR_RETRY_ON_PROCESS" )
{
parsed.retry_on_process = v.parse::< u8 >().ok();
}
}
if parsed.process_delay.is_none()
{
if let Some( v ) = env_str( "CLR_PROCESS_DELAY" )
{
parsed.process_delay = v.parse::< u32 >().ok();
}
}
if parsed.retry_on_validation.is_none()
{
if let Some( v ) = env_str( "CLR_RETRY_ON_VALIDATION" )
{
parsed.retry_on_validation = Some(
parse_u8_bounded( &v, "--retry-on-validation" ).map_err( | e |
Error::msg( format!( "CLR_RETRY_ON_VALIDATION: {e}" ) )
)?
);
}
}
if parsed.validation_delay.is_none()
{
if let Some( v ) = env_str( "CLR_VALIDATION_DELAY" )
{
parsed.validation_delay = v.parse::< u32 >().ok();
}
}
if parsed.retry_on_runner.is_none()
{
if let Some( v ) = env_str( "CLR_RETRY_ON_RUNNER" )
{
parsed.retry_on_runner = v.parse::< u8 >().ok();
}
}
if parsed.runner_delay.is_none()
{
if let Some( v ) = env_str( "CLR_RUNNER_DELAY" )
{
parsed.runner_delay = v.parse::< u32 >().ok();
}
}
if parsed.retry_on_unknown.is_none()
{
if let Some( v ) = env_str( "CLR_RETRY_ON_UNKNOWN" )
{
parsed.retry_on_unknown = v.parse::< u8 >().ok();
}
}
if parsed.unknown_delay.is_none()
{
if let Some( v ) = env_str( "CLR_UNKNOWN_DELAY" )
{
parsed.unknown_delay = v.parse::< u32 >().ok();
}
}
if parsed.retry_override.is_none()
{
if let Some( v ) = env_str( "CLR_RETRY_OVERRIDE" )
{
parsed.retry_override = v.parse::< u8 >().ok();
}
}
if parsed.retry_override_delay.is_none()
{
if let Some( v ) = env_str( "CLR_RETRY_OVERRIDE_DELAY" )
{
parsed.retry_override_delay = v.parse::< u32 >().ok();
}
}
if parsed.retry_default.is_none()
{
if let Some( v ) = env_str( "CLR_RETRY_DEFAULT" )
{
parsed.retry_default = v.parse::< u8 >().ok();
}
}
if parsed.retry_default_delay.is_none()
{
if let Some( v ) = env_str( "CLR_RETRY_DEFAULT_DELAY" )
{
parsed.retry_default_delay = v.parse::< u32 >().ok();
}
}
if parsed.output_format.is_none() { parsed.output_format = env_str( "CLR_OUTPUT_FORMAT" ); }
if parsed.max_turns.is_none() { parsed.max_turns = env_str( "CLR_MAX_TURNS" ); }
if parsed.allowed_tools.is_none() { parsed.allowed_tools = env_str( "CLR_ALLOWED_TOOLS" ); }
if parsed.disallowed_tools.is_none() { parsed.disallowed_tools = env_str( "CLR_DISALLOWED_TOOLS" ); }
if parsed.max_budget_usd.is_none() { parsed.max_budget_usd = env_str( "CLR_MAX_BUDGET_USD" ); }
if parsed.add_dir.is_none() { parsed.add_dir = env_str( "CLR_ADD_DIR" ); }
if parsed.fallback_model.is_none() { parsed.fallback_model = env_str( "CLR_FALLBACK_MODEL" ); }
if parsed.output_style.is_none()
{
if let Some( v ) = env_str( "CLR_OUTPUT_STYLE" )
{
if !matches!( v.as_str(), "summary" | "raw" )
{
return Err( Error::msg( format!(
"CLR_OUTPUT_STYLE: invalid value '{v}' — expected: summary, raw"
) ) );
}
parsed.output_style = Some( v );
}
}
Ok( () )
}
pub( super ) fn apply_ps_env_vars()
-> ( Option< String >, Option< String >, Vec< u32 >, u64, u64 )
{
let pids = env_str( "CLR_PS_PID" )
.map( | csv |
{
csv.split( ',' )
.filter_map( | s | s.trim().parse::< u32 >().ok() )
.collect()
} )
.unwrap_or_default();
let ancient_secs = env_str( "CLR_PS_ANCIENT_SECS" )
.and_then( | v | v.parse::< u64 >().ok() )
.unwrap_or( 28_800 );
let high_ram_mb = env_str( "CLR_PS_HIGH_RAM_MB" )
.and_then( | v | v.parse::< u64 >().ok() )
.unwrap_or( 400 );
( env_str( "CLR_PS_MODE" ), env_str( "CLR_PS_COLUMNS" ), pids, ancient_secs, high_ram_mb )
}