Files
punktfunk/docs-site/content/docs/profiles-and-links.md
T
enricobuehler ac5299d4ce docs: the Deck plugin is a launcher now, not a second client
The plugin's settings tab, fullscreen page, host editor and games picker are gone, and the
docs described all four in detail. Sweeps clients/decky/README.md and the docs site.

steam-deck.md gains a **Request access** section — the no-PIN path where the host's operator
approves the Deck, which is the one genuinely new thing a user gets — and says plainly where
the settings went: **Open Punktfunk → Settings**, the same rows over the same store, one tap
from the same panel. A removal that reads as a regression is worth a sentence, not a silence.
The troubleshooting table drops the rows for surfaces that no longer exist and gains the two
questions the new path will actually raise ("request access isn't offered", "the stream just
sits there").

client-settings.md claimed ~18 settings were "offered by … and Decky". None are; the console
home offers them. Its intro now names the console home's real sections (Stream, Video,
Presentation, Audio, Controller, Touchscreen, Interface, Profiles) instead of describing the
deleted sidebar.

Three claims in that file turned out to be wrong ALREADY, independent of this rework, and are
fixed here because verifying against crates/pf-console-ui/src/screens/settings.rs is what
found them:

  • "Render scale — offered everywhere except the console home's list". RowId::RenderScale has
    been in the console's ROWS since 2026-07-31.
  • wake-on-lan.md: "Punktfunk Console has no auto-wake setting of its own". It does —
    RowId::AutoWake, "Wake hosts automatically". Its Wake & Connect BUTTON is independent of
    the setting, which is the true half that sentence was built on.
  • The console home's Library button was documented as gated on the "Show game library"
    toggle. It isn't — `library_enabled` appears nowhere in pf-console-ui outside the toggle
    row itself; home.rs offers Library on any paired, saved host.

Also updated: support-matrix (Decky's Profiles and Game library go /⚠️ — the panel shows
pinned profile cards but creates none, and the library lives in the console home),
wake-on-lan (the plugin no longer fires its own packet or stretches the connect budget — the
CLI runs the real wake-and-wait), pairing, game-library, profiles-and-links, input, clipboard
and install-client.
2026-08-04 20:58:11 +02:00

196 lines
11 KiB
Markdown

