Safely update the macOS Codex desktop app from a remote shell while preserving a way back into the app after it quits for the updater.
This is a small Codex-only update and health toolkit. It started as a macOS remote updater for Codex.app and now also includes safe Codex doctor scripts for macOS, Windows, Linux, and WSL.
The macOS app updater uses the normal logged-in Codex.app Sparkle updater UI,
starts a finite backup reopen watchdog, and then verifies that both the Codex
GUI and codex app-server are running again.
This project is Codex-only. It is not intended to update arbitrary apps or packages. See ROADMAP.md for the safe cross-platform Codex app/CLI direction.
- Updating Codex on a Mac you are controlling remotely.
- Checking Codex app, CLI, and app-server health on macOS, Windows, Linux, and WSL.
- Recovering from Codex desktop / Connections / app-server version mismatches.
- Checking the installed Codex GUI version, bundled CLI version, and app-server process from a terminal.
- Avoiding fragile persistent
launchdreopen loops.
- Not a generic updater for non-Codex apps.
- Not a Linux desktop app updater while Codex does not publish a Linux desktop app.
- Not a private updater client.
- Not an updater bypass, app-bundle patcher, or credential helper.
- Not a guarantee that private Codex internal thread state is idle.
The macOS app updater only works on the Mac GUI host that owns the running Codex.app session. If you are viewing that Mac through remote desktop, run the macOS updater on the remote Mac, not on the laptop or phone you are viewing from.
Read the script before you run it. The install path is git clone, not
curl | sh, so you can inspect exactly what will execute.
Safety-relevant facts:
- It does not use
sudo. - It does not install daemons, login items, or persistent
launchdjobs. - It does not store or read credentials.
- It does not call private update endpoints.
- It does not patch or replace the app bundle manually.
- It writes logs and a finite reopen helper script under
~/Library/Logs/codex-remote-update/by default. - It may clear Codex.app's skipped Sparkle update preference so the normal updater can check again.
- It uses macOS Accessibility / System Events only to drive Codex.app's normal updater UI.
- Only
--installcan quit/relaunch Codex.
Start with read-only checks:
scripts/codex-update-doctor.sh --doctorSee SECURITY.md for the full trust boundary.
Install as a Codex skill:
mkdir -p "$HOME/.codex/skills"
git clone https://github.com/neenvm/codex-remote-update.git "$HOME/.codex/skills/codex-remote-update"Optional: make the script callable from any directory on the same Mac.
mkdir -p "$HOME/.local/bin"
ln -sf "$HOME/.codex/skills/codex-remote-update/scripts/codex-remote-update.sh" \
"$HOME/.local/bin/codex-remote-update"
ln -sf "$HOME/.codex/skills/codex-remote-update/scripts/codex-update-doctor.sh" \
"$HOME/.local/bin/codex-update-doctor"Make sure ~/.local/bin is on your PATH if you use the short command.
macOS, Linux, or WSL:
scripts/codex-update-doctor.sh --doctor
scripts/codex-update-doctor.sh --app-status
scripts/codex-update-doctor.sh --cli-status
scripts/codex-update-doctor.sh --app-server-status
scripts/codex-update-doctor.sh --checkWindows PowerShell:
.\scripts\codex-update-doctor.ps1 -Doctor
.\scripts\codex-update-doctor.ps1 -AppStatus
.\scripts\codex-update-doctor.ps1 -CliStatus
.\scripts\codex-update-doctor.ps1 -AppServerStatus
.\scripts\codex-update-doctor.ps1 -Check--doctor / -Doctor is read-only. It reports the OS, Codex desktop app where
supported, Codex CLI, app-server process, and known update path.
From the skill directory:
scripts/codex-remote-update.sh --status
scripts/codex-remote-update.sh --quiet-check
scripts/codex-remote-update.sh --check-only
scripts/codex-remote-update.sh --installIf you installed the optional symlink:
codex-update-doctor --doctor
codex-remote-update --status
codex-remote-update --quiet-check
codex-remote-update --check-only
codex-remote-update --installOver SSH:
ssh <mac-host> 'zsh -lc "codex-remote-update --status"'
ssh <mac-host> 'zsh -lc "codex-remote-update --quiet-check"'
ssh <mac-host> 'zsh -lc "codex-remote-update --install"'- Confirm you are on the Mac that owns the Codex GUI session.
- Run
codex-remote-update --status. - Run
codex-remote-update --quiet-check. - Run
codex-remote-update --check-onlyif you only want to inspect whether Sparkle reports an update. - Run
codex-remote-update --installonly when it is acceptable for Codex to quit and relaunch. - Reconnect if needed, then run
codex-remote-update --statusor inspect~/Library/Logs/codex-remote-update/latest.log.
--install refuses by default if it sees shell-visible Codex worker activity.
Use --force-active only when you explicitly accept interrupting active work.
--install Check for updates and install/relaunch if one is ready. Default.
--check-only Open the updater and report the dialog text without installing.
--status Print installed versions and current Codex processes only.
--quiet-check Report whether shell-visible Codex worker activity looks quiet.
--test-reopen-helper Start only the finite backup reopen watchdog.
--force-active Allow install even if the quiet check sees active workers.
--help Show script help.
CODEX_APP_PATH=/Applications/Codex.app
CODEX_APP_ID=com.openai.codex
CODEX_UPDATE_LOG_DIR=~/Library/Logs/codex-remote-update
CODEX_UPDATE_CHECK_TIMEOUT=45
CODEX_UPDATE_RELAUNCH_TIMEOUT=240
CODEX_UPDATE_HELPER_TIMEOUT=600
CODEX_UPDATE_HELPER_INTERVAL=10
CODEX_UPDATE_ACTIVE_CPU_THRESHOLD=5.0
CODEX_UPDATE_ALLOW_ACTIVE_THREADS=1
Unix/macOS/WSL:
--doctor Read-only OS, Codex app, CLI, and app-server report. Default.
--status Alias for --doctor.
--app-status Report Codex desktop app status where supported.
--cli-status Report Codex CLI status.
--app-server-status Report Codex app-server process status.
--check Read-only update path check.
--install Apply only known safe Codex update paths.
Windows PowerShell:
-Doctor
-Status
-AppStatus
-CliStatus
-AppServerStatus
-Check
-Install
On Linux/WSL/Windows, install mode only uses codex update when that command is
available and CODEX_UPDATE_ALLOW_APPLY=1 is set. Unknown install/update paths
are refused.
Every run writes a timestamped log under:
~/Library/Logs/codex-remote-update/
The latest run is also linked at:
~/Library/Logs/codex-remote-update/latest.log
If an install causes a disconnect, the backup watchdog writes its own
*-reopen-helper.log in the same directory. The watchdog exits after Codex GUI
and codex app-server are both detected, or after its timeout.
- The script uses Codex.app's normal
Check for Updates...menu item. - It clears a skipped Sparkle version when one is set, then asks Sparkle to check again.
- It does not call private update endpoints.
- It does not store credentials.
- It does not install persistent
launchdjobs. - It cannot see private Codex internal thread state, so
--quiet-checkis a conservative shell-process check rather than a perfect idle detector.
If the updater UI cannot be found, verify that you are in a logged-in macOS GUI session and that Accessibility permissions allow terminal automation of Codex.
If Codex updates but remote control still looks broken, verify all three pieces:
codex-remote-update --status
pgrep -x Codex
pgrep -f "/Applications/Codex.app/Contents/Resources/codex app-server"If an older failed experiment left a persistent reopen job behind, inspect
launchctl print gui/$(id -u) for names such as codex-force-restart-* or
codex-reopen-after-*, then unload only the stale job after confirming Codex is
running normally.
LICENSE MIT license
ROADMAP.md Codex-only cross-platform plan
SECURITY.md Security model and review guidance
SKILL.md Codex skill instructions
agents/openai.yaml Skill display metadata
scripts/codex-update-doctor.ps1 Windows Codex doctor
scripts/codex-update-doctor.sh macOS/Linux/WSL Codex doctor
scripts/codex-remote-update.sh Update/check/watchdog script
MIT. See LICENSE.