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
aptpackage backing them, soapt upgradewon'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.