From e4f8b0eb6081d8c228e9789d6aacca7f677a222f Mon Sep 17 00:00:00 2001 From: Amol Kapoor Date: Sun, 18 Jan 2026 00:10:40 -0500 Subject: [PATCH 1/3] feat(cli): Enable --yolo flag for all builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the feature gate from the `--yolo` (alias: `--dangerously-bypass-approvals-and-sandbox`) CLI flag so it works in minimal Nori builds without requiring the `codex-features` Cargo feature. When the flag is enabled, it sets: - `SandboxMode::DangerFullAccess` (no filesystem restrictions) - `AskForApproval::Never` (no confirmation prompts) The flag maintains `conflicts_with_all` for codex-features builds to prevent confusing interactions with `--full-auto` and `-a` approval policy flags. 🤖 Generated with [Nori](https://nori.ai) Co-Authored-By: Nori --- codex-rs/core/docs.md | 3 ++- codex-rs/tui/docs.md | 10 ++++++- codex-rs/tui/src/cli.rs | 60 ++++++++++++++++++++++++++++++++++++----- codex-rs/tui/src/lib.rs | 9 ++++++- 4 files changed, 73 insertions(+), 9 deletions(-) diff --git a/codex-rs/core/docs.md b/codex-rs/core/docs.md index 365e5a530..1443988d2 100644 --- a/codex-rs/core/docs.md +++ b/codex-rs/core/docs.md @@ -139,7 +139,8 @@ The `UserNotifier` supports two delivery modes: └─────────────────────┘ └─────────────────────┘ ``` -The `use_native` flag controls whether native notifications are sent when no external command is configured. Production code passes `true`, test code passes `false` to avoid notification spam during tests. + +Notification dispatch priority: external command takes precedence over native. If `notify_command` is `Some` (even if empty), native notifications are skipped. An empty `notify_command` (`Some(vec![])`) disables all notifications - the test infrastructure uses this by default via `load_default_config_for_test()`. **Window Focus (X11 Linux):** diff --git a/codex-rs/tui/docs.md b/codex-rs/tui/docs.md index b539cfc64..2fbe02f9f 100644 --- a/codex-rs/tui/docs.md +++ b/codex-rs/tui/docs.md @@ -586,9 +586,17 @@ For E2E testing, `NORI_SYNC_SYSTEM_INFO=1` env var enables synchronous collectio **Configuration Flow:** TUI respects config overrides from: -1. CLI flags (`--model` always available; `--sandbox`, `--oss`, `-a`, `--full-auto`, etc. require `codex-features`) +1. CLI flags (`--model` and `--yolo` always available; `--sandbox`, `--oss`, `-a`, `--full-auto`, etc. require `codex-features`) 2. `-c key=value` overrides 3. Config profiles (`-p profile-name`) 4. `~/.nori/cli/config.toml` +**YOLO Mode:** + +The `--yolo` flag (alias: `--dangerously-bypass-approvals-and-sandbox`) bypasses all safety mechanisms: +- Sets `SandboxMode::DangerFullAccess` (no filesystem restrictions) +- Sets `AskForApproval::Never` (no confirmation prompts for commands or file writes) + +This flag works in all builds (with or without `codex-features`). In `run_main()`, when enabled, the flag overrides any configured sandbox or approval policies before passing to `ConfigOverrides`. + Created and maintained by Nori. diff --git a/codex-rs/tui/src/cli.rs b/codex-rs/tui/src/cli.rs index ff880a14c..97907002a 100644 --- a/codex-rs/tui/src/cli.rs +++ b/codex-rs/tui/src/cli.rs @@ -71,12 +71,22 @@ pub struct Cli { /// Skip all confirmation prompts and execute commands without sandboxing. /// EXTREMELY DANGEROUS. Intended solely for running in environments that are externally sandboxed. - #[cfg(feature = "codex-features")] - #[arg( - long = "dangerously-bypass-approvals-and-sandbox", - alias = "yolo", - default_value_t = false, - conflicts_with_all = ["approval_policy", "full_auto"] + #[cfg_attr( + feature = "codex-features", + arg( + long = "dangerously-bypass-approvals-and-sandbox", + alias = "yolo", + default_value_t = false, + conflicts_with_all = ["approval_policy", "full_auto"] + ) + )] + #[cfg_attr( + not(feature = "codex-features"), + arg( + long = "dangerously-bypass-approvals-and-sandbox", + alias = "yolo", + default_value_t = false + ) )] pub dangerously_bypass_approvals_and_sandbox: bool, @@ -107,3 +117,41 @@ pub struct Cli { #[arg(long = "skip-trust-directory", default_value_t = false)] pub skip_trust_directory: bool, } + +#[cfg(test)] +mod tests { + use super::*; + use clap::Parser; + + /// Test that --yolo flag is recognized and sets dangerously_bypass_approvals_and_sandbox to true. + /// This flag should work without the codex-features feature flag. + #[test] + fn test_yolo_flag_is_recognized() { + let cli = Cli::try_parse_from(["nori", "--yolo"]).expect("--yolo should be a valid flag"); + assert!( + cli.dangerously_bypass_approvals_and_sandbox, + "--yolo should set dangerously_bypass_approvals_and_sandbox to true" + ); + } + + /// Test that --dangerously-bypass-approvals-and-sandbox works as the full flag name. + #[test] + fn test_dangerously_bypass_flag_is_recognized() { + let cli = Cli::try_parse_from(["nori", "--dangerously-bypass-approvals-and-sandbox"]) + .expect("--dangerously-bypass-approvals-and-sandbox should be a valid flag"); + assert!( + cli.dangerously_bypass_approvals_and_sandbox, + "--dangerously-bypass-approvals-and-sandbox should set the field to true" + ); + } + + /// Test that without --yolo, the field defaults to false. + #[test] + fn test_yolo_flag_defaults_to_false() { + let cli = Cli::try_parse_from(["nori"]).expect("basic parsing should work"); + assert!( + !cli.dangerously_bypass_approvals_and_sandbox, + "dangerously_bypass_approvals_and_sandbox should default to false" + ); + } +} diff --git a/codex-rs/tui/src/lib.rs b/codex-rs/tui/src/lib.rs index f3c02ce3f..3ce02560f 100644 --- a/codex-rs/tui/src/lib.rs +++ b/codex-rs/tui/src/lib.rs @@ -201,7 +201,14 @@ pub async fn run_main( #[cfg(not(feature = "codex-features"))] let (sandbox_mode, approval_policy): (Option, Option) = - (None, None); + if cli.dangerously_bypass_approvals_and_sandbox { + ( + Some(SandboxMode::DangerFullAccess), + Some(AskForApproval::Never), + ) + } else { + (None, None) + }; // Map the legacy --search flag to the new feature toggle. #[cfg(feature = "codex-features")] From a2cc244dc7624f5016062949ba100ee807ea974e Mon Sep 17 00:00:00 2001 From: Amol Kapoor Date: Sun, 18 Jan 2026 00:19:48 -0500 Subject: [PATCH 2/3] fix(cli): Update test to expect --yolo flag in non-codex-features builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test `dangerous_bypass_flag_rejected_without_codex_features` was asserting that the flag should be rejected, but we've now deliberately made it available in all builds. Updated the test to verify the flag IS accepted and added a test for the --yolo alias. 🤖 Generated with [Nori](https://nori.ai) Co-Authored-By: Nori --- codex-rs/cli/src/main.rs | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/codex-rs/cli/src/main.rs b/codex-rs/cli/src/main.rs index 66d05db50..68827f114 100644 --- a/codex-rs/cli/src/main.rs +++ b/codex-rs/cli/src/main.rs @@ -1070,15 +1070,31 @@ mod tests { ); } - /// When codex-features is disabled, --dangerously-bypass-approvals-and-sandbox flag should not be recognized + /// The --dangerously-bypass-approvals-and-sandbox (--yolo) flag should be recognized + /// in all builds, regardless of whether codex-features is enabled #[test] #[cfg(not(feature = "codex-features"))] - fn dangerous_bypass_flag_rejected_without_codex_features() { - let result = - MultitoolCli::try_parse_from(["nori", "--dangerously-bypass-approvals-and-sandbox"]); + fn dangerous_bypass_flag_accepted_without_codex_features() { + let cli = + MultitoolCli::try_parse_from(["nori", "--dangerously-bypass-approvals-and-sandbox"]) + .expect( + "--dangerously-bypass-approvals-and-sandbox should be accepted in all builds", + ); assert!( - result.is_err(), - "--dangerously-bypass-approvals-and-sandbox should be rejected when codex-features is disabled" + cli.interactive.dangerously_bypass_approvals_and_sandbox, + "--dangerously-bypass-approvals-and-sandbox should set the field to true" + ); + } + + /// The --yolo alias should be recognized in all builds + #[test] + #[cfg(not(feature = "codex-features"))] + fn yolo_alias_accepted_without_codex_features() { + let cli = MultitoolCli::try_parse_from(["nori", "--yolo"]) + .expect("--yolo should be accepted in all builds"); + assert!( + cli.interactive.dangerously_bypass_approvals_and_sandbox, + "--yolo should set dangerously_bypass_approvals_and_sandbox to true" ); } From be77948915de7bd7707d0545aebd894174328aa5 Mon Sep 17 00:00:00 2001 From: Amol Kapoor Date: Sun, 18 Jan 2026 00:46:42 -0500 Subject: [PATCH 3/3] fix(acp): Honor AskForApproval::Never policy in approval handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The --yolo flag was parsing correctly but the ACP backend was still prompting for approvals. The run_approval_handler function now checks the approval policy and auto-approves immediately when approval_policy == AskForApproval::Never. This completes the data flow: CLI --yolo flag → AskForApproval::Never → AcpBackendConfig → run_approval_handler() → auto-approve 🤖 Generated with [Nori](https://nori.ai) Co-Authored-By: Nori --- codex-rs/acp/docs.md | 16 +++++++++++++++- codex-rs/acp/src/backend.rs | 16 ++++++++++++++++ codex-rs/cli/docs.md | 5 ++++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/codex-rs/acp/docs.md b/codex-rs/acp/docs.md index ca988aaa3..e1ff7f7ac 100644 --- a/codex-rs/acp/docs.md +++ b/codex-rs/acp/docs.md @@ -377,7 +377,21 @@ Session discovery logic (finding files in ~/.codex, ~/.gemini, ~/.claude) is def **Approval Bridging:** -The ACP module bridges permission requests to Codex's approval UI. Approval requests are handled **immediately** (not deferred) to avoid deadlocks: +The ACP module bridges permission requests to Codex's approval UI via `run_approval_handler()`. The handler respects the configured `approval_policy` from `AcpBackendConfig`: + +| Policy | Behavior | +|--------|----------| +| `AskForApproval::Never` | Auto-approve all requests immediately (yolo mode) | +| `AskForApproval::OnFailure` | Prompt only when operations fail | +| `AskForApproval::UnlessAllowListed` | Prompt except for allowed operations | + +When `approval_policy == AskForApproval::Never` (set via `--yolo` or `--dangerously-bypass-approvals-and-sandbox` CLI flags), the approval handler sends `ReviewDecision::Approved` without forwarding requests to the TUI. This completes the data flow: + +``` +CLI --yolo flag → AskForApproval::Never → AcpBackendConfig → run_approval_handler() → auto-approve +``` + +For all other policies, approval requests are handled **immediately** (not deferred) to avoid deadlocks: ``` ┌─────────────────────────┐ ApprovalRequest ┌─────────────────────────┐ diff --git a/codex-rs/acp/src/backend.rs b/codex-rs/acp/src/backend.rs index d371bfd3c..74d12adeb 100644 --- a/codex-rs/acp/src/backend.rs +++ b/codex-rs/acp/src/backend.rs @@ -308,6 +308,7 @@ impl AcpBackend { Arc::clone(&pending_approvals), Arc::clone(&user_notifier), cwd.clone(), + config.approval_policy, )); Ok(backend) @@ -719,14 +720,29 @@ impl AcpBackend { } /// Background task to handle approval requests from the ACP connection. + /// + /// When `approval_policy` is `AskForApproval::Never` (yolo mode), requests + /// are auto-approved without prompting the user. async fn run_approval_handler( mut approval_rx: mpsc::Receiver, event_tx: mpsc::Sender, pending_approvals: Arc>>, user_notifier: Arc, cwd: PathBuf, + approval_policy: AskForApproval, ) { while let Some(request) = approval_rx.recv().await { + // If approval_policy is Never (yolo mode), auto-approve immediately + if approval_policy == AskForApproval::Never { + debug!( + target: "acp_event_flow", + call_id = %request.event.call_id(), + "Auto-approving request (approval_policy=Never)" + ); + let _ = request.response_tx.send(ReviewDecision::Approved); + continue; + } + // Send the appropriate approval request event to TUI based on operation type. // Use the call_id as the event wrapper ID so that the TUI can // correctly route the user's decision back to this pending request. diff --git a/codex-rs/cli/docs.md b/codex-rs/cli/docs.md index 0e90f9f55..70d32947a 100644 --- a/codex-rs/cli/docs.md +++ b/codex-rs/cli/docs.md @@ -68,13 +68,16 @@ The following CLI flags are gated behind the `codex-features` Cargo feature and | `--sandbox` | `-s` | Select sandbox policy | | `--ask-for-approval` | `-a` | Configure approval policy | | `--full-auto` | | Sandboxed automatic execution mode | -| `--dangerously-bypass-approvals-and-sandbox` | | Skip all safety checks (dangerous) | | `--search` | | Enable web search tool | | `--enable` | | Enable a feature toggle | | `--disable` | | Disable a feature toggle | Without `codex-features`, passing these flags results in a clap parse error. +**Always-Available Safety Override:** + +The `--dangerously-bypass-approvals-and-sandbox` flag (alias: `--yolo`) is available in all builds regardless of `codex-features`. When set, it configures `approval_policy: AskForApproval::Never`, causing the ACP backend to auto-approve all tool operations without prompting the user. + **Resume Logic (requires `codex-features`):** `nori resume` supports three modes: