• v0.38.0
    ci / changes (push) Successful in 17s
    windows-host / pr-lint (push) Skipped
    ci / bun-nix (push) Successful in 1m19s
    ci / docs-drift (push) Successful in 2m16s
    secret-scan / gitleaks (push) Successful in 19s
    android-screenshots / screenshots (push) Successful in 3m20s
    windows-host / package (arm64, 89841f5a57f2348b67ec0839b718f4bf4ea7d07c371c9ba4b77b6c790f918953, bun-windows-aarch64.zip, , --no-default-features --features gamestream, _arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 13m6s
    docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 1m30s
    docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 9s
    decky / build-publish (push) Successful in 36s
    docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 7s
    docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 9s
    docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 9s
    docker / builders (ci/gamescope-trixie.Dockerfile, punktfunk-gamescope-trixie) (push) Successful in 9s
    docker / builders (ci/flatpak-ci.Dockerfile, punktfunk-flatpak-ci) (push) Successful in 9s
    docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
    docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
    docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m51s
    sbom / sbom (push) Successful in 21s
    linux-client-screenshots / screenshots (push) Successful in 5m50s
    setup-binary / build (aarch64) (push) Successful in 3m55s
    setup-binary / build (x86_64) (push) Successful in 3m59s
    flatpak / build-publish (push) Successful in 8m19s
    ci / rust-arm64 (push) Successful in 1m28s
    ci / sdk-plugin-kit (push) Successful in 31s
    ci / decky-typecheck (push) Successful in 10s
    ci / web (push) Successful in 3m37s
    ci / docs-site (push) Successful in 3m43s
    windows-host / package (x64, 0a0620930b6675d7ba440e81f4e0e00d3cfbe096c4b140d3fff02205e9e18922, bun-windows-x64.zip, --features nvenc,qsv, --features nvenc,qsv, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 16m50s
    windows-host / canary-manifest (push) Skipped
    web-screenshots / screenshots (push) Successful in 9m11s
    docker / builders-arm64cross (push) Successful in 17s
    docker / deploy-docs (push) Successful in 29s
    rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m15s
    setup-binary / publish to the generic registry (push) Successful in 12s
    setup-binary / probe the published channel (push) Skipped
    windows-host / winget-source (push) Successful in 18s
    ci / rust (push) Successful in 11m39s
    deb / smoke-install (push) Successful in 6m44s
    deb / build-publish (push) Successful in 3m39s
    deb / build-publish-host (push) Successful in 7m9s
    deb / build-publish-gamescope (push) Successful in 18s
    deb / build-publish-client-arm64 (push) Successful in 3m8s
    arch / build-publish (push) Successful in 12m30s
    rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 25m58s
    android / android (push) Successful in 16m9s
    android / gate (push) Successful in 6s
    windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 6m28s
    windows-client / gate (push) Successful in 7s
    windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 11m8s
    apple / distribute (push) Successful in 23m46s
    apple / gate (push) Successful in 6s
    apple / swift (push) Successful in 8m45s
    apple / screenshots (push) Successful in 17m34s
    Stable

    enricobuehler released this 2026-09-15 00:15:15 +00:00 | 311 commits to main since this release

    Wire-compatible with 0.37.0: a new client streams from an old host and the other way round, so you can update one side at a time. The Windows display driver is unchanged from 0.37.0.

    0.38.0 comes days after 0.37.0. It carries fixes we did not want to hold back: a Windows update that left the old display driver running, a stuttering stream on Windows hosts, and a Siri Remote pointer that froze. Picture fit and controller mouse came in with them, and new features belong in a minor release, not a patch.

    • Picture fit: crop or stretch the stream to your screen on Linux, Windows, Mac, iPhone, iPad, Apple TV and Android. A device joining a display another device sized gets a picture framed for its own screen from Linux hosts with a hardware encoder.
    • Controller mouse. A dial button turns your controller into the host's mouse, for the launcher or dialog that ignores controllers.
    • Apple TV catches up with the 0.37 app: tabs, the Library with details, its own presets and dial. The Siri Remote pointer no longer freezes after the first click.
    • Windows: the installer checks the display driver really loaded. A host that said "driver outdated" after updating to 0.37.0 streams again.
    • Windows hosts stop stuttering on a monitor that keeps waking up, and a controller keeps its player slot when it reconnects quickly.
    • Library titles show their description, tags and player count on iPhone, iPad, Mac and Apple TV. Windows hosts add Epic, GOG and Xbox app tiles, and Moonlight shows the Desktop and launcher tiles instead of blanks.
    • Game Mode hosts: the pointer hides when the game hides it, scrolling moves at the right speed, and switching to the desktop no longer freezes the stream for 16 seconds.

    Before you update

    • Windows: Disable monitor devices (PnP) is now on. The update turns it on. If a monitor fails to come back after a stream, turn it off in the console's display settings; it then stays off.
    • Linux hosts: HDR now wins over 4:4:4. A client that asks for both gets HDR at 4:2:0, so games offer their HDR toggle. Turn HDR off in the client for 4:4:4 text.

    New

    Picture fit

    • Fit, Crop to fill or Stretch to fill, in each client's settings and in presets. Fit keeps the whole picture with bars; Crop fills the screen and cuts the edges; Stretch fills it and distorts. Mouse, touch and pen follow the picture you see. A size within a few pixels of 1:1, 2× or 3× snaps to it, so the picture stays sharp. On Android 9 and older, Crop shows the picture squeezed.
    • A joined display framed for the joiner. A phone joining a 4K desktop on a Linux host with a hardware encoder (AMD, Intel or NVIDIA) gets just the part it shows, at its own size, instead of decoding 4K with bars. Other hosts send the whole picture and the client frames it.
    • Sharper scaling on Linux and Steam Deck clients, and most Windows clients. A picture at an in-between size draws through sharp scaling filters instead of one soft blur, and whole-number scales stay pixel-exact.

    Controller mouse

    • Add Controller mouse to the quick-action dial on Linux, Windows, Android and Apple clients. The controller that opened the dial moves the pointer with the left stick, scrolls with the right, clicks with A and X, and B is Escape. The game sees an idle controller. Fire it again to hand the controller back. A dial opened by touch or keyboard switches every connected controller.

    Apple TV

    • Hosts · Library · Settings tab bar. One swipe up reaches any tab, and Menu inside a tab returns to its top.
    • The Library tab from iPhone and iPad: the shelf, the host filter and the sections. Holding a title opens its menu; Details opens a full-screen page with the cover, credits, genres and your play record. Customize reorders sections from each row's menu.
    • Settings in categories, with a sidebar. Codec, 4:4:4, 10-bit SDR, controller routing, Library and Start in now reach the TV, and the focused row's description reads at TV size.
    • Presets made on the TV. The Editing row creates, renames, duplicates and deletes them, and a changed row shows a dot that a long press resets.
    • A quick-action dial for the TV. It starts with End stream, Disconnect, Statistics, Guide and Quick access menu, and Settings › Quick Actions edits it.
    • The host page with sections, as on iPad and Mac. Play/Pause on a host card opens it, and the speed test waits for Start in its own pane.

    Library

    • Descriptions, tags and player counts from library plugins show on a title's details on iPhone, iPad, Mac and Apple TV. A cover a plugin sends inline loads.
    • Epic, GOG and Xbox app tiles on Windows hosts. A tile whose app is not installed is left out; its games still sync.

    Android

    • Settings → Input → Back opens quick actions. Turn it off and Back does nothing while the twist, a keyboard or a controller can open the dial.

    Improved

    • iPhone, iPad and Mac: a stream larger than the screen, such as 2880×2160 on an iPad Pro, downscales through Apple's own scaler, so fine text stays sharp. A host's address, port and Wake-on-LAN address edit in place on its page. Every cover names its host with the host's OS mark.
    • Two-finger scrolling on Android, iPhone, iPad and touchscreens on Linux and Windows starts from the first movement and moves smoothly, instead of late and in notches.
    • Hyprland is its own compositor choice on every client, and a Windows host no longer calls itself KDE.
    • PyroWave sessions ask for 4:4:4 on the switch alone, on Linux, Windows and Apple clients whose graphics can't decode HEVC 4:4:4.
    • Android: with a hardware keyboard attached, the app explains its key service once at launch and asks before turning it on. Keys go only to the streamed computer, and only during a stream.

    Fixed

    • Windows host: an update could leave the virtual display on the previous driver, and a reboot did not always recover it. The installer now restarts or rebinds the driver, and fails if it still isn't the new one. A controller that dropped and came back within a third of a second got a second controller beside the live one, so games moved it to another player. A host running under an account other than the system one could take a live pad's slot and lose controllers for the rest of the session.
    • Windows hosts on AMD and Intel graphics: a lost packet in AV1 from an AMD host heals without a full keyframe, and a second loss shortly after the first no longer costs one on AMD or Intel.
    • Linux hosts: a second device that joins a running session sees the same screen instead of a new display beside it. The first stream after boot has a pointer. On Hyprland, a menu opened by a click from the stream no longer closes at once. On KDE, a game that hides its pointer on a mirrored monitor hides it on the stream, and switching from Game Mode to the Plasma 6 desktop updates its portal. Desktop titles show their icons as library art. The Big Picture tile opens Big Picture when Steam is already running, a launcher tile opens again when you reconnect, and a device set to its own game session launches into it.
    • Gamescope and Game Mode hosts: the Steam overlay shows on the stream over a game that stops drawing. A game that hides its pointer no longer streams Steam's frozen arrow. Scrolling in Game Mode no longer moves 10 to 16 times too far. Switching from Game Mode to the desktop no longer freezes the stream for 16 seconds, and the next Game Mode session keeps HDR afterwards.
    • Every host: one out-of-range year or player count from a library plugin no longer fails the whole sync, and a large library with descriptions syncs. A kept display no longer makes the device it was kept for wait at the display limit. On Linux, an update restarts the plugin runner with the host. Moonlight shows the Desktop and launcher tiles with a picture instead of blank.
    • Web console: a plugin that restarts, as every plugin install does, no longer announces itself as new.
    • Linux, Windows and Steam Deck clients: the quick-action ring opened invisibly over a host desktop that wasn't changing, so presses could land on End stream unseen. An HEVC stream no longer freezes for good under heavy packet loss. When two machines share a hostname, a saved host card no longer switches to the other machine's address and reads Offline until you restart the app.
    • Linux, Windows and Apple clients: Select+A opens the dial when the hold-Select gesture is off.
    • iPhone, iPad, Mac and Apple TV: the speed test chart draws while the test runs, instead of only at the end. The Add Host address field no longer autocorrects or capitalizes. A launch animates out of the tile you pressed.
    • Apple TV: the Siri Remote pointer froze for the session after the first click, and now keeps moving. It no longer jumps back when your finger lifts, and a swipe aims the quick-action dial by direction. With only the remote, every part of the controller interface is reachable: settings tabs, value steps, host options and the library. A focused launcher tile's logo no longer disappears white on white. The controller legends name the remote's buttons when no controller is paired, and Play/Pause opens Options in the Library. The licenses screen scrolls back to its title, About shows the current app icon, and host options no longer offer a Copy link that does nothing on a TV.
    • Android: a picture could stay frozen after a still stretch on the host until something else changed. A library restored from cache keeps its developer, release year and genres. A Switch Pro controller's ZL and ZR reach the host.

    Security

    • Hosts and clients take a fixed TLS library. The one behind pairing, streaming and the web console accepted a TLS 1.3 handshake message at the wrong stage of a connection. Update both sides.

    For developers

    Compat card: CHANGELOG.md.
    Deep dive: git log v0.37.0..v0.38.0

    Downloads
  • v0.37.0
    secret-scan / gitleaks (push) Successful in 15s
    android / gate (push) Successful in 5s
    apple / gate (push) Successful in 6s
    deb / build-publish (push) Successful in 3m36s
    deb / build-publish-gamescope (push) Successful in 18s
    decky / build-publish (push) Successful in 31s
    docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 6s
    docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 6s
    docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 5s
    docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 6s
    docker / builders (ci/flatpak-ci.Dockerfile, punktfunk-flatpak-ci) (push) Successful in 7s
    docker / builders (ci/gamescope-trixie.Dockerfile, punktfunk-gamescope-trixie) (push) Successful in 6s
    docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 6s
    docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 7s
    deb / build-publish-client-arm64 (push) Successful in 2m4s
    docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 53s
    docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m16s
    linux-client-screenshots / screenshots (push) Successful in 2m50s
    sbom / sbom (push) Successful in 18s
    setup-binary / build (aarch64) (push) Successful in 4m26s
    deb / build-publish-host (push) Successful in 16m31s
    apple / swift (push) Successful in 18m38s
    setup-binary / build (x86_64) (push) Successful in 4m13s
    windows-client / gate (push) Successful in 6s
    arch / build-publish (push) Successful in 20m48s
    web-screenshots / screenshots (push) Successful in 7m39s
    rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 19m12s
    docker / builders-arm64cross (push) Successful in 6s
    docker / deploy-docs (push) Successful in 31s
    rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 18m37s
    setup-binary / publish to the generic registry (push) Successful in 13s
    setup-binary / probe the published channel (push) Skipped
    deb / smoke-install (push) Successful in 2m53s
    android / android (push) Successful in 13m11s
    apple / distribute (push) Successful in 23m37s
    windows-host / pr-lint (push) Skipped
    windows-host / package (arm64, 89841f5a57f2348b67ec0839b718f4bf4ea7d07c371c9ba4b77b6c790f918953, bun-windows-aarch64.zip, , --no-default-features --features gamestream, _arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 12m59s
    apple / screenshots (push) Successful in 21m48s
    windows-host / package (x64, 0a0620930b6675d7ba440e81f4e0e00d3cfbe096c4b140d3fff02205e9e18922, bun-windows-x64.zip, --features nvenc,qsv, --features nvenc,qsv, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 15m47s
    windows-host / canary-manifest (push) Skipped
    windows-host / winget-source (push) Successful in 15s
    windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 6m29s
    windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 10m50s
    flatpak / build-publish (push) Successful in 5m20s
    android-screenshots / screenshots (push) Successful in 6m53s
    ci / changes (push) Successful in 12s
    ci / rust-arm64 (push) Successful in 3m29s
    ci / web (push) Successful in 51s
    ci / docs-site (push) Successful in 53s
    ci / docs-drift (push) Successful in 34s
    ci / sdk-plugin-kit (push) Successful in 39s
    ci / decky-typecheck (push) Successful in 13s
    ci / bun-nix (push) Successful in 17s
    ci / rust (push) Successful in 8m28s
    Stable

    enricobuehler released this 2026-09-14 01:00:20 +00:00 | 471 commits to main since this release

    Wire-compatible with 0.36.x: a new client streams from an old host and the other way round, so you can update one side at a time — except on Windows, where the host and its display driver update together.

    • A rebuilt app for iPhone, iPad and Mac. Hosts and Library get their own tabs, a host card shows two lines with a page for the rest, and the Mac gets a sidebar and a window per host.
    • Sort your library by what you played last or most.
    • The same stats on every client. The overlay shows the figures Moonlight's overlay shows, measured the same way on Windows, Linux, Android, iPhone, iPad, Mac and Apple TV. Advanced statistics brings back the full capture-to-screen view.
    • A lost packet heals cleanly more often. HEVC from an NVIDIA host no longer leaves a grey smear that drifts with motion, repairs from Intel hosts now repair, and AV1 from an NVIDIA host heals exactly.
    • A host saved at its Tailscale address keeps it. Coming home no longer swaps it for the LAN address, so the host is still there on mobile data.
    • Windows hosts stream 5.1 and 7.1 without you changing Windows' speaker setup.
    • Steam Controller 2 on Apple TV, over Bluetooth. Behind a Puck on a Linux host it no longer drops into lizard mode.
    • Windows clients stop holding frames back. A queue that could add 45–65 ms on a 60 Hz panel is gone.

    Before you update

    • Windows: run the installer. It updates the host and the display driver together; expect a brief black screen while the driver reloads. A 0.36 driver under a 0.37 host refuses to stream and says "driver outdated".
    • Bazzite: restart once after this update. From now on an update restarts the host and its console for you, but the step from 0.36 still runs the old updater. Run systemctl --user restart punktfunk-web punktfunk-host afterwards, or the console fails to load its pages.
    • Profiles are now called presets. Your saved ones carry over, and links, shortcuts and commands that say profile still work.
    • The stats overlay starts on the shorter view. Turn on Advanced statistics in the client's settings to get the stage breakdown back.

    New

    iPhone, iPad and Mac

    • Hosts and Library are two tabs on iPhone and iPad. The Library is a list of sections — Desktops, Recently Played, Favorites, Launchers and Games — that Customize reorders or switches off. A long-press marks a favorite, search filters every row, and chips at the top pick the host. On an iPad the tab bar can turn into a sidebar.
    • Host cards are two lines: the name, then the status and the host's preset, with a star on the default host. Everything else moves to a host page — presets, connection, pairing, power, logs and removal, each with a line of explanation — which opens as a sheet of sections on an iPad. The card's menu keeps five everyday actions, and Forget and Remove ask first.
    • Title details. A long-press on a title leads with Play, or Resume when it is running, and Details shows the cover, store, credits, genres and your play record.
    • On a Mac, a sidebar and a window per host. The sidebar holds Hosts and the Library, and ⌘1 and ⌘2 switch between them. A card's ⓘ opens that host's page in its own window. Text in forms, popovers and sheets is sized for the Mac.
    • The speed test is a page with a live chart of the test as it runs, with the average and the recommended bitrate drawn across it. Apply says what it changed. On Apple TV too.

    Library and presets

    • Sort by Recent or Most played, from the play time the host already records, in the console view, the Linux and Windows apps and the Apple apps. A library from an older host sorts as before.
    • Profiles are now presets in every app, link and command. Saved presets carry over, and an older app on another device keeps seeing them. Links take preset= and still read profile=; punktfunk presets replaces punktfunk profiles, which still works.

    Statistics

    • One overlay, one set of numbers. Every client measures and labels its stats the same way, so a figure on a Mac means what it means on Android. By default the overlay shows the figures Moonlight's overlay shows, as averages.
    • Advanced statistics, a new switch in each client's settings, shows capture to screen as a median and a slow-frame figure, and every stage between. It belongs to the device, so a preset never changes it.
    • The console's Performance page reads in milliseconds, against a line at one frame for the stream's rate. It charts the round trip, and a counter the host can't see leaves a gap instead of a flat zero.
    • Windows host recordings show where the time goes: waiting for a free buffer, encoding, and the hand-off to the host, instead of one lump. Every host also records what sealing and sending each frame costs.

    Apple TV

    • Steam Controller 2 over Bluetooth. Turn on capture in settings and Steam Input, the trackpads, gyro and rumble reach the host, instead of a generic pad in lizard mode. It starts off because turning it on can ask for Bluetooth access.
    • The Liquid Glass icon, the look every other Apple platform already had, with its layers moving on focus.

    Audio

    • 5.1 in the layout LG TVs decode natively. The host can send surround the way the TV's own decoder expects, so the webOS app passes it to a receiver without re-encoding every packet.

    Docs

    • Troubleshooting is five shorter pages: startup, connecting, the stream, input and audio. A new guide to reporting an issue builds one file with every log a report needs, and the stats page leads with the view Moonlight users know. Profiles and links is now Presets and links.

    Improved

    • Windows clients on integrated graphics: the D3D11 decode path no longer copies every frame an extra time, and converts colour on the GPU the way the Vulkan path does. That helps 4K HDR on laptops such as those with a Radeon 780M.
    • Windows clients on older AMD drivers get one warning when an HDR stream might paint green on Vulkan. Updating to Adrenalin 25.9.1 or later fixes it; nothing is switched for you.
    • Linux and Windows clients skip a decoder their graphics can't run before the stream starts, instead of after the first frame.

    Fixed

    • Every client: a host saved at a Tailscale address keeps it. The saved address used to follow whichever address answered, so turning the VPN off at home swapped it for the LAN one. A host that stops answering where it was saved is looked for at its live address and the last three it used.
    • Dual-boot hosts: both installs of one box stay apart when you tap a card, add a host, pair or open a link. A tap on one no longer dials the other and fails, and a launch no longer takes the other install's preset or clipboard choice.
    • Lost packets: HEVC from an NVIDIA host no longer smears grey after a loss during a repair, as reported on 0.36. The picture unfreezes only once the repair has reached every damaged row, instead of one cycle early. AV1 from an NVIDIA host heals exactly instead of carrying damage until a keyframe.
    • Linux hosts on Intel graphics: the gradual repair after a loss refreshes the picture. It used to refresh nothing, so the damage stayed until a keyframe.
    • Windows clients on AMD graphics: HEVC from an NVIDIA host no longer decodes wrong until the next keyframe when the repair reaches back past more than one frame.
    • Windows clients: a PC whose graphics can't decode HEVC no longer starts every stream twice.
    • Linux and Windows clients: frame pacing reads the panel's real refresh again, so the host lines frames up with your screen; a refresh change mid-stream re-learns it. Switching to HDR no longer crashes when the display layout changes at the same moment.
    • Android: a mouse's side button that Android turns into Back goes to the host, including on Samsung's One UI 8, where that mapping can't be changed; the Back gesture still opens the quick-action ring. Leaving a stream started from the console no longer flashes the touch interface while the controller comes back. A Steam Controller 2 behind a Puck no longer goes dead for a moment every three seconds, and its rumble no longer replays stale levels after a stall.
    • iPhone and iPad: the pairing prompt is a readable alert on iOS 26, and the trust card fits a phone held sideways.
    • Apple TV: a host card's Edit opens the host editor instead of closing the menu.
    • Steam Controller 2 on a Linux host: haptics and mode changes no longer wait one to three seconds, and the pad no longer drops into lizard mode. Steam no longer offers a firmware update for a pad behind a Puck on every stream.
    • Hosts next to Sunshine: Linux setup no longer turns on Moonlight compatibility, since both hosts want the same ports; turning it on yourself still works, with a warning. Omarchy and SteamOS setup move the console's port off Sunshine's before handing off, and Omarchy's firewall opens the moved port, so the library loads. Omarchy setup applies the host options you chose again, and a fresh Windows install gets its default host settings.
    • Windows host: a 5.1 or 7.1 session carries surround without setting Windows' speakers by hand; the host sets its own virtual speakers and leaves your real hardware alone. When Sunshine holds port 47990, the firewall now opens 47991, where Punktfunk moved, so the library loads on clients again; upgrading heals an affected box. A display driver that can't start its graphics device reloads once instead of failing every session until a reboot.
    • Gamescope hosts: on Arch, Debian and Fedora, a host without the distro's own gamescope no longer streams a black screen; our gamescope package now brings the helper it starts every session through. A kept gamescope that crashed is no longer handed to the next client. One failed HDR attempt no longer keeps every later session in SDR until the host restarts.
    • Bazzite: an update restarts the host and its console, so the console no longer fails with "Failed to fetch dynamically imported module" until you restart it by hand.

    For developers

    Compat card: CHANGELOG.md.
    Deep dive: git log v0.36.0..v0.37.0

    Downloads
  • v0.36.0
    audit / bun-audit (plugin-kit) (push) Successful in 20s
    audit / bun-audit (web) (push) Successful in 19s
    audit / cargo-audit (push) Successful in 32s
    audit / pnpm-audit (push) Successful in 9s
    audit / bun-audit (sdk) (push) Successful in 21s
    audit / docs-site-audit (push) Successful in 29s
    ci / changes (push) Successful in 17s
    ci / bun-nix (push) Successful in 30s
    ci / docs-drift (push) Successful in 32s
    macos-host / check (push) Successful in 59s
    audit / license-gate (push) Successful in 7m6s
    audit / miri (push) Successful in 7m16s
    audit / c-abi-asan (push) Successful in 7m36s
    nix / gate (push) Successful in 8s
    secret-scan / gitleaks (push) Successful in 17s
    windows-drivers / gate (push) Successful in 6s
    android-screenshots / screenshots (push) Successful in 1m58s
    decky / build-publish (push) Successful in 36s
    arch / build-publish (push) Successful in 7m46s
    flatpak / build-publish (push) Successful in 4m19s
    sbom / sbom (push) Successful in 21s
    linux-client-screenshots / screenshots (push) Successful in 7m31s
    web-screenshots / screenshots (push) Successful in 6m23s
    ci / web (push) Successful in 1m34s
    ci / docs-site (push) Successful in 49s
    ci / sdk-plugin-kit (push) Successful in 51s
    ci / decky-typecheck (push) Successful in 10s
    ci / rust-arm64 (push) Successful in 4m4s
    docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 7s
    docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 6s
    docker / builders-arm64cross (push) Successful in 9s
    docker / deploy-docs (push) Successful in 16s
    docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 6s
    docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
    docker / builders (ci/flatpak-ci.Dockerfile, punktfunk-flatpak-ci) (push) Successful in 6s
    docker / builders (ci/gamescope-trixie.Dockerfile, punktfunk-gamescope-trixie) (push) Successful in 6s
    docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 7s
    docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 7s
    docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 1m2s
    docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 12s
    setup-binary / probe the published channel (push) Successful in 16s
    setup-binary / build (aarch64) (push) Successful in 4m16s
    setup-binary / build (x86_64) (push) Successful in 3m58s
    setup-binary / publish to the generic registry (push) Successful in 13s
    rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m57s
    deb / build-publish (push) Successful in 5m28s
    ci / rust (push) Failing after 11m55s
    deb / smoke-install (push) Successful in 7m7s
    deb / build-publish-gamescope (push) Successful in 57s
    deb / build-publish-host (push) Successful in 4m42s
    deb / build-publish-client-arm64 (push) Successful in 1m50s
    windows-host / package (arm64, 89841f5a57f2348b67ec0839b718f4bf4ea7d07c371c9ba4b77b6c790f918953, bun-windows-aarch64.zip, , --no-default-features --features gamestream, _arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 12m14s
    windows-host / pr-lint (push) Skipped
    rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 24m35s
    nix / flake (push) Successful in 20m36s
    windows-host / package (x64, 0a0620930b6675d7ba440e81f4e0e00d3cfbe096c4b140d3fff02205e9e18922, bun-windows-x64.zip, --features nvenc,qsv, --features nvenc,qsv, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 15m35s
    windows-host / canary-manifest (push) Skipped
    android / gate (push) Successful in 7s
    windows-host / winget-source (push) Successful in 17s
    android / android (push) Failing after 7m29s
    apple / distribute (push) Successful in 22m22s
    apple / gate (push) Successful in 7s
    apple / swift (push) Successful in 7m51s
    windows-drivers / probe-and-proto (push) Successful in 18s
    windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 6m18s
    windows-client / gate (push) Successful in 12s
    windows-drivers / driver-build (push) Successful in 3m25s
    apple / screenshots (push) Successful in 15m52s
    windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 10m24s
    Stable

    enricobuehler released this 2026-09-12 01:04:36 +00:00 | 720 commits to main since this release

    Wire-compatible with 0.35.x: a new client streams from an old host and the other way round, so you can update one side at a time. On Windows the installer still updates the host and its display driver together.

    • Let a friend in from the internet, safely. A device knocking from outside your network is marked, can't be approved by its name, and gets in only with a PIN you arm for that one device.
    • Each device gets its own display settings. The TV keeps its screen for hours while the tablet's goes at once, and a phone can be capped below 4K.
    • A rebuilt web console. A live map of your screens, five destinations, and it follows your desktop's theme.
    • iPhone and iPad stream to an external monitor at the monitor's own size and refresh.
    • Android keeps a stream running in the background, and a keyboard's Alt+Tab, Win chords and Korean and Japanese keys reach the host.
    • Apple devices heal a lost packet without a full refresh, and a notched Mac fills the whole screen.
    • Android handhelds pace frames evenly, and hosts show up on Wi-Fi that used to hide them.
    • Gamescope hosts stream to Linux clients again, and Hyprland keeps your screen across a reconnect.

    Before you update

    • Windows 10 can't run the host. The installer now refuses a host install below Windows 11 22H2 before it changes anything; the virtual display never started there. The client still installs on Windows 10.

    New

    Pairing and guests

    • Knocks from the internet are marked. The console tags a pending device that knocked from outside your network "From the internet" and offers no Approve for it. Arm PIN opens a PIN for that one device; a PIN you armed for your own next device never admits it. Devices on your network and on Tailscale pair as before.
    • "Until they disconnect." A new expiry for a paired device: a minute after its last session ends, its record is removed, so nothing is left to clean up. It is the default for a PIN armed for a device from the internet.
    • The Connect card's link works on a new device. It now carries the host's address and fingerprint, so a friend's first connect is verified instead of blind.
    • The Friends over the internet guide covers port forwarding as the last resort, with the rules above.

    Displays

    • Each paired device can have its own display settings, from its row on the console's Devices page. Choose how long its screen stays after it leaves, the largest size and refresh it gets, and what happens when its mode clashes with another device's. On Linux it can also choose whether your monitors go dark, and the scale its screen starts at. Anything left unset follows the host.
    • A capped device is told what it gets. It keeps what fits and loses only the rest: a phone capped at 1440p60 that asks for 1080p at 240 Hz streams 1080p60.
    • Keep one monitor on while a device takes over the rest, on KDE.

    Web console

    • Displays is a live map of your screens. Drag a screen to arrange it, pick a preset right on the page, and one sentence says what happens when a device connects.
    • Five destinations: Home, Devices, Displays, Library and Host, with the rest under Manage. A phone gets a bottom bar and a list, a tablet a rail of icons. A plugin's page is pinned from the Plugins page.
    • The console follows your desktop's theme on GNOME, Plasma, COSMIC, Hyprland, sway and Windows. Settings → Appearance overrides it, and a chosen accent recolours the whole console.
    • The activity feed keeps the newest dozen events, with a page of its own for the rest.
    • Automation suggests what the host knows: events by name, devices, and games with their covers.

    iPhone, iPad and Mac

    • An external monitor gets the stream. On a USB-C or AirPlay monitor the picture moves there at the monitor's size and top refresh, so a 120 Hz monitor gets 120 fps. Touch, the stats and the quick-action ring stay on the phone; unplugging hands the picture back.
    • L3 and R3 on the on-screen controller, on iPhone, iPad and Android.
    • "This display" is your Mac panel's real size. A scaled Mac used to stream the larger picture the system shrinks: 3420×2224 on a 2560×1664 MacBook Air.
    • Notched Macs. Full screen fills the panel, camera housing included, and a new "This display (below the notch)" mode sits flush under it.

    Android

    • Keep streaming in the background. Turn it on in settings and a glance at another app no longer ends the stream: the sound keeps playing, and the notification's End button stops it. Not on Android TV.
    • Every key reaches the host. Turn on Punktfunk keyboard shortcuts under Android's Accessibility settings and Alt+Tab, Win chords and the Language key reach the host; without it, Alt+` stands in for Alt+Tab. The Korean 한/영 and 한자 keys, the Japanese input keys and the Brazilian ABNT2 extras reach it too.
    • A mouse's Back button goes to the host, and Ctrl+Alt+Shift+O opens the quick-action ring from a keyboard.
    • Steam Controller 2. A wired SC2, a Puck or a DualSense keeps its USB permission across plugs, including on Android TV where the prompt often never appeared. An uncaptured SC2 drives the menus as a pad and names itself on the controller chip.
    • A hovering mouse moves the console's cursor. A TV remote, arrow keys and Escape drive the quick-action ring.
    • A keyboard on a combined receiver types in the console, and its Y and X keys open a tile's options.
    • The stats name Android's frame-rate cap. When Android holds the app below the panel's rate, the first line says so and names the setting to check. The everyday tier shows only lost frames.

    Hyprland and Omarchy

    • Keep-alive on Hyprland. A disconnect leaves the streamed screen up for the keep-alive window, and reconnecting returns to it instead of an empty one. When it does come down, its windows move to a physical monitor instead of disappearing.
    • A new Omarchy bar panel with Session, Pairing, Devices and Display sections. Super+Space gains rows for Dedicated display or This screen, a Moonlight PIN, Unpair and GameStream.
    • Tailscale reaches an Omarchy host that joins a tailnet later. Setup installs the firewall rule before the interface exists.

    Everywhere

    • The host names the screen it couldn't find. A host set to stream a monitor it no longer has fails the session at once with that monitor's name, instead of a black screen for 15 seconds and a generic error. The console marks the missing screen.
    • Linux and Windows clients say when a pinned bitrate is too much for the device, instead of stuttering silently.
    • Choose the console password during setup on Linux. Keep the generated one, with the command that prints it, or type your own. On Windows, punktfunk-host web password in an elevated PowerShell prints it after a silent or winget install.
    • The console's sign-in says when a locked-out attempt can retry.

    Improved

    • Recovery no longer feeds the overload it repairs. A client that can't decode the stream no longer gets a full keyframe on a fixed beat; each one that does not heal doubles the wait, up to 3 s. Loss protection follows what the network loses, not frames a slow client dropped, so the host stops spending bandwidth on parity it can't use.
    • Logs tell a network drop from a stalled client. The host logs what left its network card, the client logs how long nothing arrived versus how long it stopped reading, and Android logs every refresh-rate change of the panel.
    • The console's Logs tab shows host events instead of a wall of TLS handshakes.
    • PyroWave on Android TV. A device that can't decode it says "unsupported" and names the requirement, instead of offering a choice that did nothing.

    Fixed

    • iPhone, iPad, Apple TV and Mac: a single lost packet no longer freezes the picture about 300 ms for a full keyframe; the repair heals it. On an iPad, a fast trackpad double-click no longer hides the cursor for half a second on every later click.
    • Windows clients on AMD graphics, such as the ROG Ally: after a lost frame, HEVC no longer decodes smeared until the next keyframe.
    • Linux and Windows clients: V-sync on no longer tears on a display that offers only immediate and FIFO presentation.
    • Android: hosts appear on Wi-Fi networks that stop forwarding discovery to a power-saving phone, such as UniFi's default. A phone started with a controller attached asks for the network permission, so its host list is no longer empty. A stream no longer skips every other frame after a short slow patch or a refresh-rate switch. A paired host stays reachable after the TV moves between Wi-Fi and Ethernet. The TV stats overlay fits the screen.
    • Dual-boot hosts: both OS installs of one box stay two hosts. Pairing one no longer retires the other, forgetting by address refuses to remove both, and the online dot checks which one answered. A machine that took a sleeping host's address no longer reads as that host, so Wake-on-LAN fires.
    • Linux host: Steam, Lutris and other X11 apps launched from the library open instead of failing "Unable to open a connection to X". A second session on a GNOME or KDE host no longer stalls at start. A KDE host above 60 Hz keeps the refresh rate you asked for when KDE remembered an old layout. Super no longer sticks on Hyprland after a client loses a key release. The plugin runner can be switched back on after it was switched off, and an Ubuntu install no longer refuses every plugin. Windows-only display switches no longer show on a Linux host.
    • Gamescope hosts: Linux clients get a picture again, HDR included. On NixOS a nested session finds Steam and its reaper.
    • SteamOS host: a desktop with an NVIDIA card streams. A host built without an encoder no longer blanks a KDE desk eight times before giving up. A source build's update card reports the commit it built and offers an update only when there is one.
    • Setup: Bazzite no longer waits forever on "Controller access".
    • Omarchy: the menu's checked capture row follows a PUNKTFUNK_CAPTURE_MONITOR override.
    • Windows host: a hung display driver no longer hangs every session while the host reports busy; the host reloads it. One tray icon per signed-in user again. Uninstalling the client removes its Start menu and desktop shortcuts.
    • Web console: Firefox's saved password signs in, and a signed-in visit to the sign-in page goes on to where you were headed. Game sources carry their plugin's name, their settings open for a plugin that keeps them on its own page, a running source shows as running, and a refusal says why.

    Security

    • A device from the internet can't be admitted by its name. The host itself refuses Approve for it; only a PIN armed for that device works.
    • The host checks that a first packet's sender can answer before it spends a handshake on it, so a spoofed flood can't make it amplify.
    • The web console's dependencies moved past two Next.js remote code execution advisories and two others.
    • A crafted sign-in link can no longer loop the console, and the redirect check behind it now has a test.
    • A configured gamescope layer path is quoted, so shell syntax in it can't run.

    Thanks

    One person outside the team wrote code that ships in this release.

    • luxus brought gamescope hosts back for Linux clients: the PipeWire format negotiation, HDR capture and the NixOS wrapper fixes. They made Hyprland keep a reconnecting client's screen and windows, rebuilt the Omarchy bar panel and its Super+Space host menu, and set up Tailscale's firewall rule ahead of the interface. They also narrowed which CI lanes a change wakes.

    For developers

    Compat card: CHANGELOG.md.
    Deep dive: git log v0.35.0..v0.36.0

    Downloads
  • v0.35.0
    ci / web (push) Successful in 47s
    ci / docs-site (push) Successful in 51s
    ci / decky-typecheck (push) Successful in 11s
    ci / bun-nix (push) Successful in 12s
    ci / sdk-plugin-kit (push) Successful in 35s
    ci / docs-drift (push) Successful in 37s
    secret-scan / gitleaks (push) Successful in 16s
    ci / rust-arm64 (push) Successful in 19m32s
    android-screenshots / screenshots (push) Successful in 4m58s
    macos-host / check (push) Successful in 3m45s
    android / android (push) Successful in 13m39s
    decky / build-publish (push) Successful in 40s
    nix / flake (push) Successful in 26m43s
    arch / build-publish (push) Successful in 16m33s
    sbom / sbom (push) Successful in 55s
    linux-client-screenshots / screenshots (push) Successful in 7m42s
    ci / rust (push) Successful in 47m8s
    flatpak / build-publish (push) Successful in 9m22s
    windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 6m54s
    rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 21m17s
    rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 21m22s
    audit / cargo-audit (push) Successful in 46s
    audit / bun-audit (plugin-kit) (push) Successful in 15s
    audit / bun-audit (sdk) (push) Successful in 2m41s
    audit / docs-site-audit (push) Successful in 2m39s
    audit / pnpm-audit (push) Successful in 27s
    audit / license-gate (push) Successful in 5m20s
    audit / miri (push) Successful in 7m9s
    audit / c-abi-asan (push) Successful in 19m35s
    web-screenshots / screenshots (push) Successful in 21m2s
    docker / builders-arm64cross (push) Successful in 6s
    docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 10s
    docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 8s
    docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 8s
    docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 8s
    docker / builders (ci/flatpak-ci.Dockerfile, punktfunk-flatpak-ci) (push) Successful in 7s
    docker / builders (ci/gamescope-trixie.Dockerfile, punktfunk-gamescope-trixie) (push) Successful in 7s
    docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 11s
    docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 6s
    docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 21s
    docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 16s
    docker / deploy-docs (push) Successful in 12s
    setup-binary / publish to the generic registry (push) Successful in 20s
    windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 11m15s
    setup-binary / build (aarch64) (push) Successful in 5m33s
    setup-binary / build (x86_64) (push) Successful in 4m57s
    setup-binary / probe the published channel (push) Skipped
    audit / bun-audit (web) (push) Failing after 1m13s
    deb / smoke-install (push) Successful in 13m16s
    deb / build-publish (push) Successful in 4m46s
    deb / build-publish-host (push) Successful in 6m30s
    deb / build-publish-gamescope (push) Successful in 15s
    deb / build-publish-client-arm64 (push) Successful in 2m25s
    windows-host / package (arm64, 89841f5a57f2348b67ec0839b718f4bf4ea7d07c371c9ba4b77b6c790f918953, bun-windows-aarch64.zip, , --no-default-features --features gamestream, _arm64, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 14m20s
    windows-host / pr-lint (push) Skipped
    windows-host / package (x64, 0a0620930b6675d7ba440e81f4e0e00d3cfbe096c4b140d3fff02205e9e18922, bun-windows-x64.zip, --features nvenc,qsv, --features nvenc,qsv, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 17m4s
    windows-host / canary-manifest (push) Skipped
    windows-host / winget-source (push) Successful in 25s
    apple / distribute (push) Successful in 37m38s
    apple / swift (push) Successful in 23m17s
    apple / screenshots (push) Successful in 29m47s
    Stable

    enricobuehler released this 2026-09-08 22:46:12 +00:00 | 1048 commits to main since this release

    Wire-compatible with 0.34.x: a new client streams from an old host and the other way round, so you can update one side at a time — except on Windows, where the host and its display driver update together.

    • Windows streams with less lag. The display driver encodes each frame the moment it is composed. Run the installer once; it updates host and driver as a pair.
    • Android decodes PyroWave, and Android and Apple clients can ask for 10-bit colour on an ordinary SDR screen.
    • A picked game's cover holds until the game is up, and a settings profile can be bound to one title.
    • Foldable phones split at the hinge, and you lay out the on-screen controller control by control.
    • A glitch heals without a full refresh on NVIDIA hosts and on AMD and Intel Linux hosts.
    • Steam Deck: stream a game from Steam's own Play button.
    • A browser can stream. Off until you turn it on at the host.
    • Pick where the app opens. "Start in" chooses the hosts list, the library or a default host's stream.

    A word of caution. This release rebuilds how every host encodes: Windows encodes inside the display driver, AMD and Intel Linux hosts run a new encoder, and FFmpeg is gone. Changes this large can carry issues we have not found yet. If a stream that was fine on 0.34 misbehaves, tell us, with the host log and the Status page's capture line.

    Before you update

    • Windows: run the installer. It updates the host and the display driver together; expect a brief black screen while the driver reloads. A 0.34 driver under a 0.35 host refuses to stream and says "driver outdated".
    • Apple and Android: the game-library switch is gone. Pairing decides whether you see games.
    • Android: clipboard sharing starts off. Turn it on per host if you want it.
    • Linux, unattended installs: --yes now adds you to the punktfunk group on every distro, not only Bazzite and Nobara. Pass --no-punktfunk-group to keep the old behaviour.

    New

    Library and launching

    • Launch hold. The cover flies out of its tile and holds over the stream until the host reports the game running; any press shows the stream early. Launchers never hold.
    • A settings profile per game. Options on a cover → "Settings profile…". A one-off choice beats the title, the title beats the host, the host beats the defaults.
    • A Desktop tile leads every shelf. It reads "Resume <title>" while the host has a game up, so you can rejoin a game the host started on its own. A host card names that game too.
    • Six more library sources, as plugins. Ubisoft Connect, Amazon Games and Battle.net on Windows; desktop entries, Flatpak, Bottles and itch.io on Linux; itch.io on Windows too. Install them under Game sources. A Windows launcher that lives in your user profile shows as "not installed" until you run punktfunk-host plugins grant <dir> once.
    • Steam Deck: Punktfunk hosts in Steam's "Play from" menu. The Play button becomes Stream while a host is chosen, and the stream runs as the game, with its art.
    • Linux desktop and Windows clients sort the library the way the console does.
    • Pick where the app opens. Settings → "Start in" chooses the hosts list (as before), the library, or straight into a host's stream. With one paired host that host is the default; with more, "Make default host" on a host's Options menu chooses.

    Controls

    • On-screen controller layout editor. Drag each stick and button, scale it or hide it, on Android, iPhone and iPad. A foldable half-opened on a table puts the picture on the upright half and the controller on the flat one.
    • Quick-action ring on a Mac. Stream menu, Ctrl+Alt+Shift+O, or Select+A on a pad.
    • Guide and Quick Access on the ring. Two new slots tap those buttons on the host's controller, so Steam's overlay is a ring press away.
    • Mac: the Steam Controller 2 over USB or a Puck dongle. Each pad on a Puck reaches the host as its own controller; macOS asks for Input Monitoring once. Windows hosts now present a Puck pad as a Steam Controller 2 instead of an Xbox pad.
    • Windows client: DualSense haptics and pad-speaker rows in settings, as the Linux client has had.
    • Overlay size is a setting on every client, and the ring steps it mid-stream. Android TV draws the overlay 1.75× by default; the Apple TV client already did.

    Picture

    • Android decodes PyroWave. A phone, tablet or TV with Vulkan 1.3 and the compute features the codec needs offers the row; the codec stays opt-in per session.
    • 10-bit colour without HDR. Android and Apple clients can ask for a 10-bit stream on an SDR panel, so gradients stop banding.
    • Windows: any GPU with a Windows H.264 or HEVC encoder can host. When the vendor's own encoder refuses, the host falls back to Windows' built-in one (8-bit only).
    • Windows: capture health on the Status page. The session card says healthy, idle, stalled or recovering, and a stalled stream walks a recovery ladder — encoder reset, swap chain, presentation, driver reload — instead of freezing.
    • Headless gamescope hosts get adaptive sync. Install punktfunk-gamescope +pfhdr10 or newer.

    Hosts and installs

    • Two games at once on one Linux host. On a gamescope-capable box, each client gets its own session — picture, keyboard, pad, audio and mic. Disconnecting one leaves the other running; reconnecting returns to it.
    • A browser can stream (preview). Turn the host's browser plane on (--webtransport); a browser pairs like any other device. Set the allowed pages too, or any page you have open could reach it. The client lives at punktfunk/client-web.
    • Linux: the one-liner downloads a setup program. It asks nothing after the settings screen, installs the client too (--client, or a Flatpak where your distro has no package), takes SteamOS through the guided path, trusts the web console's certificate so the browser opens it without a warning, and stops asking the package manager's own "proceed?". Re-running it upgrades a box that already has everything.
    • Windows: Punktfunk's own installer. Recommended or Custom, the web-console password shown once, the same silent flags as before. The wizard needs Windows 11; a silent install runs anywhere the host does. An ARM64 host installer for Snapdragon X ships on the canary channel — untested on hardware, video only.
    • Omarchy. The bar widget ships with the host package; its panel has Now, Stats (with sparklines), Displays, Pairing and Devices tabs; every client surface follows the Omarchy theme live; your saved hosts sit in Super+Space; host actions have their own Punktfunk Host menu; the client installs by default.
    • Friends over the internet. A guide to letting one friend reach one host without joining your network: Porthole for PC friends, Tailscale sharing for everything else, port forwarding if you run your own router.
    • Network speed test in the gamepad console's host menu — Android TV, Steam Deck, Linux console, webOS.
    • A screen reader hears the Android console. TalkBack names the focused row on home, the library and settings.
    • webOS: the controller-optimised UI is a switch, as on Android.

    Improved

    • Windows: the display driver encodes. At 4K120 on an RTX 4090 no frame waited more than 6 ms for the encoder, where the old path reached 48. The frame pool keeps the newest frame under load, HDR with 4:4:4 keeps full chroma, and REALTIME GPU priority is the default again.
    • AMD and Intel Linux hosts have their own encoder. A lost packet heals on the next frame instead of a full keyframe, a bitrate change lands in place, and HEVC 10-bit carries its HDR10 metadata. A mirrored monitor now encodes at the client's size, so a 4K screen to a Deck is not a 4K stream.
    • The packages carry no FFmpeg. Fedora needs no RPM Fusion, the Windows installer is smaller, NixOS loads Vulkan and VAAPI again, and a SteamOS host builds four minutes faster (delete target-steamos/ffmpeg to reclaim the space).
    • A glitch heals without a full refresh. NVIDIA hosts everywhere and AMD/Intel Linux hosts repair the picture row by row, without the bitrate spike an IDR costs. Windows NVIDIA hosts also stop forcing a full keyframe on every lost frame, and Apple clients accept the repaired frame instead of asking for one — a ~250 ms hitch per loss on Wi-Fi, gone.
    • Linux desktops keep the refresh rate they run at. Hyprland is captured directly (165 fps at 165 Hz where the portal gave 82), GNOME 49+ paints a frame when the stream asks for one, and KDE follows its own refresh signal and tears no more under load.
    • Audio on a bursty link. A Wi-Fi link that delivers audio in clumps no longer has each clump trimmed and concealed; and the loss-protection floor is now 5 %, so a two-packet burst on a clean link costs no frame.
    • The bitrate stays where your decoder has headroom. A phone decoding near its frame budget used to be pushed to the link's ceiling anyway, so every hiccup became a stall; the rate now parks there, or steps back one notch, and climbs again only once the decoder has room.
    • Trackpad scrolling matches your fingers, on Windows, Linux and Mac clients and on every host; it used to run about five times too far.
    • A sleeping host shows Offline, and auto-wake fires for it, on every client. A stale advert no longer reads as a live host.
    • Apple TV presents video through the system renderer on tvOS 17.4 and newer, dropping a two-refresh delay. Menu backs out of every screen, and the Siri Remote drives the ring.
    • The quick-action dial follows the left stick on Apple and Android, as on the desktop.
    • Every connected controller drives the desktop launcher, not only the newest, and a Deck in Game Mode forwards every pad Steam Input wraps.
    • The console's refresh row keeps 144, 165 and 240 Hz, and a resolution or rate one client cannot list survives opening Settings there.
    • Windows: a standby TV that keeps re-lighting itself is parked for the session instead of costing a rebuild each time.
    • A pinned data port works behind NAT: the host answers where the hole-punch came from.
    • Windows client crashes name the faulting module in client.log, and the client ships its own VC++ runtime, so an old redistributable no longer crashes it on the first text.

    Fixed

    • Android: Select+A opens the ring on any pad. Resetting a profile's 10-bit row sticks. "Low-latency mode" off now keeps the same decoder with its boosts off, so "Prefer smoothness" works in both states; if you turned it off for a device that misbehaved, try it on again. A Steam Controller 2 over Bluetooth now behaves as a controller instead of a mouse and keyboard, rumbles and reports gyro, and comes back after powering off. Hosts appear reliably: the app runs one discovery browse instead of two that split each other's answers.
    • iPad and Apple TV: audio no longer sits 40–90 ms behind the picture with the mic off, and the mic path no longer drops out every half minute.
    • Mac: a Mac with no microphone connects instead of crashing. The desktop mouse stops at the window edge. ⌘ chords pass through under the desktop mouse model. A wrong PIN says so instead of a status code.
    • Apple TV: the Siri Remote pointer no longer jumps toward wherever the surface is touched.
    • Windows host: RX 400/500 and Vega GPUs encode again. NVENC no longer pins a stream at 10 Mbps. A game's own display mode survives the host re-asserting its displays. A launched game starts in its own folder (Ryujinx runs). The forwarded cursor is no longer three times too large from a 300 % desktop. The sign-in, lock and UAC screens show in the stream instead of a frozen frame. A pointer gesture no longer rests one step behind. A resize on an idle desktop no longer ends the session. A host update whose download got stuck retries whole instead of failing on every attempt. An I-beam over a text box no longer draws as a grey block, and a moving mouse on a 240 Hz desktop no longer sends the client more frames than its decoder was sized for.
    • Windows client: the picture below the first tile row is no longer green on AMD GPUs with 4K120 AV1.
    • Linux host: a GNOME 50 host survives a mid-stream resize. An odd-width window from an Intel host is no longer sheared. A KDE session's streamed display sits at the desktop origin, so popups land on screen. AMD and Intel hosts offer AV1 again. A capture-loss rebuild replaces the stalled display instead of adding one.
    • Steam Deck host: a dedicated game session runs on its own gamescope, so a second launch no longer kills the stream seconds before it starts, and a Moonlight client switching Desktop to Game keeps its seat. A SteamOS host updates again after the preview channel moved FFmpeg ahead, and a rebuild that failed no longer runs for 25 minutes on every boot.
    • Every client: a damaged frame is held instead of shown, so the grey smear that lasted until a scene change is gone, and Intel Arc, Linux iGPU and older Windows GPU clients check before lifting a freeze. A scaled Wayland desktop no longer draws the forwarded pointer 2.25× too large. A game launched from the library no longer opens soft and stuttering: frames arriving while the cover still held were read as a backlog and cut the bitrate to a quarter before the first one was shown.
    • Hosts and pairing: one client stalling its handshake no longer blocks every other client's connect for up to 8 s. Forgetting one unpaired host no longer forgets them all; Windows Forget removes the host you picked. A pairing that failed to save says so instead of "Paired". Request access connects instead of cancelling itself. A host-side setup failure — no encoder, no display driver — reads as one on iPhone and Android.
    • Desktop client: capturing a quick-action chord no longer kills the app, closing the window no longer ends a live stream, an open dial no longer strands a button down on the host, duplicating a profile copies what is on screen, clearing the controller pin clears it, and a slow library fetch no longer overwrites the host you asked for last.
    • Controllers: two pads no longer swap rumble or raw reports, a DualSense's haptics and speaker come from its own pad, and its adaptive triggers fire in game.
    • Installer: a fresh Linux box gets a running web console, a box with no desktop is set up for gamescope, and Omarchy's desktop entries open every surface in app mode. NixOS's punktfunk-gamescope ships the reaper it starts games through, so a session no longer comes up empty.

    Security

    • Android: clipboard sharing starts off. Turn it on per host if you want it.
    • A fake advert on the LAN can no longer replace a saved host's wake address, and a machine that inherited a sleeping host's IP no longer passes as that host.
    • Windows: a secret planted before the host's first run is not adopted. A token, key or web-console password another local account left in the host's data directory is set aside; the installer rotates the password. Elevated helpers and the AMD driver library are loaded by absolute path. A plugin can no longer have the host end a process outside the streamed session, and a token set in host.env no longer reaches games and hooks.
    • Deleting a Moonlight device's access record ends its session instead of lifting every restriction on it.
    • punktfunk-client --library verifies the host again; an unpinned host is refused unless you pass --fp.
    • A pairing PIN stays out of the process list on Linux.
    • Browser plane: loopback-only routes are never answered cross-origin, and serve --open refuses to start with the plane on and no allowed pages.
    • A corrupt or hostile stream cannot crash the client: a reserved AV1 bit is a parse error, not an abort, and a host's audio settings are bounded before they size a buffer.
    • A GameStream pairing ceremony belongs to one peer; another host cannot hijack a client's PIN exchange. A LAN peer holding connections open can no longer exhaust the host's Moonlight or management listeners.
    • Windows: a link another account planted in the host's data directory is refused instead of hardened in place.
    • Local hardening: a plugin's freed launch port can no longer be squatted by another process, the web console verifies the host's own identity on its loopback hop, a seat display answers only its own session, and a browser's sign-in challenges are budgeted per address.

    Thanks

    Four people outside the team wrote code that ships in this release. The work is theirs, so they are named here.

    • Seenko built the Steam Deck integration: Punktfunk hosts in Steam's "Play from" menu, the Play button that becomes Stream, the per-game shortcut with the game's own art, and the Recent shelf entry. Seenko also made the overlay size a setting on every client, stepped from the ring mid-stream.
    • Sonar made the Steam Controller 2 work on a Mac over USB and the Puck dongle, each pad as its own controller and corrected against real hardware, and made a Windows host present a Puck pad as a Steam Controller 2 instead of an Xbox pad.
    • Keith Porcaro found and fixed the iPad and Apple TV audio sitting 40–90 ms behind the picture with the mic off.
    • luxus wrote the house-style gate that now checks every commit and comment in CI, then swept all 31 crates to meet it, and rebuilt how these notes are written — from the git log, at the version bump. They also made the audit job fail on unsound advisories, kept CI compiling when its build cache cannot authenticate, and put the SDK, the plugin kit and the Decky plugin under type-checking. None of it is a button you can press, and all of it is why the rest of this page is accurate.

    For developers

    Compat card: CHANGELOG.md.
    Deep dive: git log v0.34.0..v0.35.0

    Downloads
  • v0.34.0
    audit / bun-audit (plugin-kit) (push) Successful in 23s
    audit / bun-audit (sdk) (push) Successful in 21s
    audit / pnpm-audit (push) Successful in 20s
    audit / docs-site-audit (push) Successful in 26s
    audit / bun-audit (web) (push) Successful in 25s
    audit / cargo-audit (push) Successful in 49s
    ci / bun-nix (push) Successful in 38s
    ci / docs-site (push) Successful in 58s
    ci / docs-drift (push) Successful in 36s
    ci / rust-arm64 (push) Successful in 1m33s
    macos-host / check (push) Successful in 1m6s
    audit / license-gate (push) Successful in 6m49s
    audit / c-abi-asan (push) Successful in 5m59s
    ci / web (push) Successful in 1m13s
    audit / miri (push) Successful in 6m1s
    ci / rust (push) Successful in 6m57s
    nix / flake (push) Successful in 21m51s
    android-screenshots / screenshots (push) Successful in 1m37s
    deb / build-publish-gamescope (push) Successful in 1m4s
    docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 23s
    deb / build-publish-client-arm64 (push) Successful in 1m53s
    docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 16s
    docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 1m0s
    apple / swift (push) Successful in 2m16s
    docker / builders (ci/flatpak-ci.Dockerfile, punktfunk-flatpak-ci) (push) Successful in 16s
    docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 17s
    docker / builders (ci/gamescope-trixie.Dockerfile, punktfunk-gamescope-trixie) (push) Successful in 15s
    docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 23s
    docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 23s
    docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 1m24s
    docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m27s
    deb / build-publish (push) Successful in 5m27s
    deb / build-publish-host (push) Successful in 6m9s
    sbom / sbom (push) Successful in 37s
    linux-client-screenshots / screenshots (push) Successful in 4m11s
    docker / builders-arm64cross (push) Successful in 15s
    arch / build-publish (push) Successful in 9m50s
    docker / deploy-docs (push) Successful in 52s
    windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 9m1s
    android / android (push) Successful in 11m59s
    deb / smoke-install (push) Successful in 3m5s
    web-screenshots / screenshots (push) Successful in 6m46s
    flatpak / build-publish (push) Successful in 7m22s
    windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 4m19s
    decky / build-publish (push) Successful in 1m1s
    apple / distribute (push) Successful in 13m45s
    rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 17m59s
    rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 19m52s
    apple / screenshots (push) Successful in 10m48s
    windows-host / package (push) Successful in 12m38s
    windows-host / canary-manifest (push) Skipped
    windows-host / winget-source (push) Successful in 31s
    Stable

    enricobuehler released this 2026-08-31 01:16:00 +00:00 | 2352 commits to main since this release

    This release is for everyone who streams games or a desktop with Punktfunk. It works with 0.33.x, so everything you have already paired keeps working, and you can update one side at a time.

    The headline is a control surface for everyone who streams to a screen they hold. Touch has been able to move a cursor for a long time. It could not end a stream, show a keyboard, switch touch mode or send Ctrl+Alt+Del without leaving the picture. Now a two-finger twist on the stream opens a ring of six buttons under your fingers. You choose what the six are, and you edit them by using the ring itself rather than reading a list of names.

    Phones and tablets also get an on-screen controller. Show it from the ring when a game wants a gamepad and you do not have one with you. The host sees a controller arrive, exactly as if you had plugged one in.

    And the Steam Controller 2 goes much further than Linux. It now streams from an iPhone, iPad, Mac and Android device, and reaches a Windows host as well as a Linux one. It still arrives as itself, rather than flattened into a generic pad. That work came from a contributor, credited by name further down.

    TL;DR

    • A quick-action ring on the stream. Open it with a two-finger twist on a phone or tablet, a short Back on Apple TV, or Select+A on a controller anywhere.
    • An on-screen controller on Android, iPhone and iPad, for a game that needs a gamepad you did not bring.
    • The Steam Controller 2 now works from Apple and Android devices, and to a Windows host. Read "Before you update" if your host runs Windows.
    • Linux: the app stops opening fullscreen on an ordinary desktop. Our own Flatpak told it that every machine was a Steam Deck. Flatpak is the main Linux channel, so this reached most Linux users.
    • Apple: fixed a picture that froze while the sound kept playing. Only reconnecting cleared it. It now recovers on its own.
    • Windows: F11 no longer ends your session. On some graphics drivers, going fullscreen dropped the stream and then blamed the connection.

    What's in this release

    Before you update

    • Windows hosts, for the Steam Controller 2 only: reinstall the controller driver. Windows support for that pad needs a driver package your current install does not have. Run punktfunk-host.exe driver install --gamepad and reconnect the pad. Every other controller keeps working untouched, so skip this if you do not own one.
    • If you keep a virtual display on "Forever", read this before sending your host to sleep. Sleep, restart and shut down now clear the virtual displays first, so a wake starts clean. A display you pinned to Forever is kept on purpose, because that pin is what holds a game running across disconnects. If a wake lands on a black screen, release that display from the console under Virtual displays.
    • Windows: the tray icon's Exit entry now stops the host. It used to close only the icon and leave the host streaming. The menu says so before it acts. Signing out still leaves the host running, as before.

    New

    • The quick-action ring. A two-finger twist on the stream opens six buttons under your fingers, on Android, iPhone and iPad. About 10° starts it opening and 30° commits it, so letting go early winds it back in and sends nothing. The centre button opens the full catalogue and the resolution presets. Android's Back gesture opens the same ring instead of ending your session, and Apple TV opens it with a short press of Back. A controller opens it with Select+A on every client, and the host never sees those two presses.
    • You edit the ring by using the ring. Tap a button to change it, drag one onto another to swap them. With a controller, the stick walks the buttons, A changes one, and Y lifts a button so A can drop it somewhere else. There is no separate list to learn.
    • Custom keyboard shortcuts on the ring. Give a shortcut a name, pick its modifiers, and choose the key on a keyboard you can see. Ctrl+Shift+Esc and Alt+F4 stop needing a real keyboard on the couch.
    • An on-screen controller on Android, iPhone and iPad. Show and hide it from the ring's Virtual controller button. The host sees one controller arrive when it appears and one leave when it goes, on the next free slot beside any real pad you have connected. A stick follows your thumb from wherever it lands, and the D-pad reads eight directions. A trigger reads how far down your finger sits, so a slow press stays a slow press. A finger anywhere else still drives your touch mode, so tap-to-click keeps working beside it. Choose Full, Sticks and shoulders or D-pad and face buttons, and set its opacity and size in settings.
    • The Steam Controller 2 streams from Apple and Android devices. Android reads it over USB, the Puck dongle or Bluetooth; Apple over Bluetooth. The pad reaches your host as itself, so the trackpads, gyro and haptics behave the way they do when it is plugged in locally. It is on by default on Android and off on Apple. Switching it on there asks for Bluetooth permission, which is a question worth asking only from someone who owns the controller.
    • Windows hosts can present a Steam Controller 2. Previously Linux only. The multi-pad Puck dongle stays Linux-only for now.
    • The console tells you a device is asking to pair, wherever you are in it. A pairing request used to appear only on the Pairing page, so it waited until somebody thought to go and look. That is worst on a phone, where the page is several taps away. A notice now names the device and offers one button through to it, and the waiting list refreshes the moment the request arrives rather than up to ten seconds later.
    • Every client draws the same icons. The quick-action ring showed icons in one place and words in another, because three separate apps each had their own vocabulary for the same six buttons. They now share one set, so a button looks the same wherever you meet it.
    • A host card shows which system the machine runs, in place of the first letter of its name. The name is spelled out underneath anyway. A host too old to say what it runs keeps its initial.

    Improved

    • A switched-off TV plugged into your Windows host stops costing you frames. A standby screen on HDMI keeps Windows drawing for a head nobody is watching, and your stream pays for it. The host now switches such a screen off for the duration of the stream. On our test machine that cut the median stall from 6.3 seconds to 0.7 across sixteen alternating runs. It is an improvement rather than a cure — some stalls survive it. Only a screen that belongs to no display arrangement is ever chosen, so your laptop panel and your working monitors are never touched. If a screen must stay awake, for a capture card or a receiver, there is a setting to keep it.
    • Putting your host to sleep now clears its virtual displays first. A wake used to resume onto a display built for whoever sent the machine to sleep.
    • The Windows tray icon survives an update. It used to disappear on every upgrade and stay gone until the next sign-in. Only console-initiated updates were ever covered, so a winget upgrade, a hand-run setup and a plain crash all ended the same way. The host now watches the icon for as long as it runs.
    • The Linux install script asks about what you want, not how it works. Its questions are now full controller support, third-party Moonlight clients, the shared clipboard, and starting at boot — and it picks sensible defaults from your machine. Bazzite and Nobara join the group and keep running after you log out. A host already running Sunshine or Apollo is offered Moonlight compatibility, and an SSH session with no screen keeps running too. It still runs unattended, and re-running it is still safe.
    • The access badge appears only when the stats overlay does. A badge that never goes away reads as clutter. What it tells you, which is what this session may do, is something you check now and then rather than watch. Notices about a change still appear at any time.
    • Touch handling is more consistent. Long-press to drag now works on every client rather than some. Two-finger scrolling respects your invert-scroll setting. Scrolling needs exactly two fingers, so a three-finger gesture is no longer read as a scroll.
    • A host that cannot accept touch now says so. Some Linux desktops and older Windows builds have nowhere to deliver a touch contact, and they were dropping every one in silence. Your client now falls back to the trackpad model for that session and tells you when the stream starts.

    Fixed

    • Windows: F11 ended the session instead of going fullscreen. On graphics drivers that refuse a fullscreen-sized surface, the failure ended the stream, and the app then reported a live session as "Couldn't connect". A refused fullscreen now costs you the fullscreen and nothing else.
    • Apple: the picture froze while sound and input kept running. Reported from an iPad Pro, twice in one session, and only reconnecting cleared it. The part of the pipeline that hands frames to the screen had stopped asking for them, and nothing noticed. It is now watched and restarted within a quarter of a second.
    • Both sticks on a virtual Switch Pro controller sat in the top-right corner under Steam. They reached the centre only at full down-left, while the buttons and motion were fine. Steam reads the controller's calibration in a shape we did not answer, so it read zeros and treated a zeroed centre as real.
    • Steam Deck in Gaming Mode: touch dragged the host cursor into a corner and every touch mode stopped working. Steam owns the touchscreen there and replays it as mouse movement, which the stream then applied as if you had moved a mouse a very long way. One capture showed 341 such movements and not a single finger. Punktfunk now recognises that pattern, ignores it, and tells you once why.
    • Android: touching the black bars beside the picture did nothing. Those taps never reached the gesture handling at all.
    • Linux: the Flatpak app opened fullscreen on every desktop. It checks one setting to tell whether it is running in Steam's Gaming Mode, and our own Flatpak sets that value on every launch. The graphics layer we bundle reads that setting, and nothing else, to decide whether to offer HDR. Inside the sandbox it was always set, so the app believed every machine was a Deck. Reproduced on a plain GNOME desktop with no Deck and no Steam session anywhere.
    • Steam Deck and CachyOS: the in-session display menu offered one refresh rate and no resolutions. The list of rates we build never reached a SteamOS-style session, so games paced themselves to that single number.
    • Apple TV: the wake prompt could not be answered with a controller. Neither Cancel nor Try Again could be pressed, which left a failed wake as a dead end. The prompt shown for an unknown host had the same problem.
    • Android TV: settings offered rumble and gyro "from this phone" on a box that has neither. An Nvidia Shield answers yes when asked whether it can vibrate, most likely on behalf of an attached controller, so those rows appeared and promised something the box cannot do.
    • Windows: the tray icon could vanish for good. An internal lock left in a bad state took the whole tray process down with it, which is exactly the disappearance the new supervision is there to prevent.
    • Our own documentation said AMD and Intel encoding was untested. It has been validated since 0.31, on a Ryzen 7000 integrated GPU and on Intel Arc. The README, the roadmap and the Windows host page were never updated to say so. If you skipped Punktfunk because you have an AMD card, that was our mistake.

    Thanks

    Two people outside the team wrote code that ships in this release, and both are named here because the work is theirs.

    Keith Porcaro built Steam Controller 2 support beyond Linux. It is five separate pieces across four platforms, and the largest single contribution in this release:

    • the shared description of how that controller talks;
    • the Windows driver identity that lets a Windows host present one;
    • the path that carries the pad's raw reports across the stream;
    • Bluetooth capture on Apple devices;
    • the motion-sensor gate on Android.

    If you use that controller from a phone, a tablet, a Mac, or to a Windows PC, this is why.
    luxus rewrote what the Linux install script asks you. It used to ask about our internals. It now asks what you want and works the rest out from your machine. They also tightened the previous release's changelog to our own house style, which is the kind of contribution nobody has to make.

    The rest started, as usual, with people describing exactly what they saw:

    • "The GTK client is just launching in fullscreen." One sentence, and it named a bug that had been shipping to most Linux users in our main channel.
    • The iPad whose picture froze twice in one session while the sound kept playing. The detail that audio survived is what pointed at the screen rather than the network.
    • The Switch Pro sticks pinned in a corner, with the observation that the same pad read correctly outside Steam. That one detail ruled out half the system.
    • The Steam Deck whose touch controls all died at once in Gaming Mode. Three separate features failing together is what showed they shared a cause.

    Thank you.

    One caveat we would rather write down than have you find. Touch on a Steam Deck in Gaming Mode is the one path we have not re-run on the hardware since the fix. It was built from a capture of exactly that failure and it is covered by tests, but a Deck has not played the finished build back to us. If a gesture still behaves oddly there, please tell us — and say what you saw, because that is what made every other fix on this page findable.

    For developers

    Protocol, application binary interface (ABI), driver and embedder detail is in the v0.34.0 CHANGELOG. It carries the version table and the full breaking-change list.

    The short version: the ABI that embedders build against moves 26 to 28, and one of those steps widens a struct. PunktfunkHidOutput grows from 19 to 85 bytes, so this is a recompile rather than a relink — the existing version equality check is what catches a stale build. Everything else versioned stands still: the streaming protocol, the driver protocol, the gamepad channel, the add-on contract and the management API are all where 0.33.0 left them.

    Packagers on Windows: the controller driver package gains an eighth hardware identity for the Steam Controller 2, so it must be rebuilt and reinstalled for that pad to work.

    Downloads
  • v0.33.0
    audit / bun-audit (plugin-kit) (push) Successful in 29s
    audit / bun-audit (web) (push) Successful in 31s
    audit / bun-audit (sdk) (push) Successful in 38s
    audit / docs-site-audit (push) Successful in 32s
    audit / license-gate (push) Successful in 5m5s
    audit / c-abi-asan (push) Successful in 5m43s
    ci / web (push) Successful in 51s
    ci / bun-nix (push) Successful in 26s
    ci / docs-site (push) Successful in 56s
    ci / docs-drift (push) Successful in 29s
    ci / rust-arm64 (push) Successful in 5m48s
    audit / miri (push) Successful in 8m13s
    audit / pnpm-audit (push) Successful in 16s
    audit / cargo-audit (push) Successful in 1m10s
    ci / rust (push) Successful in 16m29s
    nix / flake (push) Successful in 19m50s
    deb / build-publish-gamescope (push) Successful in 1m3s
    android-screenshots / screenshots (push) Successful in 1m52s
    deb / build-publish-client-arm64 (push) Successful in 1m54s
    decky / build-publish (push) Successful in 1m4s
    deb / build-publish (push) Successful in 4m44s
    deb / build-publish-host (push) Successful in 5m17s
    sbom / sbom (push) Successful in 36s
    android / android (push) Successful in 9m35s
    windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 8m4s
    arch / build-publish (push) Successful in 10m5s
    flatpak / build-publish (push) Successful in 7m17s
    linux-client-screenshots / screenshots (push) Successful in 4m43s
    deb / smoke-install (push) Successful in 2m48s
    web-screenshots / screenshots (push) Successful in 6m11s
    windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 10m36s
    rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 17m8s
    rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 19m5s
    windows-host / package (push) Successful in 15m11s
    windows-host / canary-manifest (push) Skipped
    windows-host / winget-source (push) Successful in 52s
    docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 21s
    docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 24s
    docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 21s
    docker / builders (ci/flatpak-ci.Dockerfile, punktfunk-flatpak-ci) (push) Successful in 21s
    docker / builders (ci/gamescope-trixie.Dockerfile, punktfunk-gamescope-trixie) (push) Successful in 22s
    docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 22s
    docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 23s
    docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 11s
    docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 34s
    docker / builders-arm64cross (push) Successful in 13s
    docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m6s
    apple / swift (push) Successful in 2m17s
    docker / deploy-docs (push) Successful in 36s
    apple / distribute (push) Successful in 12m38s
    apple / screenshots (push) Successful in 9m59s
    Stable

    enricobuehler released this 2026-08-28 23:46:59 +00:00 | 2494 commits to main since this release

    This release is for everyone who streams games or a desktop with Punktfunk. It works with 0.32.x, so everything you have already paired keeps working, and you can update one side at a time.

    If you are on 0.32.0, update. That release broke automatic bitrate. The first moment of packet loss dropped a stream from 20 Mbps to around 2 Mbps, and it never climbed back. Two people reported it from opposite setups, which is what made the cause findable. It is fixed here.

    The headline feature is the other half of a round trip we only ever did once. Punktfunk has been able to wake your host from the couch for a while. Now it can put it back: sleep, restart and shut down appear on every client, in the same menu that woke the machine. Finish on the TV and send the host to sleep from the sofa.

    Omarchy is now a first-class host. A one-command install, a setup command that wires the firewall and the app menu for you, and a console that wears your desktop theme instead of ignoring it. Five things we had assumed about that system turned out to be wrong when we ran it on real hardware, and all five are fixed rather than documented.

    TL;DR

    • Automatic bitrate is fixed. On 0.32.0 one bad moment cost you the whole session. Read "Before you update" if you turned automatic off because of it.
    • You can sleep, restart or shut down your host from any client. Read "Before you update" if you have paired a device with Full control.
    • Omarchy is a supported host. One-command install, a setup step, and the console follows your theme.
    • Fixed a black screen on Hyprland desktops. The streamed display was never focused, so nothing was ever drawn on it.
    • Your client no longer picks a random route to your host. One person's stream went over a virtual private network while both machines sat on the same Wi-Fi.
    • Intel Arc graphics: fixed a green picture on every high dynamic range (HDR) session.
    • "Keep host audio playing" now works on Apple and Android, not just the desktop clients.

    What's in this release

    Before you update

    • A device paired with "Full control" can now shut down your host. Host power is a new permission, and it is included in Full control. Any device you already trust with everything gains it when you update. If that is not what you want, open the device's access settings and switch host power off. Every other access level is unaffected.
    • If you turned automatic bitrate off on 0.32.0, you can turn it back on. The collapse you were working around is fixed. If you set a manual rate to escape it, that rate is now a ceiling you no longer need.
    • Omarchy users: run punktfunk-omarchy setup after installing. The package installs the command but never runs it, because opening a firewall and editing your app menu behind your back is not something a package should do. The install guide walks through it.

    New

    • Sleep, restart and shut down your host from the couch. Every client's host menu grows the three rows, right where "Wake host" appears when the machine is asleep. Restart and shut down ask you to confirm. Sleep does not, because it is reversible from the same menu. An action your host cannot run right now stays listed, greyed out, and says why.
    • Omarchy is a supported host. It gets its own install page, a one-command installer, and a setup step. Setup opens the firewall for your local network only, adds Punktfunk to the app menu, and starts the host with your session. It also checks whether anything else is already using the same ports. punktfunk-omarchy remove puts everything back.
    • The web console follows your desktop theme. Switch theme and the console switches with it, within a couple of seconds, including your background and text colours. Warning and delete buttons deliberately keep their own colours: a theme with a red accent must not make "delete" and "save" look the same. Every colour combination is checked for readable contrast against six shipped themes before it ships.
    • Opening the console from your own app menu no longer asks who you are. It recognises you as the person running the host, using a one-time pass that expires in a minute. Anyone arriving without one still meets the login page, so the console stays safe to reach from your phone.
    • A command-line interface for the host. punktfunk-host ctl handles pairing, device lists, access levels, stopping a session, and following host events as they happen. It verifies it is talking to your real host before it sends anything, so a program squatting on the port learns nothing.
    • The installer can move a host between release channels. --channel canary and --channel stable now work on a machine that already has Punktfunk, in both directions. Going back to stable is a downgrade, which package managers refuse unless told, so the installer tells them. Re-running the installer without naming a channel leaves you on the one you are on.

    Improved

    • The one-command install is on every page it works for. It used to be mentioned only on the install hub, so anyone landing on the Ubuntu page from a search never learned it existed.
    • The troubleshooting page names two failures that used to report nothing. Hyprland can silently refuse a program permission to capture the screen or send input, which looks like a black screen with dead controls and no error anywhere. And on Omarchy the console's update button is deliberately absent, so the page now says where updates come from instead.
    • The tray's restart row says "Restart Punktfunk", so it is not confused with restarting the machine.

    Fixed

    • Automatic bitrate collapsed and stayed collapsed. On 0.32.0, and only on 0.32.0, every automatic session dropped from around 20 Mbps to around 2 Mbps at the first sign of packet loss, and could never climb back. It was reported twice from opposite setups: a Windows client over a virtual private network, and an Android client on Wi-Fi. The cause was 0.32.0's own bitrate rework, where a rounding step of one or two kilobits made every successful rate change look like the host refusing to go faster. Your client learned that as a hard limit, then lowered it again on the next dip.
    • A stream could start with five to eleven seconds of black video. Your client measures your connection's capacity by sending a short burst at startup. It fired on a fixed two-second timer, but a Windows host can take six to eight seconds to get its display ready. So the burst landed exactly on the first video frame and buried it, then missed its own deadline and threw the measurement away. The burst now waits until a frame has actually arrived.
    • Hyprland desktops: a black screen on every session. The display Punktfunk creates for your stream was never given focus, and a display nothing is looking at draws nothing at all. No drawing means no frames, so capture gave up waiting and the client showed black. Getting focus onto it needed a spelling that only works on newer Hyprland setups, and we had the wrong one.
    • Hyprland desktops: only the first session worked. Punktfunk borrows your screen-share picker while it streams and hands it back afterwards. Handing it back after every session restarted a system service underneath the next one, and a stream started across that restart never receives a single frame. The picker is now handed back when the host exits. In between, it passes anything that is not us straight through, so an ordinary browser screen share behaves exactly as before.
    • Switching desktop theme reset your stream's resolution. Changing an Omarchy theme reloads the compositor's configuration, and a reload discards the display settings Punktfunk had applied — so the stream silently dropped to a default resolution mid-session. Resizing the client window appeared to fix it, which is why this looked like a client bug. Punktfunk now watches for the reload and re-applies its settings. Any reload is covered, including one you run yourself.
    • Hyprland desktops: your monitors could stay dark after a failed session. When Punktfunk streams your desk exclusively it turns your physical monitors off, and puts them back at the end. If starting the session failed and it retried, the retry overwrote the note saying which monitors to restore. So nothing was restored, and recovery meant reloading the compositor by hand.
    • Your client picked a route to your host at random. One person's stream ran over a virtual private network while both machines sat on the same Wi-Fi, and neither end chose that. Your operating system answers name lookups on every network it can see, so the list your client gets is polluted by every virtual network reaching it. The client then took whichever entry came first, re-rolling every time your host announced itself. Desktop and Android now both prefer the network they share with your host, then the address your host says to use.
    • Intel Arc graphics: a green picture on every HDR session. Reported on an Arc A370M, where 8-bit sessions at the same resolution and frame rate looked perfect. Your client was promising it could display HDR without ever checking whether the graphics driver could actually convert it. It now asks the driver first, and only a definite "no" turns HDR off.
    • "Keep host audio playing" was missing on Apple and Android. The setting shipped in 0.32.0, but only three clients ever offered it. So a phone or an Apple TV was the one place someone would look for "why did my host go quiet" and find nothing. It is now on every client, in the same place, worded the same way. A per-host profile can keep the study machine's headphones live while the living-room profile mutes them.
    • A fresh install reported that the web console had failed to start. It then started two seconds later and worked fine, but the first attempt printed a hard failure on a perfectly good install — and anything watching the result believed it. The console was starting before the host had written the files it needs. It now waits for them.
    • Uninstalling left things behind. Removing Punktfunk took the packages but left firewall rules, an app-menu entry, a startup file, and a screen-share setting still pointing at something no longer installed. Uninstall now undoes its own setup first.
    • Omarchy: the install command could not work. The command we published combined two options that Omarchy deliberately blocks, so it installed nothing at all. Two other things were wrong on that system. The setting that keeps your machine awake during a stream was never restored afterward. And the status command reported firewall rules missing seconds after adding them.
    • Punktfunk's entry in your app menu drew no icon, because the host package never shipped one.
    • Updating our website under an open tab no longer blanks the page. A tab left open across a deployment asked for files the new version had renamed, and the page went blank on the next click. It now reloads onto the page you were going to. This affected the web console and the documentation site.

    Thanks

    Most of this release started as somebody describing what they actually saw:

    • The stream that fell to 2 Mbps and stayed there, reported twice from setups with nothing in common. That pair is what ruled out the network.
    • The green picture on an Arc card, with the detail that 8-bit sessions at the same resolution were clean. That is what pointed at the conversion rather than the decoder.
    • The stream running over a virtual private network while both machines were on the same Wi-Fi. Nobody would have gone looking for that one.
    • A real Omarchy machine, run through the whole plan step by step. Five of our assumptions were wrong, and every one of them was a bug somebody would have hit in their first ten minutes.

    Thank you.

    One caveat we would rather write down than have you find. The Hyprland fixes are verified on a real Omarchy machine, with one exception. Re-applying your resolution after a theme switch is unit-tested, and we confirmed the trigger fires on that machine. Testing the re-application itself would have meant interrupting a live stream on the only box we had. If a theme switch still costs you your resolution, please tell us.

    For developers

    Protocol, application binary interface (ABI), driver and embedder detail is in the v0.33.0 CHANGELOG. It carries the version table and the full breaking-change list.

    The short version: nothing versioned moves. The streaming protocol, the ABI, the driver protocol, the gamepad channel, the add-on contract and the event schema are all where 0.32.0 left them. The management API grows two routes for host actions.

    Two changes will still break a build. The "everything" permission mask widens to include host power, so code comparing a stored mask against it for equality now reads an older record as custom. There is a compatibility constant for the old value, and the host applies the compatibility rule itself. Separately, a capability constant that 0.32.0 exported without its prefix is renamed to carry one. Its value is unchanged.

    Downloads
  • v0.32.0
    audit / docs-site-audit (push) Successful in 24s
    audit / bun-audit (plugin-kit) (push) Successful in 30s
    audit / bun-audit (sdk) (push) Successful in 26s
    audit / pnpm-audit (push) Successful in 22s
    audit / bun-audit (web) (push) Successful in 38s
    audit / cargo-audit (push) Successful in 48s
    ci / rust-arm64 (push) Successful in 3m15s
    audit / license-gate (push) Successful in 6m1s
    audit / c-abi-asan (push) Successful in 6m5s
    ci / web (push) Successful in 2m2s
    ci / bun-nix (push) Successful in 25s
    ci / docs-drift (push) Successful in 35s
    ci / docs-site (push) Successful in 1m5s
    audit / miri (push) Successful in 8m16s
    ci / rust (push) Successful in 9m50s
    nix / flake (push) Successful in 21m12s
    deb / build-publish-gamescope (push) Successful in 38s
    android-screenshots / screenshots (push) Successful in 1m39s
    decky / build-publish (push) Successful in 56s
    deb / build-publish-client-arm64 (push) Successful in 1m47s
    docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 17s
    apple / swift (push) Successful in 2m10s
    docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 16s
    docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 19s
    docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 15s
    docker / builders (ci/flatpak-ci.Dockerfile, punktfunk-flatpak-ci) (push) Successful in 15s
    docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 17s
    docker / builders (ci/gamescope-trixie.Dockerfile, punktfunk-gamescope-trixie) (push) Successful in 19s
    docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 14s
    docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 28s
    docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 1m1s
    deb / build-publish (push) Successful in 3m54s
    deb / build-publish-host (push) Successful in 4m52s
    windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 4m45s
    sbom / sbom (push) Successful in 40s
    docker / builders-arm64cross (push) Successful in 15s
    docker / deploy-docs (push) Successful in 34s
    linux-client-screenshots / screenshots (push) Successful in 5m24s
    deb / smoke-install (push) Successful in 2m58s
    flatpak / build-publish (push) Successful in 7m39s
    arch / build-publish (push) Successful in 11m18s
    android / android (push) Successful in 12m4s
    windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 8m29s
    web-screenshots / screenshots (push) Successful in 6m15s
    apple / distribute (push) Successful in 13m17s
    rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 18m57s
    rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 18m56s
    apple / screenshots (push) Successful in 9m48s
    windows-host / package (push) Successful in 12m49s
    windows-host / canary-manifest (push) Skipped
    windows-host / winget-source (push) Successful in 1m3s
    Stable

    enricobuehler released this 2026-08-27 21:04:48 +00:00 | 2541 commits to main since this release

    This release is for everyone who streams games or a desktop with Punktfunk. It works with 0.31.x, so everything you have already paired keeps working. You can update one side at a time.

    The main change is that the bitrate number now tells the truth. When you set a rate, that number used to cover the picture only, while error correction, packet overhead and audio rode on top of it. So asking for 20 Mbps could put 30 Mbps on your network. You would never notice on a fast wired connection, but on a weak one it was the problem you were tuning around. The number you set now covers everything that leaves the machine.

    The part of your client that picks the rate for you has also been rebuilt. It used to mistake a still picture for a bad connection. A paused game convinced it the link was failing, so the next moment of motion arrived at the worst quality available. Climbing back could take a minute and a half. It now tells stillness apart from congestion, and recovers in seconds.

    It is also a security release, though the count sounds worse than it is. A review of the whole system produced 58 findings, and most are small: hardening, build infrastructure, and places where a comment promised more than the code delivered. The one worth your attention needed somebody already signed in to your web console. From there they could reach the pairing controls without being asked for the console password, and pairing a device lets it launch programs. If anyone else can sign in to your console, take this update.

    TL;DR

    • The bitrate you set is now the bitrate on the wire. It used to cover the picture only. If you tuned your rate by trial and error, read "Before you update".
    • Automatic bitrate no longer misreads a still picture as a bad connection. Motion starts sharp, and recovery takes seconds instead of 100.
    • A security review fixed 58 findings, most of them small. The one that mattered needed somebody already signed in to your web console. From there they could pair a device without the console password, and pairing is what lets a device launch programs.
    • Android TV: fixed a permanent black screen with working sound. Some devices could never start their decoder, so no picture ever arrived.
    • Two people streaming at once now both get a controller. The second person used to get no controller on Windows, or a merged one on Linux.
    • Fixed garbage rectangles that never went away. Black bars moved "like an equalizer" on every decoder, and nothing ever recovered.
    • Moonlight-compatible streaming got real work. Encryption is on by default, Wake-on-LAN works, and resuming a session now resumes it.

    What's in this release

    Before you update

    • Your bitrate setting means something slightly different now. Nothing breaks, and you need do nothing. But the same number now puts less on your network than it did. If you tuned by trying numbers until streams behaved, you can ask for more than before. If you tuned down because streams were unstable, leave it where it is — the overshoot you were compensating for is gone.
    • Moonlight users: your video and control channel are now encrypted by default. Clients that support it turn it on themselves. We watched one do exactly that on a local network, unprompted. That is why it became the default. A switch exists to go back; the developer changelog names it.
    • If you script the web console's pairing steps, they now need the console password. Arming a pairing, approving it and submitting the PIN no longer accept a signed-in browser session alone. That is the security fix described below, so the change is deliberate. Add the password to your script.

    New

    • 10-bit colour without high dynamic range (HDR). Asking for 10-bit used to mean asking for HDR, because the two were welded together, and they are separate again. A new standard dynamic range (SDR) setting, called "10-bit SDR", asks for the extra precision on its own and stays off by default. Neither screen switches into HDR, no colour is remapped, and compression stops adding banding to gradients such as skies and fades. It needs a Windows host, an NVIDIA graphics card and High Efficiency Video Coding (HEVC), so every other setup stays 8-bit and says so.
    • Keep your host's speakers playing. A new per-session setting asks the host to leave its audio devices alone. The host listens to whatever is already playing instead of re-routing sound to a silent output. Headphones plugged into the host stay live, and you still hear everything on the client. An older host simply ignores the request, and the setting appears in the desktop and gamepad interfaces.
    • Setup commands now know your stream's mode. A command you run before or after a game receives the width, height, refresh rate and whether the session is HDR. That means one setup step instead of one entry per device you stream to. It works on Windows hosts too, where those commands previously received only the app's identifier.
    • "Send logs to host" reached every interface. The button packages what your client saw and sends it to the host, so a report carries evidence instead of a description. It now works in the Linux, Windows and Android touch interfaces. A gamepad interface that cannot start also says why instead of failing silently.
    • Heroic's fullscreen interface can be a tile. On Linux, a library tile can open Heroic's gamepad-friendly console mode directly.

    Improved

    • Automatic bitrate was rebuilt. Every part came from a report where a stream behaved badly on a connection that measured fine.
      • Stillness is no longer mistaken for congestion. Your host now marks the moments when the picture is not changing. Your client treats those stretches as carrying no information, so they neither raise nor lower your quality. Previously a static menu looked exactly like a connection delivering nothing.
      • Recovery is fast and bounded. Climbing back after a dip used to crawl, taking about 100 seconds from the bottom. It now takes seconds, and never overshoots what your connection recently delivered.
      • A slow source can climb. A menu running at 35 frames per second on a 90 Hz setup was judged against 90. It looked like it was wasting its allowance, so it could never earn better quality. Your client now measures against what the source actually produces.
      • The floor is lower. The lowest rate the control settles at drops from 5 Mbps to 2 Mbps. A genuinely poor connection now gets a stream that holds together.
    • Your traffic gets priority on your own network. Streaming data is now tagged so Wi-Fi access points give it priority over other traffic on the same air. Tagging happens only toward addresses on your local network. It stays off toward the internet, because some providers and routers mishandle tagged traffic there.
    • Frames go out spread over time instead of in a burst. The allowance for sending a frame in one blast was a fixed size chosen for gigabit Ethernet. On Wi-Fi that meant frames went out back to back. It is now measured in time at your actual rate.
    • Button hints match the device in your hand. A TV remote used to be told to press Enter, Esc and Tab, which it does not have. A Nintendo pad showed Xbox letters, so "A — Select" sat over the button engraved B. Hints now follow whatever last drove the interface. A PlayStation pad gets shapes, a Nintendo pad gets its own letters, and a TV remote gets an OK badge with the missing buttons hidden.
    • A TV remote can reach the settings tabs. The tab strip answered only to shoulder buttons. Press Up from the top row to get there.
    • The mouse pointer is the right size on a high-DPI client. On a 200% display our pointer was drawn at half the size of every native one.
    • The web console is named in every install line, and a host without it gets it installed.

    Fixed

    • Android TV: a permanent black screen with working sound. Reported on a Xiaomi Mi TV Stick, where the decoder accepted the video format and then failed to start, so no picture was ever decoded. Audio, input and your library all kept working, which made it look like a host problem. Your client now tries a ladder of simpler decoder setups instead of giving up after one attempt. A device that already works pays nothing, and the setup that succeeded is logged so the next device names its own cause.
    • Two people streaming from one host both get a controller now. Every OS-level name for a virtual controller came from the controller's number, and every client numbers its first controller zero. So two people each holding a controller collided. On Windows the second person got no controller for the whole session, and the error told the operator to restart the service, which would have killed both sessions. On Linux nothing errored at all and the two controllers merged into one.
    • Garbage rectangles that appeared and never left. Reported as black bars moving "like an equalizer", identical on every decoder. A frame arriving in pieces could claim a position inside the valid range that did not actually fit, leaving a gap and overlapping its neighbour. The frame was still marked complete, so the picture was assembled from the wrong bytes, and nothing recorded a loss or asked for a fresh frame. Android was never affected.
    • A brief pause no longer wrecks quality for the rest of the session. When your client gave up waiting for frames that then arrived, it counted them as lost packets. One recording showed exactly 5% packet loss on a connection that lost nothing, and the rate was cut by 30% three times in four seconds. Neither thing that number controls could have helped, because error correction repairs loss and not delay. Real packet loss still counts as before.
    • A stall report no longer blames your laptop screen. On a laptop streaming a still desktop, the host reported dozens of stalls and pointed at the internal panel. Nothing was being drawn, because on a still desktop only the mouse pointer changes, and it moves only when your input arrives. The host was correctly displaying nothing. It now checks whether anything actually changed before blaming anything.
    • A truncated video stream no longer crashes the decoder. An access unit that claimed more data than it carried could stop the decoding thread outright. It is now treated as a parse error. This affected every AV1 path.
    • "Capture system shortcuts" now works in Desktop mouse mode. The setting was wired up and then discarded by a single condition. That made it useless for exactly the remote-desktop case where it matters most.
    • Windows: the couch interface's tiles no longer pop up a console window.
    • Linux: KDE's stored display setup no longer darkens your desk permanently. The host's changes were saved on top of your own configuration, and the restore never saw the original. Your setup is now captured before anything changes, and re-applied after the stream ends.
    • AMD: AV1 streams could arrive out of order. B-frames are now pinned off, and the stream is checked rather than assumed to be in order. AMD encoders also report the bitrate they actually applied instead of the one they were asked for. NVIDIA sub-frame delivery is now verified in release builds.
    • Moonlight-compatible streaming, a batch of fixes:
      • Wake-on-LAN never worked. The host advertised a fake hardware address, so every attempt was a silent no-op. It now advertises its real one.
      • Resuming a session did not resume it. The control channel was left undecipherable because keys were not refreshed, and video did not restart cleanly.
      • HDR games sent no colour information. The host switched the display into HDR mode and then sent nothing describing the picture. It now sends the real grade every frame.
      • Stereo audio had no loss protection. Error correction covered surround layouts only, leaving the most common setup with none.
      • The host now adapts when your client reports lost packets, adjusting error correction and rate as conditions change. Moonlight's latency overlay also shows real host numbers instead of zero.
      • The host no longer claims 4K HEVC capacity it may not have. A host with no graphics card encodes H.264 only, but still advertised an HEVC ceiling.

    Security

    A review on 2026-08-25 produced 58 findings across the host, the console, the apps and our build infrastructure. Most are small — tightening you would never notice, and places where a boundary was described correctly in its own documentation while the code had quietly drifted from that promise. A handful mattered. One mattered more than the rest, and it is worth being precise about what it was and was not.

    That one was the web console's pairing controls. Reaching them meant being signed in to the console already, so this was not something a stranger on your network could do. But once signed in, those controls ran through a general-purpose route carrying the operator's own credentials. So alone among the trust-root actions, they never asked for the console password. Since pairing a device is what lets that device launch programs, the gap turned "signed in to the console" into "can start something on the host".

    What changed: arming a pairing, approving it and submitting the PIN now all sit behind that password. The PIN itself is handed over once in the protected response, rather than being readable by anything polling for status.

    Other fixes in this release:

    • Add-ons can no longer read the unredacted log, which carried webhook credentials that were withheld from them elsewhere.
    • A revoked guest now loses clipboard access immediately, in both directions.
    • Peers on your network can no longer occupy every connection slot without a stream to join.
    • Secrets on Windows are created with their permissions already applied, rather than being briefly readable by anyone.
    • Five ways to crash the host with a malformed video packet are closed.
    • The identity key on Apple devices no longer rides along in encrypted backups.
    • Deep links auto-connect only by a stable identifier. A link naming a display name or an address asks you first.
    • Moonlight-compatible media ports now verify who is connecting. Both media planes used to accept the first packet from the right address without looking inside it. The value they were meant to check was the same fixed constant on every host, and nothing compared it. It is now a per-session secret, and the request that hands it out requires authorisation.
    • The Moonlight-compatible control channel no longer reuses one number space between the two directions.

    Thanks

    Nearly everything above started as somebody describing exactly what they saw:

    • The bars moving like an equalizer, with the detail that they looked identical on every device. That is what ruled out the decoder.
    • The stream that dropped to 7 Mbps in four seconds, reported with measurements showing the connection had lost nothing. That was the hard half.
    • The TV stick with sound but no picture, reported with a log covering nine sessions.
    • Five separate requests from one returning user, each of which turned out to be a real defect rather than a missing feature.
    • The remote that was being told to press Esc.

    Thank you.

    One caveat we would rather write down than have you find. The 10-bit SDR path is verified on Windows with NVIDIA hardware over HEVC. Other combinations deliberately stay 8-bit and say so, rather than guessing.

    For developers

    Protocol, application binary interface (ABI), driver and embedder detail is in the v0.32.0 CHANGELOG. It carries the version table and the full breaking-change list.

    The short version: the ABI that embedders build against moves 25 to 26, and nothing else versioned moves. The new interface takes every connect option in one size-prefixed struct, which closes an eleven-generation ladder of numbered entry points. Every older entry point keeps its symbol and its behaviour, so existing embedders keep working. The streaming protocol, driver protocol, gamepad channel, add-on contract and management API are all where 0.31.4 left them.

    Read the breaking-change list anyway, because most of it is behavioural rather than numbered. The bitrate on the control plane is now the total wire budget rather than the encoder rate, deliberately without a capability handshake. If you read the live bitrate as an encoder rate, it is not one any more. The rate floor drops, and traffic marking now defaults on toward local peers. Moonlight-compatible video and control encryption default on, PyroWave sessions force automatic rate, and the pairing routes move behind the console password.

    Downloads
  • v0.31.4
    audit / bun-audit (web) (push) Successful in 24s
    audit / bun-audit (sdk) (push) Successful in 25s
    audit / bun-audit (plugin-kit) (push) Successful in 26s
    audit / docs-site-audit (push) Successful in 24s
    audit / pnpm-audit (push) Successful in 12s
    audit / cargo-audit (push) Successful in 43s
    ci / rust-arm64 (push) Successful in 1m40s
    ci / web (push) Successful in 1m25s
    ci / docs-site (push) Successful in 1m11s
    ci / bun-nix (push) Successful in 33s
    ci / docs-drift (push) Successful in 39s
    audit / license-gate (push) Successful in 6m4s
    audit / c-abi-asan (push) Successful in 7m33s
    audit / miri (push) Successful in 7m48s
    android-screenshots / screenshots (push) Successful in 1m17s
    ci / rust (push) Successful in 16m49s
    windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 8m34s
    android / android (push) Successful in 10m54s
    decky / build-publish (push) Successful in 58s
    arch / build-publish (push) Successful in 12m5s
    sbom / sbom (push) Successful in 42s
    linux-client-screenshots / screenshots (push) Successful in 6m18s
    flatpak / build-publish (push) Successful in 7m39s
    docker / builders-arm64cross (push) Successful in 14s
    docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 18s
    docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 12s
    docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 15s
    docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 14s
    docker / builders (ci/flatpak-ci.Dockerfile, punktfunk-flatpak-ci) (push) Successful in 15s
    docker / builders (ci/gamescope-trixie.Dockerfile, punktfunk-gamescope-trixie) (push) Successful in 15s
    docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 18s
    docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 17s
    docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 30s
    docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m30s
    docker / deploy-docs (push) Successful in 29s
    nix / flake (push) Successful in 25m39s
    deb / smoke-install (push) Successful in 3m41s
    deb / build-publish (push) Successful in 6m45s
    deb / build-publish-host (push) Successful in 5m29s
    deb / build-publish-gamescope (push) Successful in 37s
    deb / build-publish-client-arm64 (push) Successful in 1m28s
    apple / distribute (push) Successful in 13m7s
    apple / swift (push) Successful in 2m0s
    rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 18m52s
    rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 19m52s
    apple / screenshots (push) Successful in 9m32s
    windows-host / package (push) Successful in 12m0s
    windows-host / winget-source (push) Skipped
    windows-host / canary-manifest (push) Successful in 26s
    web-screenshots / screenshots (push) Successful in 6m16s
    windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 4m12s
    Stable

    enricobuehler released this 2026-08-24 22:27:35 +00:00 | 2636 commits to main since this release

    Wire-compatible with 0.31.x — everything you have already paired keeps working, and you can update one side at a time. Nothing here changes how a host and a client agree on what to send each other, so an old client on a new host, or the other way round, streams exactly as it does today.

    This is a fix release about the machine you stream from behaving itself while you are not in the room with it. Asking for your screens off during a stream only ever worked on a box running a KDE desktop — a Steam Deck, or anything else sitting in Game Mode, kept its television lit for the whole session, playing your game to an empty room. That works now on every kind of Linux box, including ones with no desktop at all. Putting that box to sleep or shutting it down from Steam's own power menu had stopped working during a stream, in two separate ways, and works again. On the client side, a long session on a connection that was never the problem could slide from 57 Mbps down to 5 and stay there; the Mac app could quit outright the moment a stream started; and the web console served a certificate browsers refuse, so the page you are told to open did not load, while on Linux the tray insisted the console was dead the whole time it was running perfectly. There is a little new work too: the gamepad console's bitrate reaches 2 Gbps and takes a number you type, and on Linux there is finally a way into that console that is not a command line.

    TL;DR

    • "Turn my screens off while I stream" now actually turns them off. It only ever worked on a KDE desktop. A Steam Deck or any other box in Game Mode ignored it silently, which is the deployment where you most want it. It works there, and on sway and Hyprland desktops too. GNOME is the one that still cannot be served, and the host now says so instead of leaving you guessing.
    • Steam's power menu did nothing during a stream. Sleep, Restart and Shut Down all work again. Two unrelated faults with one symptom: your host was refusing every suspend request for the length of a stream, including yours, and on some setups the box lost the permission to power itself off at all while it was streaming.
    • A long session could slide to the worst picture quality on a perfectly good connection. One 1440p session walked from 57 Mbps down to 5 over ten minutes without dropping a single packet, and never recovered. Both causes are fixed.
    • Mac: the app could quit the instant a stream started. Not at launch — at the moment you connected, which made it look like the host's fault.
    • The web console would not open in a browser, and on Linux the tray labelled it "not responding" while it was serving fine.
    • New: the gamepad console's bitrate goes to 2 Gbps, steps finely at the low end, and takes a typed number; on Linux the gamepad console gets a button, a menu entry and its own app-grid launcher.

    Before you update

    • Only if your host takes the box over by stopping its login screen, and you want Steam's power menu to work: be in the punktfunk group. That is the same group the takeover already needs to do its job, so if the takeover works for you today you are already in it and there is nothing to do. If you set that up some other way, join it — the docs page titled Steam / gamescope carries the one-line command — because the permission this release adds is granted to that group and nobody else, deliberately.

    New

    • Bitrate in the gamepad console reaches 2 Gbps, and you can type a rate. The picker had seven rungs stopping at 80 Mbps since the console shipped, which someone ran straight into — and the desktop app beside it has always gone far higher, so the two disagreed about what your own machine was allowed to ask for. There are 30 rungs now, from 1 Mbps to 2 Gbps: tight at the bottom, where a single step decides whether a thin connection is watchable, and coarse at the top, where a step is noise. Press Y on that row to type a rate instead, using the same on-screen keyboard as the add-host and pairing fields, including Steam's own keyboard on a Deck. And a rate that is not one of the rungs — typed here, or set from the desktop app — now steps to its neighbour instead of being thrown away and snapped back to Automatic by a single nudge. The desktop app gets the other half of the same complaint: its bitrate box steps 1 Mbps at a time instead of 5, so 3, 4 and 6 are reachable without typing.
    • Linux: a front door to the gamepad console. The couch interface has shipped for a while, but on Linux the only way to reach it was a command-line switch, which is not something you find by looking. There are three ways in now: a gamepad button in the app's host list, a "Console UI" entry in its menu, and a separate launcher in your applications grid that you can also add to Steam as a non-Steam game so it opens straight from the couch. All three land in the same place. This comes with the packaged builds; a from-source Nix build still does not include the separate launcher, because that build leaves the console interface out.

    Improved

    • The adaptive bitrate control no longer gives up on a whole session. Part of the picture-quality fix below: when your client decided the host's encoder was the bottleneck and stopped listening to that signal, it stopped listening for the rest of the session. But the thing that provokes it is temporary by nature — a game hammering the graphics card, a shader storm, a second program on the same card — and all of those end. It now starts listening again after a clean stretch, and if the noise comes straight back it backs off for longer each time rather than flapping.
    • When your host cannot turn a screen off, it says so. Every one of those refusals means "you asked for your screens off and they stayed on", and the most common one was being recorded at a level nobody reads. It is now a warning, with the reason.

    Fixed

    • Your screens stayed lit through the whole stream, on every Linux box except a KDE desktop. Reported on Nobara: launching a game from the library with screens-off selected left the operator's monitor showing live Game Mode for the entire session. Three separate things were wrong. The setting was implemented by asking the desktop to turn its screens off — right when there is a desktop to ask, and a box in Game Mode has none, which is precisely the box whose television you want dark. That case is now handled by switching the display off through the graphics hardware directly, which needs no extra privileges and cannot leave a screen dark if the host crashes, because the screen comes back the moment the host lets go. A sway or Hyprland desktop was not served either, and now is, through each one's own controls, taking care to leave any screen it did not darken alone rather than "fixing" one that was already off. And separately, the part of the host that moves the box's own gaming session out of the way only did so for a Steam launch, because freeing Steam was the only reason anyone had ever needed it — so a non-Steam game from your library left that session running and driving the television regardless. Wanting your screens off is now a second, independent reason to move it aside. GNOME remains a genuine gap, not an oversight: it offers applications no way to turn a screen off, and holds the graphics card itself so the direct route is refused. The host warns instead of pretending.
    • The recommended way of streaming a Game Mode box ignored the setting entirely. The route that gives the best experience — and the only one that can serve your client its own screen at its own resolution — was the one route that never darkened anything, because there was nowhere safe to undo it and a screen left dark after every stream is worse than one left lit. The undo now lives in the single teardown every one of those sessions passes through, so it is honoured. A reconnect does not darken twice, and a session that keeps running between connections stays dark rather than flickering.
    • Steam's power menu did nothing during a stream, and neither did Sleep. Two independent faults, one symptom, both on Linux. Your host holds a lock for the length of a stream so the box cannot suspend out from under someone who is only watching and never touching anything — but that lock refuses every suspend, including the one you asked for by pressing Sleep, and nothing in Steam's interface shows the refusal, so the entry simply did nothing for as long as anyone was connected. The lock is now held only while the stream is genuinely quiet: any input from any client drops it immediately, so a Sleep press cannot lose the race, and it comes back after 30 seconds of silence. The case it was written for is unchanged — a passive viewer sends nothing, and the box still will not sleep under them. The second fault is Shut Down and Restart, on the takeover setups that stop the box's login screen: doing that leaves the box with no signed-in session, and the system's rules only allow powering off from one. All three entries quietly became a password prompt — asked of something that cannot answer, on a screen that is switched off. The packages now ship a rule granting exactly those three actions, to the punktfunk group and to nobody else, and only those three: a box with a second person logged in still asks first.
    • A long session slid to the lowest picture quality on a connection that never lost a packet. Reported from a 1440p60 session that ratcheted 57 Mbps down to 5 over ten minutes, with the host granting every rate it was asked for and nothing at all going wrong on the link. Two causes, both in the part of your client that watches how long the host is taking to compress each frame. Its thresholds were tuned on a 120-frames-a-second session, where one frame is 8 milliseconds; on a 60-frame session a frame is twice that, so an ordinary one-frame hiccup cleared the "something is badly wrong" bar that the identical hiccup at 120 never reached. They are now measured against the session's own frame budget. And the signal was firing for something cutting the rate cannot fix: it exists to find the point where the encoder runs out of compute, where less rate means less work — but when a game is saturating the graphics card that premise is false, the reduction changes nothing, and it would fire again a moment later. Two reductions in a row that buy no improvement now stand the signal down. Everything else your client watches — packet loss, delay, decoding, and the host's own refusal to climb — keeps its full authority throughout, so a real encoder limit is still caught.
    • Mac: the app could quit outright the moment a stream started. Not at launch, which is what made it look like a host problem. Setting up your microphone takes a snapshot of the input device's audio format and then hands that snapshot back a moment later, and on a Mac the input can change underneath in that window — you switch devices, something changes the sample rate, or the app itself switches to the device you chose two lines earlier. Any mismatch was fatal and could not be caught. It now asks the system to use whatever format the device actually has, so there is no snapshot to go stale, and follows the device if it changes rate mid-stream instead of resampling by the wrong ratio and pitch-shifting your voice.
    • The web console would not load in a browser, and the tray called it dead. A Linux operator saw "Open web console (not responding)" in the tray, beside a tooltip that said the host was idle — which was the clue, because that tooltip proved the host was answering perfectly on the very same check. Your host has kept two identities for a while now: a modern one that everything current uses, and an older one kept unchanged so Moonlight-compatible clients keep working. The web console never followed that split, and none of the things that start it could choose — so it served the old identity, which no browser will accept, and the page you were told to open failed to load. Meanwhile the tray was checking on the console using the modern identity, so its check was refused and a completely healthy console was labelled as not responding. The console now serves the modern identity whenever the host has one, and the tray's check no longer insists on any particular one, because it reads nothing, sends nothing, and decides only what a menu entry says. A host that predates the split, or one where you supplied your own certificate, is unaffected and behaves exactly as before.
    • Hyprland: the request to turn a screen off is a toggle, and would have turned a dark screen back on. Found on a live Hyprland box rather than in review, and worth saying because the first version of this fix was wrong in both directions: the command ignores whether you asked for on or off and simply flips whatever the screen is currently doing. So "turn it off now, turn it back on later" would have lit a screen that was already dark at the start of a stream, and darkened a lit one at the end — the operator's screen left off after streaming, which is the exact failure this whole feature exists to avoid. Your host now reads the screen's real state first, acts only if it differs, and checks afterwards that it worked. A screen already in the state you wanted is left completely alone.

    Thanks

    Every fix above started as somebody saying exactly what they saw. The monitor still showing Game Mode through a whole stream, and which kind of game they had launched. The power menu that did nothing, on which box. The 1440p session whose quality walked downhill for ten minutes while every other number stayed flat — that report came with the measurements that separated the two causes, which is the hard half. The bitrate ceiling somebody hit and pointed out was lower than the app right next to it. The Mac that quit on connect. And the tray that said "not responding" beside a tooltip reading "idle" — noticing that those two things contradicted each other is what found the bug. Thank you.

    One caveat we would rather write down than let you discover: the sway arm of the screens-off work has not been run against a real sway session — there is no sway machine in the lab. Hyprland, KDE, and the no-desktop route were all measured on real hardware. If you stream from sway, we would like to hear how it goes.

    For developers

    Protocol, ABI, driver and embedder detail — including the version table — is in CHANGELOG.md.

    The short version: nothing versioned moves, at all. The streaming protocol, the embedding interface, the driver protocol, the gamepad channel, the add-on contract and the management API are exactly where 0.31.3 left them — the embedding header is byte-identical for the third release running, and the API description changes only its stamped version number. No header, package, plugin or integration needs rebuilding, re-pairing or re-publishing in any direction, and the add-on toolkit and TypeScript package are both untouched. Two behaviour changes are worth knowing about if you integrate: the host's sleep veto is now conditional on stream quiet rather than held for the whole session, and the client's encode-attributed backoff both re-arms after standing down and sizes its thresholds from the negotiated refresh rather than in absolute milliseconds.

    Downloads
  • v0.31.3
    audit / bun-audit (web) (push) Successful in 22s
    audit / docs-site-audit (push) Successful in 22s
    audit / bun-audit (sdk) (push) Successful in 25s
    audit / bun-audit (plugin-kit) (push) Successful in 24s
    audit / pnpm-audit (push) Successful in 15s
    audit / cargo-audit (push) Successful in 42s
    ci / rust-arm64 (push) Successful in 3m53s
    audit / license-gate (push) Successful in 5m41s
    audit / miri (push) Successful in 6m13s
    ci / docs-site (push) Successful in 1m7s
    ci / bun-nix (push) Successful in 24s
    ci / web (push) Successful in 2m7s
    ci / docs-drift (push) Successful in 28s
    audit / c-abi-asan (push) Successful in 8m9s
    android-screenshots / screenshots (push) Successful in 2m26s
    ci / rust (push) Successful in 9m55s
    sdk-publish / publish (push) Successful in 49s
    linux-client-screenshots / screenshots (push) Successful in 4m29s
    arch / build-publish (push) Successful in 9m52s
    sbom / sbom (push) Successful in 39s
    web-screenshots / screenshots (push) Successful in 6m50s
    decky / build-publish (push) Successful in 1m4s
    docker / builders-arm64cross (push) Successful in 13s
    docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 46s
    docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 9s
    docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 10s
    docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 15s
    docker / builders (ci/flatpak-ci.Dockerfile, punktfunk-flatpak-ci) (push) Successful in 12s
    docker / builders (ci/gamescope-trixie.Dockerfile, punktfunk-gamescope-trixie) (push) Successful in 8s
    docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 9s
    docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 8s
    docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 53s
    docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 29s
    docker / deploy-docs (push) Successful in 21s
    flatpak / build-publish (push) Successful in 4m46s
    deb / smoke-install (push) Successful in 2m36s
    deb / build-publish (push) Successful in 3m53s
    deb / build-publish-host (push) Successful in 7m27s
    deb / build-publish-gamescope (push) Successful in 49s
    deb / build-publish-client-arm64 (push) Successful in 2m34s
    android / android (push) Successful in 13m48s
    windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 4m32s
    rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 23m37s
    rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 24m2s
    windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 8m1s
    apple / swift (push) Successful in 2m8s
    apple / screenshots (push) Successful in 9m31s
    windows-host / package (push) Successful in 13m9s
    windows-host / canary-manifest (push) Skipped
    windows-host / winget-source (push) Successful in 35s
    apple / distribute (push) Successful in 12m30s
    nix / flake (push) Successful in 20m9s
    Stable

    enricobuehler released this 2026-08-23 10:33:03 +00:00 | 2659 commits to main since this release

    Wire-compatible with 0.31.x — everything you have already paired keeps working, and you can update one side at a time. Nothing here changes how a host and a client agree on what to send each other, so an old client on a new host, or the other way round, streams exactly as it does today.

    This is a fix release about streams that ended, froze, stuttered or never arrived while everything involved was doing something perfectly ordinary. Launching a Steam game that had shaders to process dropped the stream about ten seconds in, so people learned to launch everything twice. A fullscreen game that picks its own screen resolution mid-play froze the picture on a Windows host and ended the video a few seconds later with the sound still running. On an Android TV or a Fire Stick the app was quietly asking your host for a frame rate your television does not actually output, which is where the latency people had been working around by hand was coming from. And on a slower connection the very first thing a client does — a quick burst to measure what the link can carry — was big enough to choke the link it was measuring, delaying the picture by many seconds or losing it entirely. There is new work too: your Moonlight devices can be given names, and a 4K television or projector can now run the on-screen interface at a lower resolution to keep it smooth.

    TL;DR

    • A Steam game with shaders to process dropped the stream about ten seconds into launching it. You watched the "Processing Vulkan shaders" dialog, lost the stream, reconnected and launched again — and the second launch worked, which is why this looked like bad luck rather than a bug.
    • Android TV and Fire Stick: the app negotiated a frame rate your TV does not output. Setting the refresh rate by hand was the known workaround; it is no longer needed, and the latency it was papering over is gone.
    • A slow first picture, or none at all, on a constrained connection. The startup speed test was so large it could black-hole the very link it was measuring — one case took fourteen seconds to show video. It is now sized to the session, and if the test does swallow the opening frame the client asks for a new one instead of sitting on black.
    • Windows: a game that changed your screen resolution mid-stream froze the picture and then ended the session. The sound carried on throughout, which is exactly what makes this look like a problem at the client's end.
    • Fire TV: a DualSense had buttons that never reached the game, and its touchpad click and Mute button did nothing. Mute now mutes your microphone.
    • New: name your Moonlight devices instead of a list of identical rows, and — on a 4K TV or projector — Reduce interface resolution for a smoother on-screen interface.

    Before you update

    • Steam Deck, and only if you installed the host from source: re-run your update after taking this release. A source install builds a patched compositor, and that build has been failing since mid-August because of a missing system package. The failure was silent — it reported success, and quietly dropped back to the system's own compositor, which is why HDR disappeared on boxes that had been streaming it minutes earlier. The missing package is added here, so the next build succeeds. Nothing to do on a packaged install.

    New

    • Give your Moonlight-paired devices names. This is not a display bug being fixed: every Moonlight-compatible client identifies itself with the same built-in name, so it says which app is connecting and nothing about which device. Until now that name was all the console could show, and someone who had paired a phone, a television and a handheld saw three rows reading identically. Each Moonlight row now has a pencil next to it — name it "Living room TV", and that is what the list says from then on, including when you are choosing which device to remove. Devices paired with Punktfunk's own apps already send a real name and are left alone. Names live on the host, so every browser you open the console in sees the same ones, and removing a device forgets its name.
    • Reduce interface resolution, for a 4K television or projector. The on-screen interface is drawn at whatever resolution the panel hands it, and on a 4K set that is four times the work of 1080p on a chip built to decode video rather than to draw a moving interface — which is why the premium 4K boxes are the ones that feel sluggish, not the cheap 1080p sticks that never had the extra pixels. The new switch sits directly under Reduce motion, because it is the same kind of bargain: text goes a little softer, the interface gets smoother. It is off by default. It changes the interface only and does nothing to your stream — picture quality is still Resolution and Bitrate, which are separate settings and untouched by this.

    Improved

    • The on-screen interface got substantially cheaper to draw, on every device. Independently of the switch above, it was doing a surprising amount of work on every single frame whether or not anything had changed: re-measuring and re-laying-out every piece of text on screen sixty times a second, and allocating a full-screen scratch image to apply an effect that did nothing whenever the interface was sitting still. On a 4K panel that scratch image alone was larger than the memory budget the whole interface is allowed on a 2 GB box, so it was evicting real work in order to do nothing. Both are gone, and the result is pixel-for-pixel identical. The interface also now gets a scheduling priority just below the stream's, so a TV box cannot park it behind background work and leave it lagging your remote.
    • When the interface is slow, the logs can now say so. It recorded which graphics version it had and how much memory it was allowed, and never what resolution it was drawing at or how long a frame took — so "it feels sluggish" could not be looked into from a log bundle at all. It now reports both.

    Fixed

    • Launching a Steam game dropped the stream while it was still starting, so you had to launch it twice. Reported on Rocket League: the stream showed the "Processing Vulkan shaders" dialog and then ended about ten seconds in, every time, with a second launch working fine. The host was doing this to itself. Steam does its preparation work for a game — processing shaders, most visibly — under the same marker it uses for the game itself, so a launch is a short chain of things that all look like your game, and only the last one is. The host accepted the first one, and from that moment it was no longer waiting for a game to start but watching for one to exit; when the preparation step finished a few seconds later, that was read as the game exiting and the session was closed. Two things change. The shader step is now recognised for what it is and never mistaken for a game. And anything else must be seen continuously for a few seconds before the host will believe it is your game — the rule it already applied to programs a launcher starts, now applied to what it finds by looking. The cost is a few seconds' delay before the host says a game is running; nothing about detecting a game exiting changes, so a game you quit still ends the session as promptly as before.
    • Android TV and Fire Stick: the app asked your host for a frame rate the television does not output, and the latency went through the roof. People had already found the workaround — set the refresh rate by hand — without knowing what it was working around. The app pins the panel to its highest refresh rate while you are in the on-screen interface; that exists for phones whose systems otherwise cap apps at 60, and no television needs it. But when the stream started, the app read the panel's pinned rate rather than what the TV genuinely outputs over HDMI, negotiated the session at that — and then released the pin, because on a TV the video decoder is what should be driving the HDMI mode. The result was a 120-frame stream arriving at a 60 Hz output, by construction, on exactly the two kinds of device in the reports. The pin is no longer applied on a television at all. A TV that really can do 120 still gets it by choosing it. In the same chain: a TV that reports the fractional broadcast rates (59.94, 29.97, 23.976) had them cut down to 59, 29 and 23 — rates no display actually has — and they are rounded properly now.
    • A slow first picture, or a black screen, on a constrained connection. Before any video, a client sends a short burst to work out how much the link can carry. That burst was a fixed, very large size on the reasoning that it should measure the link rather than itself — but the result is capped afterwards to what the session could plausibly use, so everything above that was measured and immediately thrown away. What it bought was nothing; what it cost was a flooded link. On a constrained Wi-Fi connection it could black-hole outright: one measured case spent six seconds timing out and took fourteen seconds to show any video, and the same shape came in from a Fire TV Stick 4K Max. The burst is now sized from what the session can actually use, which can never come out lower than what is needed to prove the ceiling. And the second half of the black screen is closed too: if the burst takes the opening frame down with it, the client now asks for another one instead of waiting for some unrelated recovery to happen along.
    • Windows: a game that changed your screen resolution during a stream froze the picture and then ended the session. Reported from a 4K session where the game switched the display to 1080p while it ran. A fullscreen game is allowed to choose its own resolution, and your host followed it — but the part of the host that compresses the picture cannot change size while it is running, and it was being rebuilt over and over at the size the game had already left. After about three seconds of that, the video ended while the sound kept playing, so you were left with a frozen picture, working audio and no option but to reconnect. The host now rebuilds at the size the game actually chose and tells your client about the new one, exactly as it does when you change the resolution from the client. The same fix covers a game that switches HDR on or off mid-play, which failed in the same way. If a rebuild does not take the first time — a display that has just changed mode is often still settling — it is retried for the same few seconds rather than the session being given up on immediately.
    • The same resolution change in a Moonlight-compatible session ended it too, and now does not. One caveat worth knowing, because it is a real trade: the protocol Moonlight speaks has no way for a host to announce a resolution change once a stream is running, so your client is not told. Most clients notice from the picture itself and adjust; a strict one — Media Foundation on Xbox is the known example — may stall instead and need reconnecting. That is the same bargain these sessions already take whenever the host's picture and the client's request disagree, and it is strictly better than what it replaces, which was every such stream ending.
    • Moonlight-compatible sessions stuttered at high frame rates, and the host was doing it to itself. When a client loses its place in the video it asks the host for a complete picture to start again from, and the host is supposed to ignore repeat requests that arrive too quickly. The gap it waited for was measured in frames rather than in time, which at 120 frames a second is about a sixtieth of a second — far shorter than the time a client needs to ask, receive and decode — so the requests never looked like repeats and nearly all of them were honoured. One field session recorded 1,118 such requests in 91 seconds and honoured 1,115: a complete picture roughly every tenth frame, each one large enough to saturate the connection, causing the loss that prompted the next request. It reads as heavy stutter while every latency figure stays flat, because frames are being lost rather than delayed. It also looked like a codec fault, because the same session's H.264 stream — encoded by a different part of the host — asked twice in the whole session and was completely clean. The host now waits a fixed tenth of a second before honouring another request. The field case was a 120-frame session, but the old window was too short at 60 as well, so this is not only a fix for high-refresh displays.
    • Fire TV: a DualSense had buttons that never reached the game, and its touchpad click and Mute button did nothing. Three separate faults on one controller, all reported together over Bluetooth. Some of its buttons were being labelled by the system as coming from a keyboard rather than a controller, and the app was dropping them on that basis — it now trusts what the device is rather than the system's per-press guess, and only ever for keycodes that are genuinely controller buttons, so a remote's Back button and a keyboard's arrow keys are untouched. The touchpad click and the Mute button had nowhere to go at all and were simply discarded; both now travel to your game. And Mute genuinely mutes your microphone, once per press — held down, it no longer flickers the microphone on and off — on controllers that actually have the button.
    • Android: the app could crash outright while playing, most often on an NVIDIA Shield. The system call the app used to pick up the newest video frame hands back a resource it has already given away when more than one frame arrives at once, which the system's own safety check then catches by killing the app. It is a bug in Android that is still unfixed upstream, so the app stops using that call and picks the newest frame itself.
    • Linux: after disconnecting, the box's own screen could stay black. Reported on both Bazzite and Nobara. The hand-back at the end of a session asked the system to bring the desktop session back and then walked away the moment the request was accepted — but "the request was accepted" and "the screen is showing something" are different questions, and nothing had ever asked the second one, so every way of ending up dark looked identical to success. It now checks: if the box is still dark twenty-five seconds after the hand-back, it works through a ladder of increasingly firm remedies, each of which was measured on real machines of both families, and if it still cannot fix it, it says exactly what a human should run. This is not a guess at one trigger — the specific fault people reported could not be reproduced. It closes the gap that lets any trigger end as a dark panel.
    • Windows: duplicate "Punktfunk Speakers" and "Punktfunk Microphone" devices piled up in your sound settings. Creating one of these is two steps, and a host that died between them left behind a fully working device with no ownership mark on it. Nothing ever recognised that afterwards, so the next start created a second one and the stray outlived it — and because uninstalling also went by the ownership mark, uninstalling did not remove it either. One field machine showed exactly this. The host now recognises a stray from a previous run and adopts it instead of creating another, and uninstalling sweeps up ones already on the machine. Separately, on machines where the usual naming route is blocked, the microphone's name was being written to a location that only exists for speakers, so it silently kept the driver's default name.
    • Steam Deck: HDR stopped working after updating to 0.31.2 on a source install. Two faults with one symptom. The build of the patched compositor had been failing since mid-August on a missing system package — added here — and the failure path then went on to unlink the compositor that was already installed and working. A build that never produced anything replaced nothing, so removing the perfectly good previous one meant the host fell back to the system's own compositor and fixed the session at 8-bit, which cannot be taken back once a session has started. A failed build now leaves the working installation alone.

    Thanks

    Almost everything above came from someone reporting exactly what they saw and on what — the game they launched and the dialog it hung on, the two 4K boxes that felt slow, the make of controller and which button did nothing, the card and the frame rate, the fourteen seconds before a picture appeared. Two entries are worth calling out for a different reason. The Linux black-screen fix ships without a reproduction: five scenarios were run across both distributions on real machines, the mechanism first proposed was disproved, and rather than guess, the fix closes the gap that lets any cause end the same way. And the DualSense work was re-implemented from a contributor's diagnosis rather than merged as sent — all three faults were real and correctly identified, but each proposed fix reached further than the hardware that needed it. The diagnosis was the hard part and it was right. Thank you.

    For developers

    Protocol, ABI, driver and embedder detail — including the version table — is in CHANGELOG.md.

    The short version: nothing versioned moves. The streaming protocol, the embedding interface, the driver protocol, the gamepad channel and the add-on contract are exactly where 0.31.2 left them — include/punktfunk_core.h has no diff at all against the v0.31.2 tag — and no header, package or plugin needs rebuilding, re-pairing or re-publishing in any direction. The one surface that grows is the management API, additively: a PATCH /api/v1/clients/{fingerprint} route sets or clears a paired client's label, and GET /clients gains a label field alongside the existing certificate subject. Nothing existing changed shape, so a consumer that ignores both is unaffected. The TypeScript SDK is re-cut as @punktfunk/host 0.1.6 so an add-on can actually reach the generated types for that route; the add-on toolkit is unchanged. One dependency moves for a security advisory (h2, lockfile-only), and one behaviour worth knowing about if you integrate: the host now reports a game as running a few seconds later than it used to when it identifies that game by scanning processes rather than by a plugin's own report.

    Downloads
  • v0.31.2
    audit / docs-site-audit (push) Successful in 23s
    audit / bun-audit (web) (push) Successful in 24s
    audit / bun-audit (sdk) (push) Successful in 26s
    audit / pnpm-audit (push) Successful in 19s
    audit / bun-audit (plugin-kit) (push) Successful in 26s
    audit / cargo-audit (push) Failing after 40s
    ci / web (push) Successful in 1m21s
    ci / docs-site (push) Successful in 1m13s
    ci / bun-nix (push) Successful in 16s
    ci / docs-drift (push) Successful in 21s
    audit / license-gate (push) Successful in 4m57s
    audit / miri (push) Successful in 6m17s
    audit / c-abi-asan (push) Successful in 6m24s
    android-screenshots / screenshots (push) Successful in 1m54s
    ci / rust-arm64 (push) Successful in 1m38s
    ci / rust (push) Successful in 8m29s
    android / android (push) Successful in 11m48s
    arch / build-publish (push) Successful in 9m23s
    linux-client-screenshots / screenshots (push) Successful in 4m53s
    sbom / sbom (push) Successful in 33s
    web-screenshots / screenshots (push) Successful in 6m46s
    decky / build-publish (push) Successful in 48s
    docker / builders-arm64cross (push) Successful in 10s
    docker / builders (--build-arg FEDORA_VERSION=44, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm, -f44) (push) Successful in 20s
    docker / builders (ci/android-ci.Dockerfile, punktfunk-android-ci) (push) Successful in 13s
    docker / builders (ci/arch-ci.Dockerfile, punktfunk-arch-ci) (push) Successful in 15s
    docker / builders (ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 14s
    docker / builders (ci/flatpak-ci.Dockerfile, punktfunk-flatpak-ci) (push) Successful in 11s
    docker / builders (ci/gamescope-trixie.Dockerfile, punktfunk-gamescope-trixie) (push) Successful in 8s
    docker / builders (ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 16s
    docker / builders (ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 13s
    docker / apps (., web/Dockerfile, punktfunk-web) (push) Successful in 17s
    docker / apps (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 1m31s
    docker / deploy-docs (push) Successful in 17s
    nix / flake (push) Successful in 22m13s
    deb / smoke-install (push) Successful in 2m52s
    deb / build-publish (push) Successful in 5m12s
    deb / build-publish-host (push) Successful in 5m39s
    deb / build-publish-gamescope (push) Successful in 1m5s
    deb / build-publish-client-arm64 (push) Successful in 2m42s
    rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 18m49s
    apple / distribute (push) Successful in 13m6s
    apple / swift (push) Successful in 2m4s
    rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 21m22s
    apple / screenshots (push) Successful in 9m40s
    windows-host / package (push) Successful in 13m30s
    windows-host / canary-manifest (push) Skipped
    windows-host / winget-source (push) Successful in 28s
    windows-client / client (arm64, --no-default-features, aarch64-pc-windows-msvc, C:\t-a64) (push) Successful in 5m57s
    windows-client / client (x64, , x86_64-pc-windows-msvc, C:\t) (push) Successful in 9m45s
    flatpak / build-publish (push) Failing after 8m56s
    Stable

    enricobuehler released this 2026-08-21 20:50:53 +00:00 | 2704 commits to main since this release

    Wire-compatible with 0.31.x — everything you have already paired keeps working, and you can update one side at a time. Nothing here changes how a host and a client agree on what to send each other, so an old client on a new host, or the other way round, streams exactly as it does today.

    This is a fix release, and most of it continues the hunt 0.31.1 started: a stream that connects, reports itself perfectly healthy at every gauge, and shows you a black screen. Two more causes end here, and both are about which of your host's addresses it used — video that left the host by whichever network connection the machine happened to prefer rather than the one your client actually dialled, and a host that started up faster than its own network and then spent the rest of the day telling everyone to connect to an address that only ever means "this machine". The other half is Windows security: the firewall rules Punktfunk installs named ports but not programs, which left those ports open to anything running on that PC — they name Punktfunk now, and that is the one change here that can affect another program on the same machine. On Android, the controller fix from 0.31.1 turned out to be firing on controllers that never needed it, breaking buttons that had been correct all along.

    TL;DR

    • A host with two ways to reach your client streamed into a black screen. Ethernet and Wi-Fi both connected, or a VPN adapter installed, was enough: the video left by whichever one the machine preferred, and your client discarded every packet of it. Nothing else about the session was wrong, which is exactly why it was so hard to see.
    • A host that started before its network was ready never recovered. It advertised an address meaning "this machine", so clients listed it and could not connect to it, Moonlight-compatible sessions could not stream, and Wake-on-LAN silently stopped working. Restarting the host was the only cure; now there is nothing to cure.
    • Windows: Punktfunk's firewall rules were open to every program on your PC. They named only port numbers, so any program — with no administrator rights and no prompt — could take one of those ports and be reachable from your network through a rule meant for Punktfunk. Read Before you update: one thing on that machine may now need a rule of its own.
    • Android: 0.31.1's controller fix broke controllers that were already correct. On a GameSir G8+ and an Xbox Elite Series 2 over Bluetooth, X answered Y, Y answered the left shoulder, and both shoulders answered menu buttons.
    • Your host now follows its own address when it changes — a new lease from your router, or a machine moved between Wi-Fi and Ethernet — instead of announcing the address it had at startup forever.

    Before you update

    • Windows hosts: run the installer rather than replacing the program by hand. The firewall fix rewrites the rules Punktfunk installs, and that happens in the host's own service-install step, which the installer runs for you on every update. If you run the host some other way, run punktfunk-host service install once as an administrator. Skipping it leaves the old wide-open rules in place; nothing on the client side needs doing.
    • Windows hosts: something else on that machine may need its own firewall rule now. Punktfunk's rule for the discovery port (5353) used to be open to every program, so anything else on that PC that answers discovery — another streaming host, a media server, a printer or scanner utility — could have been reachable through Punktfunk's rule without ever having one of its own. That ends with this release. If something else on the machine stops being discoverable after you update, give it its own rule. The installer prints a note saying exactly this while it works.

    Improved

    • Your host keeps up with its own address instead of freezing it at startup. The address a host publishes for clients to dial was worked out once, when the host process started, and then never looked at again. Now it is re-read as things change and the published address is updated to match — so a new lease from your router, or a laptop host carried from Wi-Fi to Ethernet, no longer leaves your clients dialling somewhere the host has not been for hours. This is the general form of the cold-boot fix below, and it covers the cases nobody had got round to reporting yet.
    • When a stream does go black, the host's log now tells you the truth about it. The message it printed used to name a cause with real confidence — and was wrong often enough to send people to the wrong place entirely, including at least one investigation that went to the firewall while the actual fault was the network card. It no longer asserts a cause it cannot know, and it now records which network connection the video is actually leaving by, and says so plainly when that is not the one the client arrived on. That single line is what turns the black screen above from a mystery into something a log answers.

    Fixed

    • A host with more than one live path to your client sent the video down the wrong one, and you got a black screen with every indicator green. Two network connections up on the same network — the very common Ethernet-and-Wi-Fi-both-on — or a VPN or overlay adapter that claims to know a better route, and the host let the machine choose which one the video left by. That choice was made with no reference at all to how your client had reached it. Your client only listens for video from the address it dialled, so it threw away everything arriving from the other one, in the part of the system that counts nothing and reports nothing. Meanwhile the connection was made, sound and controller input flowed perfectly, and the host's own loss figure sat at zero — because loss is measured over packets that arrived, and none did. The host now sends the video from the same address the client reached it on.
    • A host that started before its network was ready advertised itself as unreachable, and stayed that way until it was restarted. Cold-booting a machine is a race, and the host wins it: it starts without waiting for the network, asks which address it should publish, gets no answer because there is no network yet, and falls back to the address that means "this machine and nothing else". Then it kept that answer for the entire life of the process. Everything that reads that address broke together — the host appeared in your client's list but could not be connected to, Moonlight-compatible sessions were handed the same useless address after launching a game, Wake-on-LAN quietly stopped working because the host could no longer identify the network hardware to record for it, and the web console displayed the wrong address to anyone who looked. Users found the workaround themselves, which was to restart the host once the machine had settled. The host now refuses that fallback answer entirely: if the usual method cannot say which address to use, it takes the first real network address it can find, which exists as soon as the network card is configured — well before the machine finishes working out how to route anything.
    • Windows: the firewall rules Punktfunk installs opened those ports to every program on the machine, not to Punktfunk. Each rule named a port and nothing else, and a rule like that admits whatever is listening on that port — Punktfunk or otherwise. Nothing about it required administrator rights to exploit: taking a high-numbered port on Windows needs no privileges at all, so any program that started first could sit on one of Punktfunk's ports and be reachable from your whole network. Worse, it happened without any of the usual signs, because the pop-up asking whether to let a program communicate on your network is precisely what a matching rule suppresses — Punktfunk's rule was answering that question on another program's behalf. Every rule now names the program that is genuinely meant to be listening on it, and keeps the port restriction as well, so both must match. The affected ports were the streaming, discovery, management and console ports. If Punktfunk cannot work out its own location on disk it keeps the old broader rule rather than leaving you with no rule at all, since a rule that is too generous still streams and a missing one is a black screen.
    • Android: controllers that had always worked started pressing the wrong buttons. This is a regression from 0.31.1, reported the same day on a GameSir G8+ and an Xbox Elite Series 2: X answered Y, Y answered the left shoulder, and the two shoulder buttons answered menu buttons, with everything else correct. 0.31.1 fixed controllers Android has no layout file for by reading each button's position in the controller's own report instead of trusting Android's guess — the right fix, applied to too many controllers. It decided which controllers needed it by asking what the device claimed to have, and that claim turns out to be true of any controller with six or more buttons, including every controller that was already perfectly correct. So it corrected pads that needed no correcting, and moved their buttons off the marks. It is now decided on the triggers instead: a controller that describes its triggers properly is one Android has a real layout for, and it is left completely alone — no correction to its buttons or its sticks. That is the same signal Moonlight uses for the same decision, and it matches the reports precisely, down to the fact that the very same model needed correcting on a Fire TV and was broken by it here: an Xbox Wireless Controller describes its triggers one way after a firmware update and the other way before it, and only the older one was ever wrong.

    Known issue

    • A DualSense with a dead Triangle button is not fixed here. It was reported alongside the two controllers above and looks related, but it is not the same fault — Triangle reaching neither the stream nor Punktfunk's own controller display is a different failure from a button arriving as the wrong one, and nothing in the fix above produces it. The Connected controllers page prints exactly what each press reports; that line from an affected pad is what will pin it down.

    Thanks

    Every fix in this release came from someone reporting what actually happened rather than what they assumed. Both black-screen causes were found in field logs from hosts that looked entirely healthy — and the firewall hole was reported by a user on the same day, immediately after the first of those fixes cleared their black screen and left them looking at the rules. The Android controller regression came back within a day of the release that caused it, from two people who named which button answered which, which is the difference between a report that can be fixed and one that can only be believed. Thank you.

    For developers

    Protocol, ABI, driver and embedder detail — including the version table — is in CHANGELOG.md.

    The short version: nothing versioned moves at all. The streaming protocol, the embedding interface, the driver protocol, the gamepad channel and the add-on contract are exactly where 0.31.1 left them, no message or function changed shape, and no header, package or plugin needs rebuilding, re-pairing or re-publishing in any direction. Two things worth knowing: on Windows the firewall rules provisioned at install are now scoped to the executable that listens on each port, which is the one change here that can affect another program on the same machine; and the host's reported address in the management API is now read fresh on every request instead of being fixed for the life of the process, so poll it rather than caching it.

    Downloads