PunktfunkPunktfunk

Host CLI

Every punktfunk-host command and flag you would run by hand, plus where the client's punktfunk command is documented.

Look up a punktfunk-host command or flag here. Most behaviour comes from host.env, not the command line; a flag wins over its host.env twin.

CommandWhat it doesPlatform
serveRun the host.all
ctlDrive a running host: pairing, devices, sessions, displays, stats, events.all
pluginsInstall, remove and list plugins, grant them folders, switch the runner on.all
libraryPrint the resolved game library as JSON.all
detect-conflictsReport other Moonlight-compatible hosts on this machine.all
openapiPrint the management API's OpenAPI document.all
punktfunk1-hostStandalone native-only test host.all
--versionPrint the host version.all
list-monitorsList the physical monitors by connector name.Linux
mirror-testCapture one of them with no client, to prove the path works.Linux
anchor-testMove the pointer across one of them, to check where absolute input lands.Linux
hdr-probeSay whether this box can stream 10-bit HDR, and what is missing.Linux
probe-compositorExit 0 once the compositor can create a virtual output.Linux
hdr-p010-selftestCheck the GPU's HDR capture colour conversion.Windows
serviceRegister, control and remove the Windows service.Windows
trayStart, stop or query the status tray.Windows
driverCheck or remove the bundled drivers.Windows
seatsTurn seats off without the service.Windows
webPrint the web-console login password.Windows

punktfunk-host --help prints the common commands. ctl, plugins, service, tray, driver and web print their usage when run with no arguments.

serve

Runs the native punktfunk/2 host and the management API in one process. The native plane always runs.

punktfunk-host serve
Flaghost.env twinMeaning
--gamestream / --moonlightPUNKTFUNK_GAMESTREAM=1Also serve stock Moonlight clients. Trusted LAN only: GameStream pairs over plain HTTP.
--native-port <PORT>PUNKTFUNK_NATIVE_PORTNative QUIC port (default 9777).
--mgmt-bind <IP:PORT>PUNKTFUNK_MGMT_BINDManagement API address (default 0.0.0.0:47990). 127.0.0.1:47990 keeps it off the LAN, and paired clients can't browse your library.
--webtransportPUNKTFUNK_WEBTRANSPORT=1Also accept the browser client (preview).
--webtransport-port <PORT>PUNKTFUNK_WEBTRANSPORT_PORTIts UDP port (default 9778).
--webtransport-bind <IP>PUNKTFUNK_WEBTRANSPORT_BINDIts interface (default: all).
--open—Serve unpaired devices. Trusted single-user setups only. With the browser client on, it also needs PUNKTFUNK_WEBTRANSPORT_ORIGINS, or the host refuses to start.
--no-mdnsPUNKTFUNK_MDNS=0Skip the mDNS adverts; add the host on the client by address.
--doorPUNKTFUNK_DOOR=1Linux: the box's host as a system service. It advertises, pairs, serves the console and places every connect on a seat, and opens no display. The Reachable without logging in switch runs it.
--native—No-op.

Pairing is required unless --open: arm it from the web console — see Pairing & Trust.

The management API is HTTPS and listens on every interface by default. Off loopback it serves paired clients the read-only status and library. Every admin action needs the token in mgmt-token and works from loopback only. The host writes that file on first start into its config directory (~/.config/punktfunk, or %ProgramData%\punktfunk on Windows); the console, ctl and the tray read it. Every endpoint is in the API Reference.

ctl

Drives a running host over loopback: everything the web console does day to day, from a terminal.

punktfunk-host ctl pending
punktfunk-host ctl approve 3
VerbWhat it does
statusHost state, live session count, paired-device counts.
sessionsThe active sessions and any launched game.
summaryHost version, what is streaming, the streaming client's name, paired counts, conflicting hosts. The only verb that names a connected device.
pair statusWhether a pairing window is open and a PIN is waiting.
pair armOpen a native pairing window and print the PIN. --ttl <s> window length, --expires-in <s> how long the device's access lasts, --preset <full|controller|view>, --fingerprint <fp> binds the window to one device.
pair disarmClose the window.
pendingDevices waiting for approval, with claimed name and fingerprint tail.
approve <ID>Admit one. Takes --name, --preset, --expires-in.
deny <ID>Refuse one.
pin <PIN> <UNIQUEID> <FP> <PEER_IP>Submit a Moonlight client's PIN, with the other three values exactly as ctl pair status shows them.
clientsPaired devices on both planes.
rename <FP> <NAME>Name a device.
access <FP> <PRESET>full, controller or view — see Access levels.
unpair <FP>Remove one device. unpair --all removes every device on both planes; it asks first, or takes --yes.
stop-sessionStop the active session.
end-gameEnd the launched game.
displayThe virtual-display policy, every preset, and the live and kept displays.
display preset <ID>Switch to a preset. The streamed screen and other settings a preset doesn't own stay.
display release [SLOT]Tear down kept displays now; omit SLOT for all. Never touches a streaming display.
statsMode, codec and bitrate of the live stream; frame timings and drops while a capture records.
stats record start|stopArm or stop the performance capture. stop writes it to disk. The console shares the one slot.
watchHost events as line-JSON. --kinds pairing.pending,stream.* filters; --since <seq> resumes.
console-urlPrint a file:// link that opens the console already logged in. Linux and macOS.

