diff --git a/codex-cli/bin/codex.js b/codex-cli/bin/codex.js old mode 100755 new mode 100644 index 17dd98a8e82..805be85af88 --- a/codex-cli/bin/codex.js +++ b/codex-cli/bin/codex.js @@ -80,6 +80,32 @@ function getUpdatedPath(newDirs) { return updatedPath; } +/** + * Use heuristics to detect the package manager that was used to install Codex + * in order to give the user a hint about how to update it. + */ +function detectPackageManager() { + const userAgent = process.env.npm_config_user_agent || ""; + if (/\bbun\//.test(userAgent)) { + return "bun"; + } + + const execPath = process.env.npm_execpath || ""; + if (execPath.includes("bun")) { + return "bun"; + } + + if ( + process.env.BUN_INSTALL || + process.env.BUN_INSTALL_GLOBAL_DIR || + process.env.BUN_INSTALL_BIN_DIR + ) { + return "bun"; + } + + return userAgent ? "npm" : null; +} + const additionalDirs = []; const pathDir = path.join(archRoot, "path"); if (existsSync(pathDir)) { @@ -87,9 +113,16 @@ if (existsSync(pathDir)) { } const updatedPath = getUpdatedPath(additionalDirs); +const env = { ...process.env, PATH: updatedPath }; +const packageManagerEnvVar = + detectPackageManager() === "bun" + ? "CODEX_MANAGED_BY_BUN" + : "CODEX_MANAGED_BY_NPM"; +env[packageManagerEnvVar] = "1"; + const child = spawn(binaryPath, process.argv.slice(2), { stdio: "inherit", - env: { ...process.env, PATH: updatedPath, CODEX_MANAGED_BY_NPM: "1" }, + env, }); child.on("error", (err) => { diff --git a/codex-rs/tui/src/lib.rs b/codex-rs/tui/src/lib.rs index 5d7188c0361..7d7412e0a4f 100644 --- a/codex-rs/tui/src/lib.rs +++ b/codex-rs/tui/src/lib.rs @@ -310,6 +310,7 @@ async fn run_ratatui_app( let current_version = env!("CARGO_PKG_VERSION"); let exe = std::env::current_exe()?; + let managed_by_bun = std::env::var_os("CODEX_MANAGED_BY_BUN").is_some(); let managed_by_npm = std::env::var_os("CODEX_MANAGED_BY_NPM").is_some(); let mut content_lines: Vec> = vec![ @@ -330,7 +331,14 @@ async fn run_ratatui_app( Line::from(""), ]; - if managed_by_npm { + if managed_by_bun { + let bun_cmd = "bun install -g @openai/codex@latest"; + content_lines.push(Line::from(vec![ + "Run ".into(), + bun_cmd.cyan(), + " to update.".into(), + ])); + } else if managed_by_npm { let npm_cmd = "npm install -g @openai/codex@latest"; content_lines.push(Line::from(vec![ "Run ".into(),