Updating coding agents on an exe.dev VM

The default exeuntu image ships with claude, codex, and pi pre-installed. They are installed when the image is built, not at VM boot. That means:

  • There is no apt package backing them, so apt upgrade won't move them.
  • Long-lived VMs keep whatever versions they were created with until you update them explicitly.

Update to latest

These commands work on newer VMs created from an exeuntu image that includes the exeuntu update agent commands. On older VMs, exeuntu update claude, exeuntu update codex, or exeuntu update pi may not exist yet; use the older VM fallback below.

Run these commands on the VM:

sudo exeuntu update claude
sudo exeuntu update codex
exeuntu update pi

claude --version
codex --version
pi --version

Or from your laptop, against a named VM:

ssh my-vm.exe.xyz 'sudo exeuntu update claude && sudo exeuntu update codex && exeuntu update pi'

The update commands are quiet on success. Run each agent's --version command afterwards if you want to confirm what changed.

Claude Code and Codex are installed into /usr/local/bin, so they require sudo. Pi is installed into the VM user's home directory under ~/.local, so run the Pi update as the user who runs Pi. If you are updating Pi for a different user, pass --home, for example:

sudo -u exedev exeuntu update pi --home /home/exedev

Pinning a specific version

To install a specific release instead of the latest:

sudo exeuntu update claude --version 2.1.185
sudo exeuntu update codex --version rust-v0.140.0
exeuntu update pi --version 1.2.3

Codex release tags are listed at https://github.com/openai/codex/releases.

Older VM fallback

If your VM is too old to have the exeuntu update commands, use the older manual Codex replacement recipe. Run this on the VM:

sudo bash -c '
  set -euo pipefail
  case "$(uname -m)" in
    x86_64) A=x86_64-unknown-linux-musl ;;
    aarch64|arm64) A=aarch64-unknown-linux-musl ;;
    *) echo "unsupported arch: $(uname -m)" >&2; exit 1 ;;
  esac
  V=$(curl -fsSL https://api.github.com/repos/openai/codex/releases/latest | jq -r .tag_name)
  echo "installing codex $V ($A)"
  curl -fsSL "https://github.com/openai/codex/releases/download/$V/codex-$A.tar.gz" \
    | tar -xzC /usr/local/bin
  mv "/usr/local/bin/codex-$A" /usr/local/bin/codex
  chmod +x /usr/local/bin/codex
'
codex --version

Or from your laptop, against a named VM:

ssh my-vm.exe.xyz 'sudo bash -s' <<'EOF'
set -euo pipefail
case "$(uname -m)" in
  x86_64) A=x86_64-unknown-linux-musl ;;
  aarch64|arm64) A=aarch64-unknown-linux-musl ;;
esac
V=$(curl -fsSL https://api.github.com/repos/openai/codex/releases/latest | jq -r .tag_name)
curl -fsSL "https://github.com/openai/codex/releases/download/$V/codex-$A.tar.gz" \
  | tar -xzC /usr/local/bin
mv "/usr/local/bin/codex-$A" /usr/local/bin/codex
chmod +x /usr/local/bin/codex
EOF

The unified exeuntu update command is the supported path for newer VMs. For older VMs that need Claude Code or Pi updates, use the agent's upstream installer or create a new VM from the current default image.

Why not npm install -g @openai/codex?

That works too if you prefer the Node-packaged build and already have a modern Node on the VM. The image ships the native Codex binary because it is self-contained, smaller, and faster to start. If you mix the two, remember that which codex will resolve to whichever appears first on PATH: the npm shim usually lands in ~/.npm-global/bin or similar, ahead of /usr/local/bin.

Why doesn't my VM just have the latest already?

The agents are fetched during docker build of the exeuntu image, not at VM boot. New VMs built from a freshly published image will have recent agent versions; long-lived VMs keep whatever they were created with until you update them explicitly.