cat / goq
clone

turns a linux box into a private steam streaming appliance: plug in, tap your key, play from another computer

fix/drop-hero-notarization-note
goq / README.md
README.md 9.9K rendered
1# goq.sh23**Your key is the address. Plug in, tap, play.**45goq turns one Linux machine into a personal Steam streaming appliance. You6dedicate that machine to your games, plug in nothing but power and network,7and play from another computer with a controller. The goal is the latency of8sitting at the machine, not the latency of a screen-sharing tool.910goq is not a multi-tenant streaming service and not a desktop-sharing tool.11It streams a private [Gamescope](https://github.com/ValveSoftware/gamescope)12session that exists only for your games: the host needs no monitor, no13desktop environment, and no interactive login. Native MoQ admits three viewers14by default, up to a hard ceiling of eight. Every viewer may watch according to15its grants, while exactly one viewer at a time may hold slot-0 input focus.16Legacy control/media clients remain strictly exclusive.1718## The two programs1920- **Sigil** is the host: a pure Rust daemon for a bare-metal, physically21 headless Linux machine. Gamescope owns the private game display, PipeWire22 provides capture, and hardware H.264 plus Opus leave the machine over23 [iroh](https://github.com/n0-computer/iroh), so the client reaches the host24 by its cryptographic identity rather than an IP address.25- **Portal** is the client: an installed Tauri desktop application with a26 native iroh endpoint, WebCodecs video decode, AudioWorklet playback, and27 controller-first navigation.2829```text30Sigil · bare-metal Linux host Portal · installed desktop client31 Gamescope headless session native iroh endpoint32 -> PipeWire video/audio -> binary Tauri channels33 -> hardware H.264 + Opus -> WebCodecs video + audio out34 -> iroh / MoQ media objects controller, keyboard, mouse35 uinput virtual devices <---- -> iroh input protocol36```3738## Design principles3940- **Latency over history.** Every capture, encode, transport, decode, and41 input queue is bounded. Stale video is dropped or cancelled rather than42 buffered, so a slow receiver never accumulates a playable backlog. Media43 travels as bounded MoQ groups: one GOP is one group, and a newer44 independently decodable group cancels its predecessor.45- **Input is independent and focused.** Controller, keyboard, and relative mouse travel46 on their own iroh connection, unaffected by media backpressure. Session47 focus is a revocable token rather than a viewing right. Every handoff first48 invalidates the former focus generation, then releases held keys and emits a49 neutral gamepad state before a successor can inject.50- **Fail closed.** Portal derives its stable iroh identity from a FIDO2 key51 with `hmac-secret`. A signed, short-lived, peer-bound invitation from Sigil52 enrolls each bounded viewer once, with independently granted view,53 pointer/keyboard, and gamepad permissions and durable replay protection.54 Every ordinary launch after that is **PIN -> tap -> play**.55- **Strict product boundary.** Sigil never depends on Tauri or a webview.56 Portal never bundles capture, encoding, a daemon, or host input injection.5758## Status5960goq is pre-release. The reference host is an AMD machine running61[Bazzite](https://bazzite.gg); H.264 at 1280x800/60 is the known-safe62measured benchmark, while production capture accepts any even native mode63within the protocol's bounded pixel limits.6465Working today:6667- The pure Rust Sigil daemon: Gamescope PipeWire capture at the display's68 native mode, AMD GstVA H.264 encoding, and bounded PipeWire/Opus audio.69- Authenticated session admission over a control connection, then a70 shared, authenticated upstream `iroh-moq` generation with a strictly71 validated catalog. Multiple viewers share one video/audio producer and one72 adaptive actuator; earlier custom media protocols remain exclusive73 compatibility fallbacks.74- Adaptive bitrate and motion-sensitive resolution on the opt-in in-process75 encoder backend: session-authenticated receiver feedback, hysteresis, and76 changes that commit only on exact encoder readback or a target-size IDR.77- Portal playback through bounded binary Tauri channels into WebCodecs and an78 AudioWorklet, with per-stage queue, drop, and latency diagnostics.79- Linux `uinput` keyboard, relative mouse, and an Xbox-style virtual gamepad,80 with strict device preflight and end-of-session neutralization.81- One-time FIDO-bound enrollment, replay protection, and controller-usable82 onboarding in Portal, with bounded multi-peer authorization and live view or83 input revocation.84- A deterministic, checksum-bound Bazzite runtime package with serialized85 install/upgrade and tamper-checked rollback, plus the foundation of a86 controller-first Decky Loader management plugin over a redacted local87 appliance-status contract.8889The streaming-hardening roadmap, where the remaining work is hardware90acceptance on the reference host, is tracked as91[MoQ recovery hardening](https://github.com/FelineStateMachine/goq/issues/7),92[adaptive bitrate](https://github.com/FelineStateMachine/goq/issues/8),93[motion-sensitive resolution](https://github.com/FelineStateMachine/goq/issues/9),94and [automatic codec selection](https://github.com/FelineStateMachine/goq/issues/10).95The remaining public-alpha acceptance gates (headless cold boot, physical96controller gameplay, sustained A/V measurement, and the signed public release97path) are tracked in issues98[#4](https://github.com/FelineStateMachine/goq/issues/4) to99[#6](https://github.com/FelineStateMachine/goq/issues/6).100101## Repository layout102103| Path | Contents |104| --- | --- |105| `crates/sigil-protocol` | Bounded, versioned handshakes, media/audio headers, input messages, limits, ALPNs |106| `crates/sigil-host` | The `sigil` daemon and the `sigil-probe` diagnostic |107| `src-tauri/` | Portal's native side: iroh transport, FIDO2 identity, binary channels |108| `portal/` | Portal frontend: WebCodecs decode, audio playback, controller navigation |109| `decky/` | Decky Loader management plugin for the Sigil appliance |110| `website/` | The static goq.sh site, published via a Cloudflare Worker |111| `scripts/` | Build, packaging, verification, and host provisioning tooling |112| `docs/` | Runbooks and contracts for provisioning, releases, and hardware acceptance |113114## Getting started115116You need:117118- Rust 1.91 or newer (the repository pins Rust 1.95)119- Tauri v2 system dependencies120- A FIDO2 security key with `hmac-secret` support121- For a host: a dedicated AMD Linux machine (Bazzite is the packaged target)122123Building Sigil with the optional Linux `in-process-gstreamer` feature124additionally needs the GStreamer core, app, and video development libraries;125the matching runtime libraries and plugins must be installed on the host.126127Run Portal against a Sigil host during development:128129```bash130source ~/.cargo/env131cargo tauri dev132```133134On Linux with NVIDIA, prefix with `WEBKIT_DISABLE_DMABUF_RENDERER=1`.135136### Provision a host137138Activate an installed dedicated AMD host with the portable139[Sigil host activation guide](docs/sigil-host-activation.md). To evaluate a140candidate machine first, run `scripts/bazzite-inventory.sh` for a read-only141hardware report; add `--smoke` to exercise a bounded 1280x800/60 VA-API142encode, or `--cold-boot` on the first login after a physically headless boot143for a strict readiness gate.144145### Enroll a Portal146147On Portal's first launch, enter the security-key PIN and choose **show portal148id**. On the Sigil host, create an invitation for that exact peer:149150```bash151sigil invitation create \152 --config ~/.config/sigil-spark/host.toml \153 --peer PORTAL_PEER_ID \154 --pointer-keyboard \155 --gamepad \156 --output ~/portal.goq-invite157```158159Move the owner-only invitation file to the client and open it with Portal.160Sigil consumes it once; every later launch is **PIN -> tap -> play**. Repeat161with a distinct invitation for each viewer. A view-only invitation creates a162spectator with no focus action; pointer/keyboard or gamepad grants make a163viewer eligible to request slot-0 focus but do not grant possession. To move164Portal to a different Sigil host, revoke the enrollment on the old host and165use **client -> reset enrollment**. A new invitation never silently replaces166a working enrollment.167168## Verification169170Run the complete repository gate before sharing work:171172```bash173./scripts/verify-demo-build.sh174```175176It covers Rust format, tests, and clippy, the Linux cross-build when177available, frontend syntax and tests, ShellCheck, package tests, a three-viewer178native-MoQ loopback proof, and a separate legacy-exclusive proof. The explicit179eight-viewer release stress gate remains a local resource test, and neither180loopback mode substitutes for exact-candidate hardware UAT. Website and installer changes go through181`./scripts/verify-website.sh`. Hardware acceptance evidence lives under182[`docs/hardware-uat/`](docs/hardware-uat/README.md), separate from local183tests.184185## Releases186187Sigil is machine setup, not a desktop download: the public bootstrap is188`https://goq.sh/install-sigil`, and it intentionally fails closed until the189Minisign publisher trust root and the first signed release exist. Its release190assets carry a single frozen build-target suffix, `linux-glibc2.17-x86_64`,191pinned by `release/sigil-target-contract.txt`; that name describes the binary192ABI (glibc 2.17, x86-64), not a distribution, so one build runs across the193supported AMD hosts. Portal is a compiled, signed desktop application, never a194shell install; the only published target is macOS arm64, which is ad-hoc signed195rather than Apple-notarized, so macOS blocks its first launch until you allow it196under System Settings, Privacy and Security. macOS x86_64,197Linux x86_64, and Windows x86_64 are built and attested every release as198unpublished preview artifacts. The packaging, signing, and publication199ceremonies are documented in200[public release delivery](docs/public-release-delivery.md) and the201[Portal release runbook](docs/portal-release.md). The operator path from the202committed `unconfigured` trust pins to a first published release is203[release credential bring-up](docs/release-credentials.md).204205## License206207[MIT](LICENSE)