detect Bun installs in CLI update banner (#5074)

## Summary
- detect Bun-managed installs in the JavaScript launcher and set a
dedicated environment flag
- show a Bun-specific upgrade command in the update banner when that
flag is present

Fixes #5012

------
https://chatgpt.com/codex/tasks/task_i_68e95c439494832c835bdf34b3b1774e

---------

Co-authored-by: Michael Bolin <mbolin@openai.com>
This commit is contained in:
Jeremy Rose
2025-10-14 10:49:44 -07:00
committed by GitHub
parent 8662162f45
commit d6c5df9a0a
2 changed files with 43 additions and 2 deletions

35
codex-cli/bin/codex.js Executable file → Normal file
View File

@@ -80,6 +80,32 @@ function getUpdatedPath(newDirs) {
return updatedPath; 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 additionalDirs = [];
const pathDir = path.join(archRoot, "path"); const pathDir = path.join(archRoot, "path");
if (existsSync(pathDir)) { if (existsSync(pathDir)) {
@@ -87,9 +113,16 @@ if (existsSync(pathDir)) {
} }
const updatedPath = getUpdatedPath(additionalDirs); 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), { const child = spawn(binaryPath, process.argv.slice(2), {
stdio: "inherit", stdio: "inherit",
env: { ...process.env, PATH: updatedPath, CODEX_MANAGED_BY_NPM: "1" }, env,
}); });
child.on("error", (err) => { child.on("error", (err) => {

View File

@@ -310,6 +310,7 @@ async fn run_ratatui_app(
let current_version = env!("CARGO_PKG_VERSION"); let current_version = env!("CARGO_PKG_VERSION");
let exe = std::env::current_exe()?; 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 managed_by_npm = std::env::var_os("CODEX_MANAGED_BY_NPM").is_some();
let mut content_lines: Vec<Line<'static>> = vec![ let mut content_lines: Vec<Line<'static>> = vec![
@@ -330,7 +331,14 @@ async fn run_ratatui_app(
Line::from(""), 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"; let npm_cmd = "npm install -g @openai/codex@latest";
content_lines.push(Line::from(vec![ content_lines.push(Line::from(vec![
"Run ".into(), "Run ".into(),