cat / goq
clone

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

fix/architecture-review-findings
goq / README.md
README.md 8.7K 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. Exactly one client is admitted14to exactly one session at a time, authenticated by a hardware security key.1516## The two programs1718- **Sigil** is the host: a pure Rust daemon for a bare-metal, physically19 headless Linux machine. Gamescope owns the private game display, PipeWire20 provides capture, and hardware H.264 plus Opus leave the machine over21 [iroh](https://github.com/n0-computer/iroh), so the client reaches the host22 by its cryptographic identity rather than an IP address.23- **Portal** is the client: an installed Tauri desktop application with a24 native iroh endpoint, WebCodecs video decode, AudioWorklet playback, and25 controller-first navigation.2627```text28Sigil · bare-metal Linux host Portal · installed desktop client29 Gamescope headless session native iroh endpoint30 -> PipeWire video/audio -> binary Tauri channels31 -> hardware H.264 + Opus -> WebCodecs video + audio out32 -> iroh / MoQ media objects controller, keyboard, mouse33 uinput virtual devices <---- -> iroh input protocol34```3536## Design principles3738- **Latency over history.** Every capture, encode, transport, decode, and39 input queue is bounded. Stale video is dropped or cancelled rather than40 buffered, so a slow receiver never accumulates a playable backlog. Media41 travels as bounded MoQ groups: one GOP is one group, and a newer42 independently decodable group cancels its predecessor.43- **Input is independent.** Controller, keyboard, and relative mouse travel44 on their own iroh connection, unaffected by media backpressure. Session45 teardown always releases held keys and emits a neutral gamepad state, even46 after an error or disconnect.47- **Fail closed.** Portal derives its stable iroh identity from a FIDO2 key48 with `hmac-secret`. A signed, short-lived, peer-bound invitation from Sigil49 enrolls that one client once, with independently granted view,50 pointer/keyboard, and gamepad permissions and durable replay protection.51 Every ordinary launch after that is **PIN -> tap -> play**.52- **Strict product boundary.** Sigil never depends on Tauri or a webview.53 Portal never bundles capture, encoding, a daemon, or host input injection.5455## Status5657goq is pre-release. The reference host is an AMD machine running58[Bazzite](https://bazzite.gg); H.264 at 1280x800/60 is the known-safe59measured benchmark, while production capture accepts any even native mode60within the protocol's bounded pixel limits.6162Working today:6364- The pure Rust Sigil daemon: Gamescope PipeWire capture at the display's65 native mode, AMD GstVA H.264 encoding, and bounded PipeWire/Opus audio.66- Authenticated session admission over a control connection, then a67 session-scoped upstream `iroh-moq` broadcast with a strictly validated68 catalog, with earlier custom media protocols kept as explicit compatibility69 fallbacks.70- Adaptive bitrate and motion-sensitive resolution on the opt-in in-process71 encoder backend: session-authenticated receiver feedback, hysteresis, and72 changes that commit only on exact encoder readback or a target-size IDR.73- Portal playback through bounded binary Tauri channels into WebCodecs and an74 AudioWorklet, with per-stage queue, drop, and latency diagnostics.75- Linux `uinput` keyboard, relative mouse, and an Xbox-style virtual gamepad,76 with strict device preflight and end-of-session neutralization.77- One-time FIDO-bound enrollment, replay protection, and controller-usable78 onboarding in Portal.79- A deterministic, checksum-bound Bazzite runtime package with serialized80 install/upgrade and tamper-checked rollback, plus the foundation of a81 controller-first Decky Loader management plugin over a redacted local82 appliance-status contract.8384The streaming-hardening roadmap, where the remaining work is hardware85acceptance on the reference host, is tracked as86[MoQ recovery hardening](https://github.com/FelineStateMachine/goq/issues/7),87[adaptive bitrate](https://github.com/FelineStateMachine/goq/issues/8),88[motion-sensitive resolution](https://github.com/FelineStateMachine/goq/issues/9),89and [automatic codec selection](https://github.com/FelineStateMachine/goq/issues/10).90The remaining public-alpha acceptance gates (headless cold boot, physical91controller gameplay, sustained A/V measurement, and the signed public release92path) are tracked in issues93[#4](https://github.com/FelineStateMachine/goq/issues/4) to94[#6](https://github.com/FelineStateMachine/goq/issues/6).9596## Repository layout9798| Path | Contents |99| --- | --- |100| `crates/sigil-protocol` | Bounded, versioned handshakes, media/audio headers, input messages, limits, ALPNs |101| `crates/sigil-host` | The `sigil` daemon and the `sigil-probe` diagnostic |102| `src-tauri/` | Portal's native side: iroh transport, FIDO2 identity, binary channels |103| `portal/` | Portal frontend: WebCodecs decode, audio playback, controller navigation |104| `decky/` | Decky Loader management plugin for the Sigil appliance |105| `website/` | The static goq.sh site, published via a Cloudflare Worker |106| `scripts/` | Build, packaging, verification, and host provisioning tooling |107| `docs/` | Runbooks and contracts for provisioning, releases, and hardware acceptance |108109## Getting started110111You need:112113- Rust 1.91 or newer (the repository pins Rust 1.95)114- Tauri v2 system dependencies115- A FIDO2 security key with `hmac-secret` support116- For a host: a dedicated AMD Linux machine (Bazzite is the packaged target)117118Building Sigil with the optional Linux `in-process-gstreamer` feature119additionally needs the GStreamer core, app, and video development libraries;120the matching runtime libraries and plugins must be installed on the host.121122Run Portal against a Sigil host during development:123124```bash125source ~/.cargo/env126cargo tauri dev127```128129On Linux with NVIDIA, prefix with `WEBKIT_DISABLE_DMABUF_RENDERER=1`.130131### Provision a host132133Activate an installed dedicated AMD host with the portable134[Sigil host activation guide](docs/sigil-host-activation.md). To evaluate a135candidate machine first, run `scripts/bazzite-inventory.sh` for a read-only136hardware report; add `--smoke` to exercise a bounded 1280x800/60 VA-API137encode, or `--cold-boot` on the first login after a physically headless boot138for a strict readiness gate.139140### Enroll one Portal141142On Portal's first launch, enter the security-key PIN and choose **show portal143id**. On the Sigil host, create an invitation for that exact peer:144145```bash146sigil invitation create \147 --config ~/.config/sigil-spark/host.toml \148 --peer PORTAL_PEER_ID \149 --pointer-keyboard \150 --gamepad \151 --output ~/portal.goq-invite152```153154Move the owner-only invitation file to the client and open it with Portal.155Sigil consumes it once; every later launch is **PIN -> tap -> play**. To move156Portal to a different Sigil host, revoke the enrollment on the old host and157use **client -> reset enrollment**. A new invitation never silently replaces158a working enrollment.159160## Verification161162Run the complete repository gate before sharing work:163164```bash165./scripts/verify-demo-build.sh166```167168It covers Rust format, tests, and clippy, the Linux cross-build when169available, frontend syntax and tests, ShellCheck, package tests, and loopback170transport proof. Website and installer changes go through171`./scripts/verify-website.sh`. Hardware acceptance evidence lives under172[`docs/hardware-uat/`](docs/hardware-uat/README.md), separate from local173tests.174175## Releases176177Sigil is machine setup, not a desktop download: the public bootstrap is178`https://goq.sh/install-sigil`, and it intentionally fails closed until the179Minisign publisher trust root and the first signed release exist. Its release180assets carry a single frozen build-target suffix, `linux-glibc2.17-x86_64`,181pinned by `release/sigil-target-contract.txt`; that name describes the binary182ABI (glibc 2.17, x86-64), not a distribution, so one build runs across the183supported AMD hosts. Portal is a compiled, signed desktop application, never a184shell install; the first public target is macOS arm64. The packaging, signing,185and publication ceremonies are documented in186[public release delivery](docs/public-release-delivery.md) and the187[Portal release runbook](docs/portal-release.md).188189## License190191[MIT](LICENSE)