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:
| System | How to get it |
|---|---|
| Arch, replacing niri | AUR biri-git. It provides niri and installs /usr/bin/niri. |
| Arch, beside niri | AUR biri-altinstall-git. It installs biri and biri-session next to stock niri. |
| Nix, NixOS | The biri repository's flake.nix exports a package and an overlay. Use it as programs.niri.package. |
| Anything else | Build 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-hostOn 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 fingerprintOpen 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.