vitro

vitro-tunnel.

Hosted browsers run on our hardware. localhost:3000 runs on yours. One static binary joins them, and bridges MCP for anything that cannot reach the fleet on its own. Sign in once; after that it is one word.

Install it In a sandbox

Run it

One file, no runtime. Three lines, none of them a setting.

curl -fsSL https://vitro.run/tunnel/install.sh | sh
vitro-tunnel login
vitro-tunnel tunnel

The installer puts it on your PATH; targets are {linux,macos}-{amd64,arm64}. login is the same OAuth sign-in claude mcp add uses — a browser, once, and nothing to paste. tunnel with no port finds the dev server already running in the directory you are in, and the fleet allocates the port it answers on. Script is served as plain text.

In a sandbox, where there is no browser

Same word. login notices and shows a code to approve on your laptop or your phone instead of opening something here — RFC 8628, and the credential it hands back needs no second host and does not expire mid‑run.

vitro-tunnel login          # picks the right door
vitro-tunnel login --device # or ask for the code

What has to be reachable, as data rather than prose: /sandbox.json before anything is installed, vitro-tunnel doctor --json from inside the box. And tunnel tells you when your platform already publishes the port and you need no tunnel at all.

Somewhere a script runs unattended

In CI, where nobody is present to approve anything, name the file and pin the version:

V=1.2.3
curl -fsSL "https://vitro.run/tunnel/linux-amd64?version=$V" -o vitro-tunnel
curl -fsSL "https://vitro.run/tunnel/linux-amd64/sha256?version=$V" \
  | sed 's|  .*|  vitro-tunnel|' | shasum -a 256 -c -
chmod +x vitro-tunnel

The credential

login saves an OAuth grant in ~/.vitro/config.json and refreshes it on its own, which is what lets a tunnel outlive one access token. Where a browser is the wrong shape — CI, a baked image, a secret store — present a psk_live_… instead. Flags win over VITRO_URL/VITRO_KEY, so an image stays overridable.

vitro-tunnel --key-file /run/secrets/vitro …
vitro-tunnel --key @/run/secrets/vitro …    # one slot to fill
vitro-tunnel --key - …  < /run/secrets/vitro

--url defaults to https://vitro.run; point it at a vitro instance to use that instead.

When the client cannot reach the fleet

The same binary bridges MCP — see the tool reference.

vitro-tunnel mcp
vitro-tunnel serve --port 43218

Bytes on your own disk

The two things MCP has no shape for.

vitro-tunnel screenshot -page "$PAGE" -o broken.png
vitro-tunnel fetch vitro://artifact/9f2c -o shot.webp

Behind somebody else's network

HTTPS_PROXY is honoured. doctor exits non-zero when it cannot reach the fleet — use it as a gate.

vitro-tunnel doctor