feat(cli): add update command

This commit is contained in:
aibrahim-oai
2025-08-08 17:18:59 -07:00
parent 307d9957fa
commit b3d47cfa11
3 changed files with 69 additions and 2 deletions

View File

@@ -13,6 +13,10 @@ use codex_cli::login::run_login_with_chatgpt;
use codex_cli::login::run_logout;
use codex_cli::proto;
use codex_common::CliConfigOverrides;
#[cfg(not(debug_assertions))]
use codex_core::config::Config;
#[cfg(not(debug_assertions))]
use codex_core::config::ConfigOverrides;
use codex_exec::Cli as ExecCli;
use codex_tui::Cli as TuiCli;
use std::path::PathBuf;
@@ -68,6 +72,9 @@ enum Subcommand {
/// Apply the latest diff produced by Codex agent as a `git apply` to your local working tree.
#[clap(visible_alias = "a")]
Apply(ApplyCommand),
/// Check for a newer Codex release.
Update,
}
#[derive(Debug, Parser)]
@@ -190,6 +197,9 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
prepend_config_flags(&mut apply_cli.config_overrides, cli.config_overrides);
run_apply_command(apply_cli, None).await?;
}
Some(Subcommand::Update) => {
run_update().await?;
}
}
Ok(())
@@ -211,3 +221,60 @@ fn print_completion(cmd: CompletionCommand) {
let name = "codex";
generate(cmd.shell, &mut app, name, &mut std::io::stdout());
}
#[cfg(not(debug_assertions))]
async fn run_update() -> anyhow::Result<()> {
use codex_tui::updates::check_for_update;
use codex_tui::updates::get_upgrade_version;
let overrides = ConfigOverrides {
model: None,
cwd: None,
approval_policy: None,
sandbox_mode: None,
model_provider: None,
config_profile: None,
codex_linux_sandbox_exe: None,
base_instructions: None,
include_plan_tool: None,
disable_response_storage: None,
show_raw_agent_reasoning: None,
};
let config = Config::load_with_cli_overrides(Vec::new(), overrides)?;
let version_file = config.codex_home.join("version.json");
if let Err(e) = check_for_update(&version_file).await {
#[allow(clippy::print_stderr)]
eprintln!("Failed to check for updates: {e}");
}
let current_version = env!("CARGO_PKG_VERSION");
if let Some(latest_version) = get_upgrade_version(&config) {
println!("Current version: {current_version}");
println!("Latest version: {latest_version}");
let exe = std::env::current_exe()?;
let managed_by_npm = std::env::var_os("CODEX_MANAGED_BY_NPM").is_some();
if managed_by_npm {
println!("Run `npm install -g @openai/codex@latest` to update.");
} else if cfg!(target_os = "macos")
&& (exe.starts_with("/opt/homebrew") || exe.starts_with("/usr/local"))
{
println!("Run `brew upgrade codex` to update.");
} else {
println!(
"See https://github.com/openai/codex/releases/latest for the latest releases and installation options."
);
}
} else {
println!("Codex {current_version} is up to date.");
}
Ok(())
}
#[cfg(debug_assertions)]
async fn run_update() -> anyhow::Result<()> {
println!("Update checking is disabled in debug builds.");
Ok(())
}

View File

@@ -49,7 +49,7 @@ mod tui;
mod user_approval_widget;
#[cfg(not(debug_assertions))]
mod updates;
pub mod updates;
#[cfg(not(debug_assertions))]
use color_eyre::owo_colors::OwoColorize;

View File

@@ -62,7 +62,7 @@ fn read_version_info(version_file: &Path) -> anyhow::Result<VersionInfo> {
Ok(serde_json::from_str(&contents)?)
}
async fn check_for_update(version_file: &Path) -> anyhow::Result<()> {
pub async fn check_for_update(version_file: &Path) -> anyhow::Result<()> {
let ReleaseInfo {
tag_name: latest_tag_name,
} = reqwest::Client::new()