In stats, Target is the encoder's bitrate; Sent is what left the box and exists only while a capture records. A still screen sends little, so read new fps beside repeated fps.

Add --json to any verb: {"v":1,"data":…} on success, {"v":1,"error":{"code":…,"message":…}} on failure, both on stdout. That envelope is stable; the human tables are not.

Exit codeMeaning
0Success.
1The host refused the request; the message says why.
2Usage error.
3No host reachable, or it never ran on this machine.
4Certificate pin mismatch — something else answers on the management port. Don't retry.

watch reconnects by itself and starts at the live tail (--since 0 replays the host's ring). It adds two lines of its own: {"kind":"ctl.resync"} means it fell behind, so re-read ctl status and ctl pending; {"kind":"ctl.disconnected"} means a reconnect is under way.

ctl reads the host's mgmt-token and pins its native-cert.pem before sending the token. It never creates a token and takes none on the command line or from the environment.

settings

punktfunk-host settings set gamestream true

Writes one Host value to host-settings.json, as the console does, without a running host. Installers use it, so the console can still change what they chose. The value is JSON (true, 30, null to clear) or a bare string. Restart the host to apply it.

plugins

punktfunk-host plugins add|remove|list|enable|disable|status|grant|access|revoke does what the console's Plugins page does. Plugins run with the host's privileges; read Plugins first.

library

punktfunk-host library prints the game library as JSON, the same as GET /api/v1/library — the quick answer to "does the host see my games?". punktfunk-host library art --clear deletes the covers the host cached for clients.

punktfunk1-host

A standalone native-only host for testing the punktfunk/2 path, with no GameStream and no console. Pairing is required; it logs a PIN at startup.

punktfunk-host punktfunk1-host --source virtual
FlagMeaning
--port <N>QUIC port (default 9777).
--source <SRC>synthetic (default, test frames), synthetic-abr (frames sized from the live bitrate; no display or GPU needed) or virtual (a real virtual display).
--content <SCRIPT>What synthetic-abr encodes: steady (default), idle-then-motion, frame-driven:<fps>, or motion-then-still:<fps> (a minute of motion, then <fps> new frames a second among repeats).
--fill <PCT>Share of each frame's bit budget synthetic-abr fills, 1–100 (default 100).
--recovery-ms <MS>How long synthetic-abr takes to answer a keyframe request (default 0).
--keyframe-answer <KIND>idr (default) or wave:<n>: answer only every n-th keyframe request with one.
--idr-pct <PCT>A keyframe's size as a percent of an ordinary frame (default 1000).
--bringup-ms <MS>How long synthetic-abr holds its first frame back (default 2500).
--no-rampDon't offer the client a link measurement before the first frame.
--seconds <N>Session length for virtual and synthetic-abr (default 30).
--frames <N>Session length for synthetic (default 300).
--max-concurrent <N>Sessions streaming at once (default 4, 0 = unlimited); the rest queue.
--max-sessions <N>Exit after N sessions (default 0, serve forever).
--allow-tofuAlso accept unpaired clients. Trusted LANs only.
--pairing-pin <PIN>Fixed pairing PIN, for test harnesses. A guessable PIN defeats the rate limit.
--idle-timeout-ms <MS>How fast a dead client is detected (QUIC idle timeout, default 8000).
--no-mdnsSkip the mDNS advert.

service (Windows)

The installer runs service install; you need these only to change an option or nudge the service. Run them from an Administrator prompt.

punktfunk-host service install [--gamestream=on|off] [--allow-public-network[=on|off]]
                               [--mgmt-bind=IP:PORT] [--web-bind=ADDR]
punktfunk-host service start | stop | restart | status | uninstall
Subcommand or optionWhat it does
installRegisters the auto-start PunktfunkHost service, adds the firewall rules, and writes %ProgramData%\punktfunk\host.env if missing. Re-run it to change an option.
--gamestream=on|offThe GameStream setting, as in the console.
--allow-public-network[=on|off]Also open the ports on networks Windows calls Public. Default: Private and Domain only; left out, the previous choice stays.
--mgmt-bind=IP:PORTSets PUNKTFUNK_MGMT_BIND and opens that port.
--web-bind=ADDRSets PUNKTFUNK_UI_BIND, the console's address: 127.0.0.1, 0.0.0.0, or one of yours.
uninstallStops and deletes the service and its firewall rules. The host stays — see Uninstalling.
start / stop / restartService control. restart waits for the old process, so it picks up a host.env edit.
statusSame as sc query PunktfunkHost.

See Running as a Service and Windows Host.

tray (Windows)

punktfunk-host tray start|stop|status brings the per-user status tray back after an update or a crash, without signing out. status says whether it is installed and running.

driver (Windows)

The installer manages the drivers. These remove one without uninstalling the host:

punktfunk-host driver check                # does the virtual display driver answer?
punktfunk-host driver uninstall            # the virtual display driver
punktfunk-host driver uninstall --gamepad  # the virtual gamepad driver
punktfunk-host driver uninstall --audio    # the host's virtual speaker and microphone devices

seats (Windows)

punktfunk-host seats off, run elevated, turns seats off without the service: Remote Desktop's listener and firewall rules and the shared Steam shortcuts go back to how they were before seats, and the seat listener goes. The seat accounts stay. Uninstalling runs it; while the host runs, use Profiles → Seats instead, which also stops the seats first.

web (Windows)

punktfunk-host web password prints the web console login password. Run it elevated: the file is readable by Administrators and SYSTEM only. A silent install (winget, /VERYSILENT) shows the password nowhere else.

list-monitors

Prints the physical monitors by connector name, the name PUNKTFUNK_CAPTURE_MONITOR takes to stream a real monitor. Run it inside the session you want to stream.

$ punktfunk-host list-monitors
Kwin:
  HDMI-A-1        1920x1080@60 at +0,+0    scale 1  Dell U2412M  [primary]
  DP-2            2560x1440@144 at +1920,+0  scale 1  ACME 27  [PINNED]

Tags: primary, disabled, punktfunk virtual display (one of the host's own), PINNED (the current pick).

punktfunk-host mirror-test --monitor <CONNECTOR> [--seconds N] [--cpu] captures that monitor with no client and reports the first frame, the frame count and the size. Move the mouse while it runs: a still screen produces almost no frames.

punktfunk-host anchor-test --monitor <CONNECTOR> [--width W --height H] walks the pointer to the centre and four corners of that monitor, one second apart; --none walks it unanchored for comparison. The log line libei: absolute input maps into this output names the monitor it hit. It needs the libei input backend (GNOME, or PUNKTFUNK_INPUT_BACKEND=libei).

hdr-probe and probe-compositor

Linux checks that need no client.

punktfunk-host hdr-probe
punktfunk-host probe-compositor

hdr-probe answers "why isn't my stream HDR?": a monitor in HDR mode (GNOME), a punktfunk-gamescope with HDR on, 10-bit HEVC and AV1 encode, and the verdict for each plane. Run it with the host service's environment: HDR → Check it has the command and reads the output.

probe-compositor exits 0 once the compositor is ready, so a bring-up script can wait on it instead of a sleep. It checks KWin's screencast grant and Hyprland's hyprctl; other compositors pass once detected.

On Windows, hdr-p010-selftest checks the GPU's HDR capture conversion with no display or session, and prints PASS or FAIL with the largest error:

punktfunk-host hdr-p010-selftest 1920x1080 nvidia

Both arguments are optional: your capture size (default 64x64; 1080 takes a different driver path) and, on a dual-GPU box, the encoding vendor (intel, nvidia or amd).

detect-conflicts

Lists Sunshine, Apollo and other Moonlight-compatible hosts installed on this machine. It exits 1 when one runs or starts on its own, 0 otherwise, so scripts can gate on it. Running one beside Punktfunk is unsupported: they fight over ports and the virtual display. serve runs the same check at startup. See Troubleshooting.

The client's punktfunk command

The machine you stream to has its own command, punktfunk. Its verbs and exit codes are on Clients → the punktfunk CLI; punktfunk wake is on Wake on LAN.

On this page