Change CLI update message presentation to reduce confusion

Resolved 💬 5 comments Opened May 9, 2026 by NickMillerUK Closed May 9, 2026

Summary

The Codex CLI update notification (the box prompt rendered by UpdateAvailableHistoryCell) places the npm command and explanatory prose on the same line, making it easy to accidentally copy trailing words as if they were part of the command. This causes npm to install stray packages globally.

Steps to reproduce

  1. Run a version of Codex CLI that is behind the latest release.
  2. The update box prompt appears:
╭───────────────────────────────────────────────────╮
│ ✨ Update available! 0.116.0 -> 0.118.0            │
│ Run npm install -g @openai/codex to update.        │
│                                                    │
│ See full release notes:                            │
│ https://github.com/openai/codex/releases/latest   │
╰───────────────────────────────────────────────────╯
  1. User selects and copies the command line. Without colour context (which is lost on copy), the full visible string is:
Run npm install -g @openai/codex to update.
  1. User strips Run from the front (or copies from npm onward), pastes into a terminal, and runs it:
npm install -g @openai/codex to update
  1. npm interprets to and update as additional package names and installs all three globally.

Observed outcome

Three packages installed at the same timestamp:

  • @openai/codex
  • to
  • update

Root cause

codex-rs/tui/src/history_cell.rs, line 674:

line!["Run ", update_action.command_str().cyan(), " to update."]

The command (npm install -g @openai/codex) is rendered in cyan, and " to update." is plain text — visually distinct by colour, but indistinguishable on copy. The same pattern is in the raw_lines() plaintext fallback at line 707:

format!("Run {} to update.", update_action.command_str())

Security impact

to and update are real npm packages with known vulnerabilities:

  • to@0.2.9 — critical audit findings
  • update@0.7.4 — multiple critical/high/moderate audit findings

Users who follow the update prompt as intended end up with vulnerable packages silently added to their global npm environment.

Secondary issue: missing @latest tag

codex-rs/tui/src/update_action.rs, line 39:

UpdateAction::NpmGlobalLatest => ("npm", &["install", "-g", "@openai/codex"]),

The runtime command omits @latest. The snapshot test (codex_tui__update_prompt__tests__update_prompt_modal.snap) shows @openai/codex@latest, so the test fixture and runtime are inconsistent. Without @latest, npm may resolve a cached or older version depending on local registry state.

Recommended fixes

  1. Separate the command from the prose. Never render a shell command and explanatory text on the same copyable line. Use a dedicated line or a copy-action button for the command itself.
  2. Use @latest consistently in the runtime command_args() to match the snapshot test expectations.
  3. Consider a one-click / confirmation update from the TUI (Variant B already moves toward this with the interactive menu — Variant A should follow the same pattern or be removed).

References

  • Related issues: #12107, #7104, #16488, #5012

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