~1150 feat/fix commits landed since v0.19 and the docs drifted badly. This is a
full sweep of every page against the code as shipped: ~280 verified corrections,
nine new pages, and one deletion.
The worst of what was wrong: the quickstart's five-minute path could not work
(`serve` never started the web console, so step 3 had no PIN to read); every
packaged Linux host runs `serve --gamestream` while security.md told readers to
leave GameStream off; HDR was documented as Windows-only; `PUNKTFUNK_SECURE_DDA`
was documented as a working knob that nothing reads; `PUNKTFUNK_INPUT_BACKEND`
listed a `uinput` value that does not exist and named libei for KDE instead of
kwin; README linked three pages deleted on 2026-07-05; and the rpm-ostree update
command pointed at a script no package installs.
Completeness: about half of what shipped since v0.19 had no page at all. New:
support-matrix (what works where, from 217 verified capability cells), input
(mouse/touch/pen — and the in-stream chords, so the docs finally say how to get
your mouse back), client-settings, profiles-and-links, game-library, clipboard,
wake-on-lan, hdr, uninstall. Updating existed but had zero inbound links.
status.md is gone: its facts moved into the support matrix, its shell stays as a
redirect so the public URL does not 404. roadmap.md is themes now, not a feature
checklist — checkboxes are what rotted.
Debian is no longer claimed. The .deb's Depends resolve against Ubuntu images,
nothing in CI builds or tests Debian, and Debian 12 is below the glibc 2.39
floor. The `debian` in the repo URL is the package format.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Intel's Windows driver advertises Vulkan Video (Arc drivers since 2023), so
the capability gate alone no longer keeps Intel off FFmpeg-Vulkan — and that
combination is broken in the field (B580 report: strobing + 7.2 ms p50
decodes at 4K120) and on glass (Arc Pro iGPU: 29-33 ms p50 decodes at 4K60
where D3D11VA does 2.5 ms on the SAME GPU). Mirror the Linux vendor order on
Windows: NVIDIA/AMD keep Vulkan Video first, Intel/unknown take D3D11VA
first; vulkan stays reachable by explicit preference and as auto's fallback.
Also:
- Vulkan→D3D11VA mid-session demotion rung (the Windows analog of Linux's
Vulkan→VAAPI rung) — a failing Vulkan backend lands on hardware, not on
software, which cannot survive 4K120.
- The demotion streak now needs 1 s of age as well as 3 consecutive errors:
a startup loss burst produced 3 errors in 20 ms and stranded the session
on software decode (one-way) before the IDR requested on the first error
could possibly arrive — live-hit on the Intel iGPU leg.
- Stale "Intel's Windows driver has no Vulkan Video" comments corrected,
docs updated to the per-vendor order, vendor-order test extended with
discrete/iGPU Arc cases.
Verified on an Arc Pro iGPU + RTX 3500 Ada laptop against a CachyOS/NVENC
host: auto now picks d3d11va on Intel (60 fps, 2.5-2.8 ms decode, e2e 26 ms
vs 50 ms before) and still picks vulkan on NVIDIA. 27/27 pf-client-core
tests, clippy clean.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The "Which should I use?" table on the clients page listed most client
names as bold text, not links — only the Decky plugin and pf-webos were
clickable — so the client references appeared broken. Link each client to
its section (or dedicated page), and fix a stale Windows headless command.
Repo-wide docs correctness/staleness pass against the code:
- steam-deck: client-not-found -> flatpak-not-found (the real backend code)
- install: host cert is punktfunk-host-windows_<ver>.cer, not ..._setup.cer
- configuration: GPU_PRIORITY_CLASS default is auto; 10BIT/444 are default-on
- how-it-works/index: GameStream/Moonlight is opt-in (--gamestream)
- roadmap: clipboard sync is shipped, not planned
- install-client: MSIX/cert artifacts are arch-suffixed (_x64/_arm64)
- requirements: fix garbled 22H2/IddCx sentence
- status: Linux encode also covers AMD/Intel (VAAPI/Vulkan Video)
- automation: add the plugins.changed event
- windows-host: note the optional bundled VB-CABLE virtual mic
- sway: PUNKTFUNK_COMPOSITOR=hyprland is a wlroots-family alias
- running-as-a-service: punktfunk-probe is a source-build-only dev tool
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds an LG webOS TV entry to Clients and Install a Client, pointing at
the community-maintained pf-webos project (dyptan-io) and its sideload
steps (Homebrew Channel + .ipk) — not an official punktfunk client.
Six parallel audits swept the root docs, docs-site, every per-directory
README, and the packaging docs; every claim below was verified against
the source before editing.
- README: Layout gains the six missing crates (pf-client-core,
pf-presenter, pf-console-ui, pf-ffvk, pf-driver-proto, punktfunk-tray),
clients/session, api/ and ci/; Linux/Windows client rows reflect the
shell + Vulkan-session split and the Vulkan Video -> VAAPI/D3D11VA ->
software decode chains; the "every client over a C ABI" claim is
corrected (Rust clients link the core directly); tiered stats overlay
+ console shell noted; Apple row mentions AV1.
- CONTRIBUTING: drop the dead CLAUDE.md link (deliberately untracked);
point at the README's build/invariants sections. SECURITY: 0.9.0.
- host-cli/pairing: --allow-pairing/--require-pairing are no-op legacy
names — pairing is required by default, --allow-tofu is the real flag;
document --data-port and --idle-timeout-ms.
- configuration: document PUNKTFUNK_RECOVER_SESSION_CMD (session-crash
recovery hook), PUNKTFUNK_MDNS, PUNKTFUNK_DATA_PORT.
- virtual-displays/gnome: GNOME per-client scaling shipped (host-
persisted) — flip the ❌ to ✅ and describe how it works.
- stats: new "Detail levels" section (Off/Compact/Normal/Detailed +
per-platform cycle gestures); retire the GTK hand-off note.
- clients/install-client/status/roadmap: decode chains, Windows client
validation narrowed to HDR-only pending, adaptive bitrate, console
shell, Apple AV1, Windows host vendor list.
- Sub-READMEs: clients/linux rewritten for the re-architecture; session
Windows decode rung + d3d11va knob; Windows tiered overlay; Android
minSdk 28; decky file table; host zerocopy/ path; scripts port
47992 and steamos-host.md; pf-dualsense source path.
- packaging: canary version bases are tag-derived (<next-minor> via
pf-version.sh/.ps1), codecs-extra not ffmpeg-full, document the
pinned offline-Skia tarball + SKIA_BINARIES_URL and vulkan-headers.
- Convert 15 dangling design/*.md links to the punktfunk-planning
prose convention (those docs live in the private planning repo).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Every other distro has a full Host Setup page; Arch only had table rows. Add
docs/arch.md (signed pacman binary repo: key import + repo + install, GPU
prereqs, service/linger, web console, client, PKGBUILD appendix), slot it into
the nav after fedora-kde, and point the install/client tables at it. Update the
client-install rows from 'from the PKGBUILD' to the binary repo now that it exists.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Plugin self-update (no Decky store): CI publishes a per-channel manifest.json
({version, immutable per-version artifact, sha256}) beside the zip and bakes
update.json {channel, manifest} into the plugin. main.py `check_update` reads the
installed version from package.json (the value Decky reports — not plugin.json),
fetches the channel manifest, and the frontend shows an "Update to vX" button that
drives Decky Loader's own install RPC (root downloads + SHA-256-verifies + hot-reloads).
CI now stamps a plain-numeric semver (0.3.<run> canary / X.Y.Z stable) into
package.json — a -ciN suffix would mis-order under compare-versions.
Linux client: `--fullscreen` (plus SteamDeck/gamescope env fallback) enters GTK
fullscreen on stream start so Gaming-Mode chrome is hidden; native-mode resolution
falls back to the display's first monitor when the window isn't mapped yet (was
dropping to the 1080p floor — wrong on the Deck's 1280×800); add a confirmed
"Remove saved host" action (KnownHosts::remove_by_fp).
Docs: new docs/steam-deck.md (Decky install/pair/stream/self-update/troubleshooting),
wired into meta.json nav, and cross-linked from clients/install-client/channels. This
is the page docs.punktfunk.unom.io/docs/steam-deck — the website's download link
pointed at it before it existed; committing it makes that link resolve.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Android app is in Google Play Internal Testing, so the public Play Store URL
doesn't resolve for non-testers. Lead the Android install instructions with a
"request a tester invite on Discord" CTA (the Play listing unlocks once a Google
account is added to the test track), and surface the Discord + r/Punktfunk
community links in the README, the docs intro, and the docs-site nav.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Refresh the README and documentation for public visitors:
- README: public-facing rewrite with accurate status for all four native
clients (macOS, Linux, Windows, Android) and the Windows host.
- docs site: fix stale client status (Android is a full client, not a
scaffold; Windows client is stage-1 complete + signed MSIX), add the
missing Android client section, correct "which client" guidance.
- Windows host: corrected from "deferred/scoped" to implemented & shipping
(NVIDIA-only, x64-only) across windows-host, roadmap, status,
requirements, running-as-a-service, and the README.
- Remove internal infrastructure from public docs (box names, private IPs,
SSH/token commands, deploy topology); rewrite status.md as a public
project-status page; sanitize ci.md and implementation-plan.md.
- Update clients/android and clients/apple READMEs to current state.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Per-device install steps in one place: Linux (Flatpak via flatpak.unom.io +
native apt/rpm/Arch), Steam Deck, Windows (signed MSIX from the registry),
macOS (notarized DMG from releases), and iOS/Android (store/beta links). Adds
it to the Connecting nav and cross-links clients.md, whose Linux/Flatpak bullet
now points at the hosted flatpak.unom.io repo instead of the bundle README.
Mobile store/TestFlight URLs are placeholders pending the public listings.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two bodies of work in one commit (the rename moved files the fixes also touched).
Naming/structure cleanup (pre-launch):
- Host modules m3.rs->punktfunk1.rs, m0.rs->spike.rs; CLI m3-host->punktfunk1-host,
m0->spike; bare `punktfunk-host` now prints help. Types M3Options/M3Source->
Punktfunk1Options/Punktfunk1Source.
- Clients consolidated out of crates/ into clients/: punktfunk-client-rs->
clients/probe (crate punktfunk-probe), client-linux->clients/linux,
client-windows->clients/windows, punktfunk-android->clients/android/native
(crate punktfunk-client-android; kept [lib] name=punktfunk_android so the JNI
contract is unchanged). crates/ now holds only core + host.
- Milestone codes M0-M4 purged from code/CLI/CLAUDE.md/README/docs/docs-site,
kept only in docs/implementation-plan.md. docs/m2-plan.md->
docs/gamestream-host-plan.md. CI/gradle/flatpak paths updated.
Client loss-recovery (video froze and never recovered after a brief drop):
- Export punktfunk_connection_frames_dropped through the C ABI (the core already
tracked it for the client keyframe-recovery loop; it was never reachable from
the ABI clients). Regenerated punktfunk_core.h.
- Apple (StreamPump + Stage2Pipeline) and Android (decode.rs) now poll
frames_dropped and request a keyframe when it climbs -- the same loss-driven
recovery Linux/Windows already had. Under infinite GOP the decoder silently
conceals reference-missing frames, so the decode-error trigger rarely fires.
Apple rumble robustness (worked then went spotty -- DualSense + Xbox):
- Add CHHapticEngine stopped/reset handlers (rebuild on app background / audio
interruption / server reset) and drop the permanent `broken` latch on a
transient drive failure; latch only when the controller truly has no haptics.
- Surface swallowed SDL set_rumble errors on Linux/Windows + diagnostic logging.
Verified: cargo build/clippy/fmt --workspace, C-ABI harness, header drift.
Not runnable on this box (verify in CI): Gitea workflows, gradle/Android,
flatpak, Swift/decky.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The winit-commit docs claimed "Reactor rejected, no SwapChainPanel hatch" — that was wrong.
windows-rs PR #4499 added the SwapChainPanel widget; the client now uses WinUI 3 via
windows-reactor. Update CLAUDE.md M4, the bootstrap-doc status banner (reactor integration:
pinned git dep, CARGO_WORKSPACE_DIR, App-SDK build.rs, LL-hook stream input), and the
docs-site clients page (WinUI 3, launch-and-pick-a-host).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds the SDL3 gamepad service (near-verbatim port of the GTK client's — SDL3 is
cross-platform) and wires it into the winit app: per-session capture (buttons/axes,
DualSense touchpad + motion 0xCC), feedback (rumble, lightbar, raw DualSense effects),
single-pad-forwarded model with auto pad-type from the physical controller. Built from
source on Windows (no system SDL3).
- gamepad.rs: GamepadService (app-lifetime SDL thread) attach/detach on session
connect/end; auto_pref resolves "Automatic" to the attached pad's type.
- app.rs: hold the service, attach on Connected, detach on Ended/Failed/close. Also
simplify the keydown path (drop the identical if/else arms).
- main.rs: start the service for the windowed path, resolve GamepadPref from settings +
the physical pad.
Build gotcha documented + fixed in the dev loop: SDL3's build-from-source MSVC
precompiled-header chokes on the `ü` in the dev box's username embedded in the cargo
registry path (MSB8084/C4828) — CARGO_HOME must be an ASCII path
(C:\Users\Public\.cargo). Unrelated to our code.
Docs: CLAUDE.md M4 + docs/windows-client-bootstrap.md status banner (winit-not-Reactor
rationale, CARGO_HOME gotcha, what's pending) + docs-site clients.md "Windows desktop
client (in development)". Crate is build + clippy + fmt + test green on
x86_64-pc-windows-msvc.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Make the host docs match the real distribution path and the actual CLI. Reviewed by a
multi-agent pass (6 editors against one verified fact sheet + an accuracy reviewer); its
findings (a wrong client-Recommends claim, a native-concurrency overstatement) folded in.
- Install front door: new README "Install (host)" method-picker + docs-site/install.md
(+ nav), routing each distro to its package registry; source build demoted to a fallback.
- Registry-first install: ubuntu-gnome/ubuntu-kde now lead with the apt registry (not a
cargo build); bazzite leads with the Gitea RPM registry (was COPR/source). Source builds
moved to an appendix.
- CLI accuracy: serve --native arms pairing from the web console (NOT --allow-pairing, which
with --require-pairing/--max-concurrent is m3-host-only); --open disables mandatory pairing.
host-cli/configuration/pairing/quickstart/troubleshooting corrected; mgmt API documented as
always HTTPS+token. Native host serves one session at a time (extras queue) — not multi.
- Firewall: real ports documented (native UDP 9777 + the ephemeral data port caveat +
GameStream ports) for Debian + Arch (ufw + nftables), not just Bazzite.
- Sync/accuracy: punktfunk-client (GTK4) presented as a shipping client (not "roadmap"),
punktfunk-client-rs as the headless tool; host Recommends punktfunk-web only (not the
client); COPR chroots f43/44; bootc header says Gitea registry not COPR.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the dev/agent-log pages with a proper user-facing doc set:
- Getting Started: Introduction (rewritten), How It Works, Quick Start.
- Host Setup: Requirements, then clean per-platform guides — Ubuntu GNOME,
Ubuntu KDE, Fedora KDE (new), Bazzite (rewritten) — plus Running as a Service
(desktop / headless GNOME / headless KDE).
- Connecting: Clients overview, Moonlight, Pairing & Trust.
- Configuration: host.env reference, Host CLI, Troubleshooting.
- The dev/design notes (architecture, roadmap, the deferred design specs, CI)
move to a clearly-separated "Project & Internals" nav section.
Removes the superseded box-specific pages (gnome-box, headless-box, linux-setup,
overview). status.md (the internal progress tracker, with box IPs) is kept as a
file but dropped from the public nav. Site builds clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>