The Web companion is an opt-in, responsive browser interface to selected CanvasTTY sessions. On narrow screens, the Sessions menu opens on the attention-first session list; selecting a session opens its detail, and the menu reopens to switch sessions. Wider screens keep the list and detail side by side. Its restrained colors and typography match the desktop interface. It is not an Android app and needs no mobile installation. Use either a private Tailscale Serve HTTPS origin on a device in the same tailnet, or a USB-connected Android phone with adb reverse and no phone VPN. This deployment has not yet been exercised on a real Android phone or end-to-end on Windows, Linux, or macOS release packages; verify the setup on your devices before relying on it.
- Install Tailscale, sign in on the CanvasTTY computer and on each client device, and enable Tailscale HTTPS/MagicDNS for your tailnet. Keep CanvasTTY running.
- In CanvasTTY, open Settings → Controls → Web companion. On the host computer run
tailscale serve --bg 3481, thentailscale serve status. This Serve syntax is supported by the Tailscale CLI; it proxies the HTTPS tailnet address to CanvasTTY's HTTP listener at 127.0.0.1:3481. On Linux, if Serve reportsAccess denied: serve config denied, runsudo tailscale serve --bg --https=443 http://127.0.0.1:3481on the host with local admin authorization, then inspecttailscale serve status; never paste a sudo password into the phone or chat. Alternatively, ask an administrator to grant Serve operator access; do not change persistent privileges. Do not usetailscale funnel: Funnel exposes the service to the public Internet. - Enter the exact
https://<device>.<tailnet>.ts.netorigin shown by Tailscale, without a path, port, or trailing slash. CanvasTTY does not discover or configure Tailscale automatically. Choose which existing sessions are shared and whether the browser may send input, create sessions in the selected local workspace, or close shared sessions. Browser and filesystem access are not exposed to the Web companion. Enabling this mode moves the companion listener from LAN to loopback; Even G2's local connection is a separate, explicit choice. - Save and begin pairing in the desktop settings. On a tailnet-connected device open
https://<device>.<tailnet>.ts.net/mobile/, enter the six-digit code, then approve the displayed browser on the computer. Codes expire after two minutes. The paired browser can then use only the granted session actions. Session creation requires an available provider CLI on the host and a desktop-selected workspace; no remote folder picker exists.
If the page does not load, check that CanvasTTY is running and enabled, tailscale serve status shows the correct HTTPS mapping, the hostname matches the saved origin, and the client is signed into the tailnet. A listener shown as ready in CanvasTTY does not by itself prove Tailscale Serve is configured or accessible. Avoid a public reverse proxy, port forwarding, and Funnel.
- Keep CanvasTTY running on the computer. Install Android platform-tools (
adb) on the computer if needed. On a trusted Android phone enable Developer options and USB debugging, connect it by cable, then authorize the computer on the phone. Runadb deviceson the computer and confirm the device is listed asdevice(notunauthorized). USB debugging authorizes the computer to access the phone; do not approve a computer you do not trust. - In Settings → Controls → Web companion, select Test over USB (no Tailscale VPN). The origin must be exactly
http://127.0.0.1:3481; choose session grants and enable the companion. CanvasTTY remains bound to host loopback (127.0.0.1:3481), and browser access remains disabled. On the computer runadb reverse tcp:3481 tcp:3481(with multiple devices, target the chosen device usingadb -s <serial> reverse tcp:3481 tcp:3481). This forwards the phone's own loopback port to the computer's loopback listener; it does not open a LAN or public listener. - On the phone, open
http://127.0.0.1:3481/mobile/, enter the desktop's six-digit code, and approve the displayed browser on the computer. Pairing and requests still use SRP and encrypted LocalLink, desktop approval, and the chosen session grants. Android's127.0.0.1is a potentially trustworthy browser context; the companion refuses pairing without a secure context and Web Crypto.localhost, a LAN address, or a different port is not an alternative to this URL.
If the page does not load, check the device authorization in adb devices, the adb reverse --list mapping, the USB cable, and that the companion is enabled. Do not enable Tailscale Funnel, port forwarding, or a public proxy. This path does not require Tailscale on the phone and does not use another VPN slot.
After the test, run adb reverse --remove tcp:3481 on the computer (use adb -s <serial> if needed), turn off or opt out of the Web companion and revoke the paired browser in Controls. Disable USB debugging and revoke USB debugging authorizations on the phone when they are no longer needed; USB debugging grants the authorized computer device access beyond CanvasTTY.
In Controls, Turn off Web companion stops CanvasTTY's listener while keeping its settings for later. Opt out of Web companion disables it and clears the configured origin, but does not delete existing device grants. Use Disconnect device → Revoke for each paired browser whose access should end. For Tailscale Serve, turn off or remove the Serve mapping separately with the Tailscale CLI (inspect tailscale serve status first); for USB, remove adb reverse tcp:3481 separately as above. If a phone is lost, revoke its pairing and, if applicable, its tailnet access. Switching to the Even G2 LAN flow requires explicitly choosing a local network; no settings change silently changes transport.
The HTTPS endpoint is tailnet-scoped, not publicly hosted; tailnet membership is not pairing authorization. The USB endpoint binds host loopback: host-local processes and browsers can reach it directly, while a phone reaches it through authorized adb reverse. Six-digit SRP pairing requires explicit approval on the desktop; subsequent session requests use a separate encrypted channel and desktop grants. Treat the browser profile as sensitive: pairing credentials stored in browser localStorage may remain accessible to scripts running at that origin and to anyone using an unlocked device/profile. Use a trusted device, avoid shared browser profiles, and revoke lost or compromised clients. HTTPS protects the Tailscale hop; USB forwards loopback HTTP over the physical debugging link. The host HTTP backend must stay bound to 127.0.0.1. Do not publish the private desktop endpoint through Funnel or another public proxy.
The Web companion has no separate API for arbitrary filesystem operations, the desktop Browser, plugins, provider credentials, or unrestricted agent control. Raw shared terminal output is not sanitized: a CLI can print secrets, passwords, file contents, or credentials to its PTY, and anyone granted that session can read them. Typing into a shared terminal can also run commands under the host account. Share only trusted sessions and grant input sparingly. See security policy and architecture.
Terminal output is retained only in bounded host memory (up to 240,000 UTF-16 characters per session), not stored as durable history. After a long disconnect the browser may show a gap where older output was evicted. A desktop restart may restore session descriptors if session restore is enabled, but cannot restore prior terminal output. The browser polls about every 2.5 seconds while visible; it is not a background service or a push-notification client.
The raw xterm view displays PTY output but is not a full remote terminal emulator: input uses the text-send action and a fixed keybar (Ctrl-C, Enter, arrows, Tab, Backspace, Esc). It does not forward arbitrary key combinations, mouse gestures, paste without submission, or browser-size changes to the host PTY.