VCode home

Update an installed machine

Agents: claude, codex, opencode · On: desktop

bash install.sh update pulls the new code, reinstalls dependencies, migrates the env file, re-renders the units and restarts them. One command per machine.

Why you would use it

A new version landed on the branch this machine tracks, and you want it running without remembering which of the six steps matter this time.

How to use it

  1. Run bash install.sh update from the main checkout, not from a worktree and not from inside a VCode thread.
  2. Read the status block it prints at the end.
  3. If a phone has the app installed and the change touched the UI shell, confirm VERSION in public/sw.js was bumped in the commit. Without a bump the phone keeps serving its cached shell whatever the server does.

What you see

In order: git pull --ff-only, npm ci --omit=dev, the env file line (env file exists, left alone: …), a migrated … line only when the file actually changed, one rendered … line per unit, then systemctl --user daemon-reload, enable --now, restart, and the status output with the tunnel token redacted.

Extra lines you may see:

Options and settings

Option Default What it changes
--dir DIR the script's directory Which checkout is pulled and pointed at
--out DIR ~/.config/systemd/user Where the re-rendered units land
--env-file FILE ~/.config/v-code/env The file that is migrated and read
--state-dir DIR ~/.local/state/v-code State and voice paths in the units
--dry-run off Print the steps, change nothing

The rename to VCode

update on a clone, like install, first moves a box that still has the names from before the rename (migrate_names). It runs after git pull and npm ci, before anything writes the env file or a unit:

Old New
~/.config/claude-portal/env ~/.config/v-code/env, every WORKBENCH_* and PORTAL_* key under its VCODE_* name
~/.local/state/claude-portal ~/.local/state/v-code
portal-workbench-prod.service, claude-portal-tunnel.service, portal-voice.service v-code.service, v-code-tunnel.service, v-code-voice.service; the old units are stopped, disabled and removed, and their drop-ins move to the new names
~/.portal-shots ~/.v-code-shots

The dev instance moves ~/.config/claude-portal/dev.env, ~/.local/state/claude-portal-dev, portal-workbench-dev.service and portal-tunnel-dev.service the same way. Each step prints one line, such as moved <old> to <new>, keys under their VCODE_ names. A run with nothing left to move prints nothing. When both the old and the new path exist, it stops before changing anything: both <old> and <new> exist, so the rename to VCode stopped and nothing was changed. Keep the one this box uses, move the other out of the way, and run this again. Run it from a terminal outside VCode: it refuses to run inside the unit it is about to stop.

voice, voice-browser and uninstall do not move anything. On a box that still needs the move they stop with this box still has names from before the rename to VCode: run <repo>/install.sh install first.

The env file migration

migrate_env runs on every install and every update, and rewrites the env file in place for a file written before the terminal portal was retired:

Old New
WORKBENCH_URL=<url> PORTAL_URL=<url> (the old PORTAL_URL named the retired portal, and is dropped)
PORTAL_PEERS=name|portalUrl|workbenchUrl PORTAL_PEERS=name|workbenchUrl
PORT=<n> removed

It is idempotent: a file already in the current shape is left byte for byte alone and nothing is printed. When it does write, it writes through a temp file at 0600 and a rename, because the file holds both tokens, and prints migrated <path> to the one-product shape (PORTAL_URL is this server). The rename step then moves PORTAL_URL and PORTAL_PEERS to VCODE_URL and VCODE_PEERS.

update also re-runs the voice uv pip install, but only on a machine where the venv and the model are already there — that is how a changed pin in voice/requirements.txt reaches the sidecar.

Limits and known gaps