//! Shared command-line flags used by both interactive and non-interactive Codex entry points. use crate::SandboxModeCliArg; use clap::Args; use codex_protocol::config_types::ProfileV2Name; use std::path::PathBuf; #[derive(Args, Clone, Debug, Default)] pub struct SharedCliOptions { /// Optional image(s) to attach to the initial prompt. #[arg( long = "image", short = 'i', value_name = "FILE", value_delimiter = ',', num_args = 1.. )] pub images: Vec, /// Model the agent should use. #[arg(long, short = 'm')] pub model: Option, /// Use open-source provider. #[arg(long = "oss", default_value_t = false)] pub oss: bool, /// Specify which local provider to use (lmstudio or ollama). /// If not specified with --oss, will use config default or show selection. #[arg(long = "local-provider")] pub oss_provider: Option, /// Configuration profile from config.toml to specify default options. #[arg(long = "profile", short = 'p')] pub config_profile: Option, /// Layer $CODEX_HOME/.config.toml on top of the base user config. #[arg(long = "profile-v2")] pub config_profile_v2: Option, /// Select the sandbox policy to use when executing model-generated shell /// commands. #[arg(long = "sandbox", short = 's')] pub sandbox_mode: Option, /// Skip all confirmation prompts and execute commands without sandboxing. /// EXTREMELY DANGEROUS. Intended solely for running in environments that are externally sandboxed. #[arg( long = "dangerously-bypass-approvals-and-sandbox", alias = "yolo", default_value_t = false )] pub dangerously_bypass_approvals_and_sandbox: bool, /// Run enabled hooks without requiring persisted hook trust for this invocation. /// DANGEROUS. Intended only for automation that already vets hook sources. #[arg(long = "dangerously-bypass-hook-trust", default_value_t = false)] pub bypass_hook_trust: bool, /// Tell the agent to use the specified directory as its working root. #[clap(long = "cd", short = 'C', value_name = "DIR")] pub cwd: Option, /// Additional directories that should be writable alongside the primary workspace. #[arg(long = "add-dir", value_name = "DIR", value_hint = clap::ValueHint::DirPath)] pub add_dir: Vec, } impl SharedCliOptions { pub fn inherit_exec_root_options(&mut self, root: &Self) { let self_selected_sandbox_mode = self.sandbox_mode.is_some() || self.dangerously_bypass_approvals_and_sandbox; let Self { images, model, oss, oss_provider, config_profile, config_profile_v2, sandbox_mode, dangerously_bypass_approvals_and_sandbox, bypass_hook_trust, cwd, add_dir, } = self; let Self { images: root_images, model: root_model, oss: root_oss, oss_provider: root_oss_provider, config_profile: root_config_profile, config_profile_v2: root_config_profile_v2, sandbox_mode: root_sandbox_mode, dangerously_bypass_approvals_and_sandbox: root_dangerously_bypass_approvals_and_sandbox, bypass_hook_trust: root_bypass_hook_trust, cwd: root_cwd, add_dir: root_add_dir, } = root; if model.is_none() { model.clone_from(root_model); } if *root_oss { *oss = true; } if oss_provider.is_none() { oss_provider.clone_from(root_oss_provider); } if config_profile.is_none() { config_profile.clone_from(root_config_profile); } if config_profile_v2.is_none() { config_profile_v2.clone_from(root_config_profile_v2); } if sandbox_mode.is_none() { *sandbox_mode = *root_sandbox_mode; } if !self_selected_sandbox_mode { *dangerously_bypass_approvals_and_sandbox = *root_dangerously_bypass_approvals_and_sandbox; } if !*bypass_hook_trust { *bypass_hook_trust = *root_bypass_hook_trust; } if cwd.is_none() { cwd.clone_from(root_cwd); } if !root_images.is_empty() { let mut merged_images = root_images.clone(); merged_images.append(images); *images = merged_images; } if !root_add_dir.is_empty() { let mut merged_add_dir = root_add_dir.clone(); merged_add_dir.append(add_dir); *add_dir = merged_add_dir; } } pub fn apply_subcommand_overrides(&mut self, subcommand: Self) { let subcommand_selected_sandbox_mode = subcommand.sandbox_mode.is_some() || subcommand.dangerously_bypass_approvals_and_sandbox; let Self { images, model, oss, oss_provider, config_profile, config_profile_v2, sandbox_mode, dangerously_bypass_approvals_and_sandbox, bypass_hook_trust, cwd, add_dir, } = subcommand; if let Some(model) = model { self.model = Some(model); } if oss { self.oss = true; } if let Some(oss_provider) = oss_provider { self.oss_provider = Some(oss_provider); } if let Some(config_profile) = config_profile { self.config_profile = Some(config_profile); } if let Some(config_profile_v2) = config_profile_v2 { self.config_profile_v2 = Some(config_profile_v2); } if subcommand_selected_sandbox_mode { self.sandbox_mode = sandbox_mode; self.dangerously_bypass_approvals_and_sandbox = dangerously_bypass_approvals_and_sandbox; } if bypass_hook_trust { self.bypass_hook_trust = true; } if let Some(cwd) = cwd { self.cwd = Some(cwd); } if !images.is_empty() { self.images = images; } if !add_dir.is_empty() { self.add_dir.extend(add_dir); } } }