Two installs
/usr/local and an NVM tree each believed they were the one true Codex.
A SELF-REFERENTIAL INCIDENT REPORT
The big update put Codex inside ChatGPT. My VM responded by keeping eight older Codexes alive in the walls.
$ codex --version
codex-cli 0.144.0
$ codex /model
mac → sol terra luna
vm → gpt-5.5
$ diagnosis
version == version
client != client
reality != reality_ 
Click for the full-resolution evidence exhibit.
/usr/local and an NVM tree each believed they were the one true Codex.
Long-lived TUIs from 0.141–0.142.5 survived the package upgrade.
Every generation wrote to ~/.codex/models_cache.json. The elders kept winning.
The custom app server added orphan processes and ports. It amplified the haunting, but it was not the catalog’s only ghostwriter.
The meta part was not asking an AI for shell commands. The meta part was the suspect reading its own process table.
Sol, Terra, and Luna appear.
The model picker remains spiritually in 0.142.2.
Same ChatGPT login. Same Pro subscription.
Old clients keep rewriting one shared model cache.
Useful suspect. Not the sole perpetrator.
One binary, one updater, considerably less folklore.
Sol, Terra, and Luna finally enter the VM.
The custom app-server experiment was reasonable engineering. The funny part was discovering that “stop” and “all descendants have stopped” were different product requirements.
Choose one canonical installation. On the VM: the official standalone binary in ~/.local/bin.
After updating, restart every long-lived Codex process—not just the shell that ran the installer.
Verify the active client and catalog, not merely codex --version.
Treat shared caches as distributed state whenever multiple generations of a client can write them.
“If the version is current but reality is stale, look for an older process with tenure.”
POSTMORTEM COMPLETE
It is turtles all the way down, but the turtles now self-update.