From 2fe4be1aa98b1706ac911ebaebc16a6c31407dcb Mon Sep 17 00:00:00 2001 From: Michael Bolin Date: Sat, 21 Feb 2026 00:20:42 -0800 Subject: [PATCH] fix: codex-arg0 no longer depends on codex-core (#12434) ## Why `codex-rs/arg0` only needed two things from `codex-core`: - the `find_codex_home()` wrapper - the special argv flag used for the internal `apply_patch` self-invocation path That made `codex-arg0` depend on `codex-core` for a very small surface area. This change removes that dependency edge and moves the shared `apply_patch` invocation flag to a more natural boundary (`codex-apply-patch`) while keeping the contract explicitly documented. ## What Changed - Moved the internal `apply_patch` argv[1] flag constant out of `codex-core` and into `codex-apply-patch`. - Renamed the constant to `CODEX_CORE_APPLY_PATCH_ARG1` and documented that it is part of the Codex core process-invocation contract (even though it now lives in `codex-apply-patch`). - Updated `arg0`, the core apply-patch runtime, and the `codex-exec` apply-patch test to import the constant from `codex-apply-patch`. - Updated `codex-rs/arg0` to call `codex_utils_home_dir::find_codex_home()` directly instead of `codex_core::config::find_codex_home()`. - Removed the `codex-core` dependency from `codex-rs/arg0` and added the needed direct dependency on `codex-utils-home-dir`. - Added `codex-apply-patch` as a dev-dependency for `codex-rs/exec` tests (the apply-patch test now imports the moved constant directly). ## Verification - `cargo test -p codex-apply-patch` - `cargo test -p codex-arg0` - `cargo test -p codex-core --lib apply_patch` - `cargo test -p codex-exec test_standalone_exec_cli_can_use_apply_patch` - `cargo shear` --- codex-rs/Cargo.lock | 3 ++- codex-rs/apply-patch/src/lib.rs | 9 +++++++++ codex-rs/arg0/Cargo.toml | 2 +- codex-rs/arg0/src/lib.rs | 13 +++++++------ codex-rs/core/src/apply_patch.rs | 5 ++--- codex-rs/core/src/lib.rs | 1 - codex-rs/core/src/tools/runtimes/apply_patch.rs | 7 +++++-- codex-rs/exec/Cargo.toml | 1 + codex-rs/exec/tests/suite/apply_patch.rs | 4 ++-- 9 files changed, 29 insertions(+), 16 deletions(-) diff --git a/codex-rs/Cargo.lock b/codex-rs/Cargo.lock index e9fd6ed16..42521a48d 100644 --- a/codex-rs/Cargo.lock +++ b/codex-rs/Cargo.lock @@ -1398,8 +1398,8 @@ version = "0.0.0" dependencies = [ "anyhow", "codex-apply-patch", - "codex-core", "codex-linux-sandbox", + "codex-utils-home-dir", "dotenvy", "tempfile", "tokio", @@ -1735,6 +1735,7 @@ dependencies = [ "anyhow", "assert_cmd", "clap", + "codex-apply-patch", "codex-arg0", "codex-cloud-requirements", "codex-core", diff --git a/codex-rs/apply-patch/src/lib.rs b/codex-rs/apply-patch/src/lib.rs index f58055f45..1fc60474b 100644 --- a/codex-rs/apply-patch/src/lib.rs +++ b/codex-rs/apply-patch/src/lib.rs @@ -25,6 +25,15 @@ use crate::invocation::ExtractHeredocError; /// Detailed instructions for gpt-4.1 on how to use the `apply_patch` tool. pub const APPLY_PATCH_TOOL_INSTRUCTIONS: &str = include_str!("../apply_patch_tool_instructions.md"); +/// Special argv[1] flag used when the Codex executable self-invokes to run the +/// internal `apply_patch` path. +/// +/// Although this constant lives in `codex-apply-patch` (to avoid forcing +/// `codex-arg0` to depend on `codex-core`), it is part of the "codex core" +/// process-invocation contract between the apply-patch runtime and the arg0 +/// dispatcher. +pub const CODEX_CORE_APPLY_PATCH_ARG1: &str = "--codex-run-as-apply-patch"; + #[derive(Debug, Error, PartialEq)] pub enum ApplyPatchError { #[error(transparent)] diff --git a/codex-rs/arg0/Cargo.toml b/codex-rs/arg0/Cargo.toml index c82bdd58d..c5d968132 100644 --- a/codex-rs/arg0/Cargo.toml +++ b/codex-rs/arg0/Cargo.toml @@ -14,8 +14,8 @@ workspace = true [dependencies] anyhow = { workspace = true } codex-apply-patch = { workspace = true } -codex-core = { workspace = true } codex-linux-sandbox = { workspace = true } +codex-utils-home-dir = { workspace = true } dotenvy = { workspace = true } tempfile = { workspace = true } tokio = { workspace = true, features = ["rt-multi-thread"] } diff --git a/codex-rs/arg0/src/lib.rs b/codex-rs/arg0/src/lib.rs index dd89baeff..3ac7e017f 100644 --- a/codex-rs/arg0/src/lib.rs +++ b/codex-rs/arg0/src/lib.rs @@ -3,7 +3,8 @@ use std::future::Future; use std::path::Path; use std::path::PathBuf; -use codex_core::CODEX_APPLY_PATCH_ARG1; +use codex_apply_patch::CODEX_CORE_APPLY_PATCH_ARG1; +use codex_utils_home_dir::find_codex_home; #[cfg(unix)] use std::os::unix::fs::symlink; use tempfile::TempDir; @@ -46,7 +47,7 @@ pub fn arg0_dispatch() -> Option { } let argv1 = args.next().unwrap_or_default(); - if argv1 == CODEX_APPLY_PATCH_ARG1 { + if argv1 == CODEX_CORE_APPLY_PATCH_ARG1 { let patch_arg = args.next().and_then(|s| s.to_str().map(str::to_owned)); let exit_code = match patch_arg { Some(patch_arg) => { @@ -58,7 +59,7 @@ pub fn arg0_dispatch() -> Option { } } None => { - eprintln!("Error: {CODEX_APPLY_PATCH_ARG1} requires a UTF-8 PATCH argument."); + eprintln!("Error: {CODEX_CORE_APPLY_PATCH_ARG1} requires a UTF-8 PATCH argument."); 1 } }; @@ -139,7 +140,7 @@ const ILLEGAL_ENV_VAR_PREFIX: &str = "CODEX_"; /// Security: Do not allow `.env` files to create or modify any variables /// with names starting with `CODEX_`. fn load_dotenv() { - if let Ok(codex_home) = codex_core::config::find_codex_home() + if let Ok(codex_home) = find_codex_home() && let Ok(iter) = dotenvy::from_path_iter(codex_home.join(".env")) { set_filtered(iter); @@ -175,7 +176,7 @@ where /// IMPORTANT: This function modifies the PATH environment variable, so it MUST /// be called before multiple threads are spawned. pub fn prepend_path_entry_for_codex_aliases() -> std::io::Result { - let codex_home = codex_core::config::find_codex_home()?; + let codex_home = find_codex_home()?; #[cfg(not(debug_assertions))] { // Guard against placing helpers in system temp directories outside debug builds. @@ -242,7 +243,7 @@ pub fn prepend_path_entry_for_codex_aliases() -> std::io::Result anyhow::Result<()> { fs::write(&absolute_path, "original content\n")?; Command::new(codex_utils_cargo_bin::cargo_bin("codex-exec")?) - .arg(CODEX_APPLY_PATCH_ARG1) + .arg(CODEX_CORE_APPLY_PATCH_ARG1) .arg( r#"*** Begin Patch *** Update File: source.txt