---
title: Profiles and links
description: How settings profiles override your client defaults per host or per connect, and how punktfunk:// links start a stream from a shortcut, a script or a browser.
---
Two features that landed together in 0.22.0 and work with each other: **settings profiles**, named
bundles of stream settings you can attach to a host, and **`punktfunk://` links**, URLs that start a
stream you have already set up.
Both live in the client apps — the Apple app, the Linux GTK client, the Windows client and the
Android app. Neither exists in the host's [web console](/docs/web-console).
The controller-driven surfaces are a half-exception: Apple TV, the Android app's console mode and
the Steam Deck console the Decky plugin launches all *use* the profile a host is bound to and can
pin one as its own card, but none of them can create or edit one. Do that on a desktop or a phone
first. The Decky panel itself only *shows* those pins, nested under their host as one-tap cards.
## What a profile is
A profile is a *sparse* set of overrides on top of your normal client settings. Only the rows you
actually touch are stored. Everything else keeps following your defaults **live**, so changing a
default later also moves every profile that never overrode it.
Touching a row records the override even when you pick the value the default already has. That is a
deliberate *pin*: the profile keeps that value when the default later moves. The only way back to
inheriting is the row's explicit **Reset**.
Where the catalog is kept:
| Client | Stored in |
|---|---|
| Linux | `~/.config/punktfunk/client-profiles.json` |
| Windows | `%APPDATA%\punktfunk\client-profiles.json` |
| Apple | the app-group store, beside your saved hosts |
| Android | app-private storage |
The catalog is per device, and nothing syncs it, so a profile you make on your laptop doesn't appear
on your phone.
## Creating and editing one
Profiles are created and edited in the client's own **Settings** screen — there is no second editor,
so a profile can never drift from the surface it overrides.
1. Open Settings. At the top is a scope switcher listing **Default settings**, your profiles, and a
**New profile** entry. Linux, Windows and iOS label the control **Editing**; macOS heads the
preferences window with the layer's name; Android shows the choices as a row of chips.
2. Create a new profile. Linux, Apple and Android ask for a name (and a colour) first; Windows
creates one called *Profile 1* and opens its edit sheet, where you rename it. Names must be
unique, ignoring case.
3. Change the rows you want. Every row shows the *effective* value — the inherited default until you
touch it.
4. A row you have overridden grows a marker and a **Reset** control. Reset drops that one override
and puts the row back to following your defaults.
Each profile can carry a colour from a small preset palette (the exact swatches differ slightly
between apps). It tints the profile's chip on host cards, so a grid of hosts is readable at a
glance.
Renaming, duplicating (overrides and colour included) and deleting sit next to the switcher on
Linux and in the same menu on Apple. Windows puts them in the sheet the switcher's **Edit** entry
opens; Android puts them on the selected profile's own chip — tap it a second time.
While a stream runs with a profile, the profile's name closes the first line of the
[stats overlay](/docs/stats) — on the Apple client, from the Normal tier up.
## What a profile can't change
In profile scope, rows that aren't profileable simply don't render. They are facts about *this
device* — the video decoder and GPU it uses, its audio endpoints, which physical controller you
hold, whether it wakes hosts on connect and whether it shows a game library — not about how you
want a stream to look. **Share clipboard** is out for the neighbouring reason: it's a per-host trust
decision stored on the host record rather than a client setting at all — see
[Clipboard](/docs/clipboard).
The row-by-row list, and why each row stays global, is on
[Client settings](/docs/client-settings#settings-that-are-facts-about-your-device).
## Three ways to use a profile
**Bind it to a host.** Open a saved host's edit sheet and set **Profile**. Every plain click on that
host's card now uses it. This is the only sticky choice. (The Apple app also offers **Connect with ▸
Set Default Profile** on the card itself.)
**Use it once.** A card's menu has **Connect with** — pick a profile for this connect only. It never
rebinds the host. **Default settings** in that menu is a real choice: on a bound host it forces your
globals for one session. (Android lists the same choices flat, as *Connect with: …*.)
**Pin it as its own card.** A pinned profile gets its own card beside the host — one click, no menu.
Pin it in the host's edit sheet on Linux, Android and Apple, or from a card menu: **Pin as Card** on
Apple, **Pin as card: …** on Android, **Pin tiles** on Windows. A pinned card is a shortcut, not a
second host: unpinning changes neither the profile nor the host's binding.
## Deleting a profile
The confirmation tells you what breaks: how many hosts will fall back to **Default settings**, and
how many pinned cards will disappear. Bindings and pins are deliberately left pointing at the gone
profile rather than rewritten; everywhere they are read, a dangling reference resolves as "no
profile", which is exactly your defaults. Nothing errors and no connect is blocked.
## `punktfunk://` links
A link starts a stream on a host this device already trusts. All four apps register the scheme with
the operating system, so a link works from a browser (behind the browser's own "open this app?"
prompt), a desktop shortcut, a home-automation rule or a script:
```text
punktfunk://connect/<host-ref>[?fp=<64-hex>][&host=<addr[:port]>][&launch=<id>][&profile=<ref>][&name=<label>]
```
`<host-ref>` is a saved host's stable record id, its name (unique, ignoring case), or `addr[:port]`.
Resolution goes in that order, and a name matching two saved hosts is refused rather than guessed.
| Parameter | Means |
|---|---|
| `fp` | the host certificate fingerprint the link expects — 64 hex characters |
| `host` | `addr[:port]` to fall back on when the reference no longer resolves; port defaults to `9777` |
| `launch` | a store-qualified [library](/docs/game-library) id such as `steam:570`, launched on arrival |
| `profile` | a settings profile, by id or unique name — for this connect only |
| `name` | a display label, shown as *claimed*, never trusted |
The scheme and the route word are case-insensitive, a trailing slash is fine, a `#fragment` is
dropped, unknown parameters are ignored, an empty value means "not given", and if a parameter
appears twice the first one wins. `pf://` parses as an input alias, but nothing emits it and no app
registers it with the operating system, so write `punktfunk://`.
`connect` is the only route any client acts on today; `wake` and `browse` parse, but every client
answers them with a notice. Values are capped (2048 for the whole URL, 128 for the host reference
and `launch`, 64 for `profile` and `name`), and `launch` must be printable ASCII with no spaces,
quotes, backslashes, `$` or backticks.
Worked examples:
```text
punktfunk://connect/Living%20Room%20PC
punktfunk://connect/Living%20Room%20PC?launch=steam:570
punktfunk://connect/Living%20Room%20PC?profile=Work
```
## What a link can and can't do
The rule the grammar exists to keep: **a link may only do what clicking a card you already have
could do, minus every trust decision.**
- It carries *references*, never values. There is no resolution, bitrate, codec or HDR parameter,
so a web page cannot shape your session beyond choosing among your own configurations.
- There is no `pair` route and never will be. `punktfunk://pair/...` is refused outright;
[pairing](/docs/pairing) stays something you do with the fingerprint on screen.
- A link naming a host you don't know is never connected. When it carries an address — as
`<host-ref>` or as `host=` — Linux and Android open the app's normal trust prompt, pre-filled with
that address and any `fp` the link carried, so the first connect is verified rather than blind.
Windows and the Apple apps show a notice naming the host instead, and you pair from the host list
yourself. A link with no address to fall back on — a bare name or a stale record id — is simply
refused with a notice.
- If the link's `fp` contradicts the fingerprint already pinned for that host, it is a hard refusal
with a notice. Nothing connects.
- A `profile=` that names nothing on this device, or two profiles at once, refuses **before**
anything is dialled — a shortcut that can't honour its profile says so rather than streaming with
the wrong settings. A link with no `profile=` honours the host's binding, exactly like a click.
- A link never preempts a running session. Linux and Windows say "A session is already running — end
it first". Apple and Android do the same, except when the link points at the host you are already
streaming, which just brings the app forward.
## Getting a link, and making a shortcut
On Linux and Windows a host card's menu has **Copy link** and **Create shortcut…**. On macOS and iOS
the card menu has **Copy Link** (tvOS has no clipboard, so it isn't offered; the Android app has no
copy action yet).
On Linux and Apple a pinned card has its own menu, and the link it hands out carries that card's
profile. Windows pinned tiles have no menu, and neither Windows action adds a `profile=`, so a
Windows link always uses the host's binding until you edit the URL yourself.
A copied link carries the host's stable record id, plus `host=` and `fp=` (the fingerprint only when
one is pinned). That is what keeps a shortcut written today working after the host changes address
or you reinstall the client.
**Create shortcut…** writes a launcher wrapped around that URL:
- **Linux** — a desktop entry in `~/.local/share/applications/`, which shows up in your app menu.
Under Flatpak the sandbox can't write there, so the app offers you the URL to place yourself.
- **Windows** — a `.lnk` on your Desktop that runs `punktfunk-client.exe` with the URL as its
argument, so it keeps working across updates.
Any other launcher works too, as long as it hands the URL to the client. From a script, or on a
headless box, use the `punktfunk` CLI:
```bash
punktfunk profiles list # ids, names, how many settings each overrides
punktfunk open 'punktfunk://connect/Desk?profile=Work'
```
It ships in the Linux client packages and in the Windows MSIX. The Flatpak build has it too, but
inside the sandbox — reach it with `flatpak run --command=punktfunk io.unom.Punktfunk`. See
[Clients](/docs/clients) for the rest of its verbs.