Vect on your phone

Your agents run on your machine. The phone is a second screen onto them: see what they are doing, answer them, from wherever you are in the house.

Nothing is uploaded anywhere. The phone talks directly to your computer.

The way to use this today is the phone's browser: scan the code and the second screen opens, with nothing to install. There are iOS and Android builds of the same client in the source tree, but neither is released, so they are something you build yourself rather than something you can download.

Pair a device

  1. On the computer running Vect, open Settings and find Devices.
  2. Turn on Reachable on this network. Until you do, only that computer can connect to it.
  3. Press Pair a device. A QR code appears next to a six-digit code and an address such as 192.168.0.14:9878.
  4. Point the phone's camera at the QR code and open the link. That is the whole gesture: no typing, no button. Typing the address and code by hand works too, for a device with no camera.

The code lasts five minutes and pairs exactly one device. The phone is issued a token it keeps; it will not ask again. Revoke a device from the same panel and its token stops working immediately.

What the phone can do

Notifications only arrive while the app is open. iOS suspends the connection when the app goes to the background, so a phone in your pocket will not buzz. Real background delivery needs Apple's push service, which is not wired up yet.

Without installing the app

vect ui serves the same client at /remote, so any phone browser on the network can be a second screen with nothing installed:

$ vect ui --host 0.0.0.0
Vect UI running at http://0.0.0.0:4321
Second screen at   http://0.0.0.0:4321/remote

It accepts the same pairing payload as a query string, so a link works where a QR scan would.

The phone renders the same event stream the desktop does, from the same raw provider output, so it never drifts into showing you something different from what is on your screen at home.

Building the app

The mobile client lives in apps/mobile. It is the same React code as the rest of Vect, wrapped as a Tauri 2 app.

pnpm --filter @vect/mobile ios:dev        # run on a simulator or attached iPhone
pnpm --filter @vect/mobile ios:build      # produce an .ipa

Android carries its own toolchain, which this repo does not install for you:

brew install openjdk@21 android-commandlinetools
export JAVA_HOME=/opt/homebrew/opt/openjdk@21
export ANDROID_HOME=/opt/homebrew/share/android-commandlinetools
yes | "$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" --licenses
"$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" \
  "platform-tools" "platforms;android-35" "build-tools;35.0.0" "ndk;27.1.12297006"
export NDK_HOME="$ANDROID_HOME/ndk/27.1.12297006"
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android

pnpm --filter @vect/mobile android:dev                    # run on a device or emulator
pnpm --filter @vect/mobile android:build --debug --apk    # produce an .apk

The generated Android project is committed, so tauri android init is only needed for a fresh one. One line in its manifest is hand-written and would be lost by re-running init: android:usesCleartextTraffic="true". Tauri turns cleartext off for release builds, and a phone talking ws:// to a machine on your own network is the entire feature. Android has no "local networking only" switch the way iOS does, so this is all or nothing.

tauri.conf.json declares "mobile": [{ "scheme": ["vect"] }]. The plugin's default is https/http app links, and it does not merely generate a manifest entry from that: it also filters incoming URLs against the same config, so a vect://pair?… link would launch the app and then be discarded before reaching JavaScript. A QR code cannot carry an app link to a host nobody owns, so the custom scheme is the only workable form and it has to be declared here.

The client reads the link with both getCurrent() and onOpenUrl(). Scanning a code starts the app, so the link that matters arrives before any listener exists; onOpenUrl alone only covers a phone that already had Vect open.

iOS needs two Info.plist keys before it will even attempt a ws:// connection to a machine on your network: an App Transport Security exception for local networking, and a stated purpose for local network access. Both live in apps/mobile/src-tauri/Info.ios.plist and are merged into the generated project, so they survive re-running tauri ios init. The CFBundleURLTypes entry for the vect scheme is not merged (only scalar keys are), so it lives directly in gen/apple/vect-mobile_iOS/Info.plist.

Ports

PortSurface
9876Local IPC bridge (vect mcp serve talks to this)
9877CRDT sync for Collab sessions
9878Remote clients (this feature)

9878 binds to 127.0.0.1 until you turn on network access, and rejects every request that does not carry a paired device's token.