Updating coding agents on an exe.dev VM
How to update Claude Code, Codex, and Pi on the exeuntu image
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](#older-vm-fallback) below.
Run these commands on the VM:
```sh
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:
```sh
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:
```sh
sudo -u exedev exeuntu update pi --home /home/exedev
```
## Pinning a specific version
To install a specific release instead of the latest:
```sh
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:
```sh
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:
```sh
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.