PunktfunkPunktfunk
Linux desktops

niri (biri)

Stream a niri session through biri, the niri fork that adds virtual outputs, and fix stock niri, socket and capture problems.

Stream a niri session. Stock niri can't create a virtual output, so the host needs biri, a niri fork that adds them. Install the host first: Arch, Ubuntu or Fedora.

What works

  • Each client gets its own virtual output at its size and refresh rate, created over niri's IPC and removed when the client leaves. A resize mid-stream works.
  • The host captures it straight from the compositor on the GPU, or through niri's built-in screencast. No chooser appears.
  • Keyboard and mouse go in through the wlroots virtual pointer and keyboard protocols. The clipboard goes through ext-data-control.
  • Library launches open on the streamed output's own workspace. The host can move a game's window there and make it full-screen: see Automation.
  • Turn off under Your monitors while streaming switches your monitors off while you stream and back on afterwards. Monitors set to Stay on stay lit.
  • A device's Scale its screen at applies to its output.

It needs a niri session running biri. It finds that niri on every connect; you don't export NIRI_SOCKET.

Get biri

niri's IPC has no request that adds an output, so stock niri can't give each client a display. biri is a niri fork that adds the request. The host asks niri whether it can create one rather than checking its name. Everything else in niri's own docs applies, and biri's extra features are off until you configure them.

biri ships no release binaries:

SystemHow to get it
Arch, replacing niriAUR biri-git. It provides niri and installs /usr/bin/niri.
Arch, beside niriAUR biri-altinstall-git. It installs biri and biri-session next to stock niri.
Nix, NixOSThe biri repository's flake.nix exports a package and an overlay. Use it as programs.niri.package.
Anything elseBuild it from the biri repository: cargo build --release.

biri-git removes your niri package. It conflicts with niri, niri-git and niri-bin, so pacman offers to replace whichever you have. Take biri-altinstall-git to keep stock niri installed.

Use a biri built on 2026-09-04 or later: older builds crash niri when an off virtual output is removed.

Log out and back in so niri restarts as biri, then restart the host:

systemctl --user restart punktfunk-host

On the next connect the log says niri: virtual outputs available.

host.env

Nothing is required: the host finds niri on every connect.

Leave PUNKTFUNK_COMPOSITOR unset: a pin turns off detection and session following. It accepts niri (alias biri) if you need it. Every other option is in Configuration.

Start the host

From inside your niri session:

systemctl --user enable --now punktfunk-host
journalctl --user -u punktfunk-host -f    # watch it start and print its fingerprint

Open the web console to pair a client. To serve Moonlight too, see What the unit starts. To restart the host with niri, see Restart the host with your desktop.

Headless session

There is no packaged headless niri session. Log in on the box, or autologin through your display manager, and enable lingering so the host starts at boot: sudo loginctl enable-linger "$USER".

Known limits

  • Only biri can host. On stock niri the host can stream a monitor you pin, never a virtual screen: see below.
  • SDR only: niri has no colour management. HDR on Linux needs gamescope — see HDR.
  • Under Turn off, a host that dies mid-stream leaves your monitors dark until the next host start lights them.

Troubleshooting

this niri has no virtual outputs

The host logs this niri has no virtual outputs — install biri, the niri fork that adds them. Your niri is stock. The client is told the host can't create a display, and the web console's Troubleshooting page shows a failed niri virtual outputs check. Get biri and restart the host.

To stream meanwhile, click Stream this monitor on a monitor's row in Screens, or set PUNKTFUNK_CAPTURE_MONITOR to its connector. That works on stock niri: Stream a real monitor instead.

"find the niri IPC socket (no NIRI_SOCKET, no niri.*.sock)"

The host found no running niri for its user: it started outside your niri session, or PUNKTFUNK_COMPOSITOR pins niri while another desktop runs. Start the host from inside the session, as above, and leave the pin unset.

"can't create a virtual output here"

The log adds niri's reason, such as not supported on the Winit backend. This niri runs as a window inside another compositor, and a nested niri can't host virtual outputs. Run niri on a TTY.

"no X display for the launch"

niri runs X11 apps, Steam and Lutris among them, through xwayland-satellite, and turns its X11 support off when that isn't installed. Install xwayland-satellite, log out and back in, and launch again.

"no direct capture on this compositor — using the ScreenCast portal"

The stream carries on through niri's built-in screencast; the log's reason says why direct capture was skipped. A software encoder always takes the screencast. If the reason says the capture protocol is missing, update biri: direct capture needs ext-image-copy-capture.

More fixes in Troubleshooting.

On this page