VCode home

Run it locally for a first try

Agents: claude, codex, opencode · On: desktop, phone

Start VCode on your own machine with one command and open it in a browser. node scripts/remote-dev.js runs the whole stack on loopback: a fake login site, a test router, one box linked to a dev account, and the app build.

A box serves no page of its own, from a clone or from a release. The app is the only way in, so a first try needs the app and a site to log in on; this script fakes the site and the router so nothing leaves the machine.

Why you would use it

You cloned the repo and want to see the app before deciding to install it. You are changing the code and need the app and a box you can restart. You want to check that your claude, codex or opencode CLI is wired up before putting the app on a phone.

How to use it

  1. Install node 24 or newer. install.sh refuses anything older (node >= 24 required), and package.json declares "node": ">=24".
  2. Install at least one agent CLI (claude, codex or opencode) so it is on your PATH. VCode spawns them by name.
  3. Install the dependencies: npm install (the app build needs the dev ones).
  4. Run node scripts/remote-dev.js. It builds the app into dist/app and prints its URL, the fake site's, the router's and a control URL.
  5. Open the app URL and tap Log in. The fake site's page asks for the email (dev@example.test unless you passed --email) and a code, which the script prints as [site] login code for dev@example.test: <code>. The page sends you back to the app, logged in, with the box dev-box listed.

--boxes N links N boxes to the same account. Ctrl+C stops everything and removes the state under /tmp.

To run a box on its own, without the app: export AUTH_TOKEN=$(openssl rand -hex 32), then npm start (which runs node server.js). It answers / with a page that points at app.fezu.dev, /health, and the API for a caller that sends the token, such as npm run smoke. For development, npm run dev restarts it by port rather than by process name, and binds the tailnet IP when tailscale ip -4 answers. With no AUTH_TOKEN set it makes a token once and keeps it in ~/.v-code/dev-token (mode 0600).

What you see

On startup the box writes two lines to stdout:

Without AUTH_TOKEN it prints one line on stderr and exits 1:

The token is never printed. If the port is taken, the server prints port 3444 is already in use; another VCode server is running. followed by find it: ss -ltnp 'sport = :3444' replace it: npm run dev, and exits 1.

remote-dev.js runs its boxes on free ports with their own tokens, so it does not clash with a box already on 3444.

Options and settings

Option Default What it changes
VCODE_PORT 3444 The port server.js listens on
BIND_HOST 127.0.0.1 The address it binds. A tailnet IP makes it reachable from the tailnet, and closes loopback
AUTH_TOKEN (none) The bearer token for the CLI and scripts. Required: without it the server does not start
VCODE_DEFAULT_CWD the home folder The folder a new thread starts in; Set as default in the new-thread card overrides it
VCODE_ENABLE_MOCK_AGENT (off) Adds a scripted mock agent. For tests only

npm run dev also reads VCODE_LOG (default /tmp/v-code-<port>.log) and VCODE_UNIT (no default: with none set it restarts by port). The server and npm run dev still read the old WORKBENCH_* names; the new name wins when both are set.

Limits and known gaps