Rename the active product, Go module, binaries, configuration, protocols and documentation to Piik while retaining the TV mascot and existing media/room behavior. Use one current private contract without old-name aliases. Preserve SQLite authority and copy compatible local settings once; other settings start fresh. Git-message cleanup and the infrastructure name cutover are coordinated with this phase, with original history and deployment data archived externally. Validated locally with Web and Go checks, Windows capture compilation, matched Client/Server builds, packaged Client control handshake and history-rewrite integrity checks. Skip duplicate hosted CI for this owner-authorized local release. [skip ci]
12 KiB
Cross-Platform Client Runtime Research
- Reviewed: 2026-09-04
- Scope: loopback control and self-contained packaging boundary
- Status: Client and Local composition implemented; Windows native Host video and a cross-NAT media gate proved
Reusable Evidence
| Project | Observed boundary | Applicable lesson |
|---|---|---|
| Discord RPC | Bounded local endpoints and an explicit handshake | Discovery and session negotiation can stay small |
| OBS WebSocket | Versioned Hello/Identify before commands |
Reject unknown protocol shapes instead of adding compatibility readers |
| Syncthing | Go process with a loopback Browser GUI by default | A native entry and system-Browser UI are a practical cross-platform pair |
| Sunshine | Native streaming host configured through a localhost Browser UI | Native media does not require a second desktop UI |
| LocalSend | One peer exposes a local HTTP service without an external server | LAN operation can be self-contained, while network reachability remains physical |
These are architecture references only. No implementation or copyleft source is copied.
A read-only inventory of locally installed streaming clients adds one practical constraint. GameViewer separates its UI, supervised media service, codec capability detector, streamer, health process, and updater. Discord keeps its Chromium UI separate from a native voice/media module and updater. Oopz ships Flutter, a second WebView, FFmpeg, Agora RTC, and Tencent LiteAV together; that stack is substantially larger and duplicates media ownership. Piik follows the first two products' process separation but not their UI runtimes, and avoids Oopz's parallel RTC stacks: one Go process, one Pion media core, and one thin system capture sidecar per platform remain sufficient. No binary code or private application data was copied or inspected.
Current Control Boundary
The Client binds IPv4 loopback on a bounded range (39721-39730). /health
returns the protocol version, service identity, selected port, and an
instanceToken. /control admits one WebSocket session whose subprotocol
contains that same value. The first frame must be hello; subsequent requests
are limited to capability discovery, source preview, and one generation-fenced
share's media controls.
The instance token distinguishes a newly discovered process from a stale or unrelated listener. It is visible through health and stdout and is not an authentication secret. Host and Origin checks plus Chromium's Local Network Access permission form the Browser boundary.
The current protocol advertises only the native capabilities and generation-fenced media commands that have consumers. It carries no room credentials or route policy; those stay in the Browser/server protocol.
Client Composition
The Client and Hosted Piik run the same server core, so the local package is one executable carrying the built Browser assets plus the optional capture and tunnel sidecars; the Client README owns that layout. In Local mode the Client runs the server in its own process with explicit local configuration. In Site mode it starts no server, and the system Browser opens the saved Site while the same process remains its loopback native-media owner. The system Browser remains the UI.
Official Go process APIs require every started child to be waited and provide a
bounded WaitDelay for cancellation and stuck I/O. That guidance now covers the
capture and cloudflared sidecars only: the room authority is no longer a child
process, and Local shutdown is one bounded in-process sequence that ends rooms
before closing signaling and HTTP. Windows is physically exercised; macOS and
Linux remain package gates.
Local And Hosted Reachability
A local page completed discovery and the full control exchange in Chromium
151.0.7922.138. The hosted Piik origin completed it after Chromium received
its loopback-network permission; without that permission the cross-origin
request was blocked. The gate checks both expected outcomes.
A self-contained LAN room uses a localhost Host URL and a selected LAN IPv4
Viewer URL backed by the same local Client process. The Client persists an
optional user-chosen access password and passes it only to its Host page in a
consumed fragment; a blank value leaves the Local site open. Explicit --link
mode launches the packaged Cloudflare Quick
Tunnel against that same local HTTP server and supplies its random HTTPS origin
to the local server configuration before it starts listening. The public path
therefore reuses the exact frontend,
WebSocket signaling, RoomStore, and Viewer grant instead of adding a rendezvous
or second client protocol. Cloudflare carries control traffic; WebRTC media uses
public STUN and remains P2P-only.
UI Runtime Boundary
The current Client opens the system Browser rather than embedding another Web runtime. A lightweight launcher chooses the authority mode, then navigates to the same Host page, where a Client-launched Host can select an exact native window. This keeps the existing UI, Site cookies, WebRTC behavior, Browser updates, and permission model intact. Syncthing and Sunshine establish this as a practical native-process plus Browser-UI deployment shape.
An embedded shell remains a decision gate rather than a rejected category.
Current WebView2 exposes getDisplayMedia screen-capture events and its
Evergreen runtime updates independently; WebKitGTK exposes display capture and
uses GStreamer for WebRTC. Electron instead bundles one Chromium and Node but
makes the Client responsible for shipping those updates and adds substantial
package size. These facts do not prove equivalent Piik media behavior.
Only a reproduced Browser-launch failure should open a comparative physical gate for Electron, Tauri, Wails, Neutralino, or another shell. That gate must compare actual capture, audio, H.264/VP8 sender implementation, 1080p cadence, relay, background behavior, and resource use on every target platform. The result selects one UI runtime; it does not create parallel products.
Current Evidence
The runs below are pre-port evidence: they exercised the package that bundled a Node runtime and an extracted application tree. Their capture, discovery, media, and network results still apply; every package composition, startup, and shutdown claim must be re-verified on the single-binary Client before that build is accepted.
On Windows with Chrome for Testing 151.0.7922.138:
- the Local Client started its built static application and reached
/healthz; - the Host fragment was removed, existing SiteAccess became authenticated, and the ordinary Host page loaded;
- the room API generated an invitation from the selected LAN origin;
- one synthetic Host and three Viewers formed a P2P-only tree with one relay, every Viewer advanced decoded frames, and no SFU publication appeared; and
- Enter-driven Client shutdown released the Browser, Client, Node, loopback and application ports, and disposable profile.
- the immutable App release was assembled with Node 24.19.0 and the Go Client
from the same full revision; that packaged directory passed the Local and Site
gates, while a deliberately mismatched
app/REVISIONwas rejected before a listener started. - the explicit target assembler produced Windows amd64, Linux amd64, and macOS arm64 outputs from one clean revision. The Linux package ran its bundled Node Local authority on Ubuntu, and its full package exposed and then closed a public link reachable from another network. The macOS Client and Node inputs are both Mach-O arm64; execution there remains unproved.
- the native Host path created a Local room and a remote Pion Viewer received
30 packets over a selected
srflx-to-srflxpair; the reverse SSH link in that gate carried signaling only. - a Windows Client created an accountless Quick Tunnel, generated its ordinary
invitation on that origin, and served the Viewer page plus
/signalWebSocket upgrade to an independent Linux host; a native Host then repeatedly delivered 30+ H.264 RTP packets to a Linux Pion Viewer over selected direct paths using a reflexive candidate. Stopping the Client closed the URL.
The one-link gate used the official Windows amd64 cloudflared 2026.8.3 asset
with SHA-256 83e726ed18ea78c5ad5213c4c3a3a27051393950d2bc8ed4de69bec12d14eaae.
The sidecar remains an explicit package input rather than a linked Client
dependency.
The peer topology gate now treats native getStats() RTP identity and frame
totals as its portable core proof. Detailed Piik quality metrics enrich a
development run when its source module is served, but their absence on a static
deployment no longer erases valid native RTCStats.
Remaining Gates
- Run the exact clean-revision package on macOS; Linux amd64 is proved.
- Prove a physical second-device LAN Viewer on desktop, Android, and iOS.
- Prove first-run Browser local-network permission outside CDP automation.
- Record no-STUN mDNS behavior on ordinary and AP-isolated LANs.
- Exercise the native Host on a configured Site and representative Browsers; the local SFU bridge is proved in isolation, while full Site recovery, representative audio, and non-Windows capture remain undefined.
- Exercise one-link Browser media on a physical second device; the current gate proves the complete public control path and independent Pion media, not decoded Browser frames.
Sources
- Go
os/exec - WebRTC peer connections
- Cloudflare public STUN endpoint
- Cloudflare Quick Tunnels
- Cloudflare Tunnel WebSockets
- cloudflared releases
- RFC 6455
- W3C Screen Capture
- Microsoft Windows Graphics Capture
- Apple SCContentSharingPicker
- XDG ScreenCast portal
- OBS window-capture source
- Chrome Local Network Access
- Discord RPC
- OBS WebSocket
- LocalSend protocol
- Sunshine
- Syncthing GUI configuration
- GameViewer product
- Discord desktop architecture
- WebView2 Evergreen runtime
- WebView2 screen capture
- WebKitGTK multimedia
- WebKitGTK display capture
- Electron architecture