acce43ebbf
- rebuild-check.sh + punktfunk-rebuild-check.service (enabled, ordered Before=punktfunk-host): ldd-probes the host binary at session start — milliseconds when healthy, a full update.sh rebuild only when a SteamOS update actually broke its library links. update.sh restarts go --no-block so the check → update.sh → restart chain can't deadlock against the unit ordering. update.sh retrofits the unit. - installer summary: web console is https (the unit serves TLS). - docs: steamos-host.md (runner in the build step, keep-list + auto rebuild = updates survive hands-free), gamescope.md (Gaming Mode touch = single-finger pointer, exact taps, no multi-touch), plugins.mdx (SteamOS runner note), scripts/steamdeck/README.md (rebuild-check, runner payload, keep list, honest packaging trade-off + the CI-prebuilt future direction). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
241 lines
10 KiB
Plaintext
241 lines
10 KiB
Plaintext
---
|
|
title: Plugins
|
|
description: First-party plugins that sync your ROM collection or your Playnite library into the game library — and how to install them.
|
|
---
|
|
|
|
Plugins extend the host through the **scripting runner** (see [Events & hooks](/docs/automation)). A
|
|
plugin runs alongside the host, reconciles titles into your **game library** as a provider — so they
|
|
appear in the grid on every client — and can add its own page to the [web console](/docs/web-console).
|
|
|
|
Two first-party plugins today:
|
|
|
|
| Plugin | What it does |
|
|
|---|---|
|
|
| **ROM Manager** | Scans your ROM directories, matches each platform to an installed emulator, and syncs them into the library with box art. |
|
|
| **Playnite** | Mirrors your [Playnite](https://playnite.link) library — every store and emulator it manages — into the library, launched back through Playnite. |
|
|
|
|
## Installing from the console
|
|
|
|
Open the [web console](/docs/web-console) → **Plugins**. The **Browse** tab lists the plugin
|
|
catalog; pick one, confirm, and the host installs it and restarts the runner for you. **Installed**
|
|
shows what you have (and switches the runner on and off), **Sources** is where the catalog comes
|
|
from.
|
|
|
|
That is the whole install. The rest of this page covers the CLI, which does the same thing, and the
|
|
trust model behind the badges — worth reading once, because a plugin runs with the same privileges
|
|
as the host.
|
|
|
|
### What "Verified" means
|
|
|
|
Every catalogued plugin pins **one exact version** and that version's package hash. A verified entry
|
|
means somebody at unom reviewed *that exact package* — not the project in general, and not whatever
|
|
it publishes next. When a plugin releases a new version, the store keeps offering the reviewed one
|
|
until the new release is reviewed too. Before anything is downloaded, the host re-checks the pinned
|
|
hash against the registry, so a package that was quietly republished under the same version number
|
|
is refused rather than installed.
|
|
|
|
Three things a plugin can be:
|
|
|
|
| Badge | Where it came from |
|
|
|---|---|
|
|
| **Verified** | The built-in catalog. unom reviewed this exact package. |
|
|
| **Unverified**, *from <source>* | A catalog **you** added. Still pinned and hash-checked, but curated by somebody else — unom has not looked at the code. |
|
|
| **Unverified** | Installed by hand from a package spec. Nobody reviewed it and nothing pins it; the console asks you to type the name to confirm, and the plugin stays marked this way for as long as it is installed. |
|
|
|
|
### Adding another catalog
|
|
|
|
**Sources** → *Add a catalog source*: a name and the URL of its index. Optionally paste the source's
|
|
`ed25519:…` public key — with a key set, the host refuses any index from that source that isn't
|
|
correctly signed, rather than falling back to an unsigned one.
|
|
|
|
Adding a source is a trust decision you make once: its plugins become installable on this host.
|
|
They are always attributed to it and never carry the Verified badge, which belongs to the built-in
|
|
catalog alone.
|
|
|
|
To publish a plugin to the built-in catalog, open a pull request against
|
|
[`punktfunk-plugin-index`](https://git.unom.io/unom/punktfunk-plugin-index) — its README covers the
|
|
format and what review looks for.
|
|
|
|
## Installing from the CLI
|
|
|
|
Two commands: install the plugin, then turn the runner on. The host CLI handles the rest — creating
|
|
the plugins directory, pointing it at the package registry, and starting the supervisor.
|
|
|
|
<Tabs items={['Linux', 'Windows']}>
|
|
<Tab value="Linux">
|
|
|
|
```sh
|
|
punktfunk-host plugins add playnite # or: rom-manager
|
|
punktfunk-host plugins enable # turn the runner on (once)
|
|
```
|
|
|
|
On **SteamOS** the [host installer](/docs/steamos-host) ships the runner automatically (user-scoped
|
|
under `~/.local` — the read-only `/usr` can't take the package). If the console reports the runner
|
|
isn't installed on an older setup, re-run `scripts/steamdeck/update.sh` once.
|
|
|
|
</Tab>
|
|
<Tab value="Windows">
|
|
|
|
Run these from an **elevated** PowerShell — right-click **PowerShell** → **Run as administrator**.
|
|
The plugins directory lives under `%ProgramData%\punktfunk`, which is admin-owned. The runner task
|
|
itself runs as the low-privilege `NT AUTHORITY\LocalService` account — `plugins enable` sets that
|
|
up (including read access to the runner's scoped API token).
|
|
|
|
```powershell
|
|
punktfunk-host plugins add playnite # or: rom-manager
|
|
punktfunk-host plugins enable # turn the runner on (once)
|
|
```
|
|
|
|
If `punktfunk-host` isn't found, open a **new** terminal (the installer adds it to `PATH`), or use
|
|
the full path: `& "$env:ProgramFiles\punktfunk\punktfunk-host.exe" plugins add playnite`.
|
|
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
Open the [web console](/docs/web-console) and the plugin's page appears in the nav automatically —
|
|
that's the whole install.
|
|
|
|
The runner is **opt-in**: `plugins add` installs, `plugins enable` turns it on. You only need
|
|
`enable` once. The runner discovers plugins when it starts, so one installed later needs a restart
|
|
to come up (`systemctl --user restart punktfunk-scripting`, or `Restart` the `PunktfunkScripting`
|
|
task) — the console does that restart for you as part of installing.
|
|
|
|
A plugin installed from the CLI shows up in the console as **Installed via CLI**: the console knows
|
|
what is installed, but not who vouched for it. Install the same plugin from the store's Browse tab
|
|
and it carries its catalog badge instead.
|
|
|
|
### The rest of the commands
|
|
|
|
| Command | What it does |
|
|
|---|---|
|
|
| `punktfunk-host plugins add <name…>` | Install one or more plugins. |
|
|
| `punktfunk-host plugins remove <name…>` | Uninstall. |
|
|
| `punktfunk-host plugins list` | List what's installed, with versions. |
|
|
| `punktfunk-host plugins enable` | Enable + start the runner. |
|
|
| `punktfunk-host plugins disable` | Stop + disable the runner. |
|
|
| `punktfunk-host plugins status` | Is the runner enabled and running? |
|
|
|
|
A bare name resolves to the first-party package — `playnite` installs `@punktfunk/plugin-playnite`,
|
|
always from Punktfunk's own package registry. Any other name (`punktfunk-plugin-*`, a foreign
|
|
`@scope/pkg`) would install from the **public npm registry** and is refused unless you add
|
|
`--allow-public-registry` — a guard against typos and look-alike packages pulling untrusted code
|
|
onto your host.
|
|
|
|
> Plugins are operator-installed code with operator privileges — they can launch games and run
|
|
> commands. Install only plugins you trust, from a registry you control.
|
|
|
|
## ROM Manager
|
|
|
|
`@punktfunk/plugin-rom-manager` — point it at your ROM directories and it scans them, matches each
|
|
platform to an installed emulator, fetches box art (SteamGridDB, or the keyless libretro thumbnails),
|
|
and reconciles the result into your library as the `rom-manager` provider. ~25 built-in platforms
|
|
(NES through Switch, PS1/2/PSP, Dreamcast, and more), per-game overrides, and a console page to
|
|
configure it all.
|
|
|
|
```sh
|
|
punktfunk-host plugins add rom-manager
|
|
```
|
|
|
|
Then add a root or two — from the console's **ROM Manager** page, or in the config file:
|
|
|
|
<Tabs items={['Linux', 'Windows']}>
|
|
<Tab value="Linux">
|
|
|
|
`~/.config/punktfunk/rom-manager/config.json`:
|
|
|
|
```jsonc
|
|
{
|
|
"roots": [
|
|
{ "dir": "/mnt/roms/snes", "platform": "snes" },
|
|
{ "dir": "/mnt/roms/ps1", "platform": "ps1", "excludes": ["*.sav"] }
|
|
],
|
|
"art": { "provider": "auto", "steamGridDbKey": "" }
|
|
}
|
|
```
|
|
|
|
</Tab>
|
|
<Tab value="Windows">
|
|
|
|
`%ProgramData%\punktfunk\rom-manager\config.json`:
|
|
|
|
```jsonc
|
|
{
|
|
"roots": [
|
|
{ "dir": "D:\\roms\\snes", "platform": "snes" },
|
|
{ "dir": "D:\\roms\\ps1", "platform": "ps1", "excludes": ["*.sav"] }
|
|
],
|
|
"art": { "provider": "auto", "steamGridDbKey": "" }
|
|
}
|
|
```
|
|
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
Full options and the platform/emulator list are in
|
|
[the plugin's repo](https://git.unom.io/unom/punktfunk-plugin-rom-manager).
|
|
|
|
## Playnite
|
|
|
|
`@punktfunk/plugin-playnite` — mirrors your **[Playnite](https://playnite.link)** library (Steam,
|
|
GOG, Epic, Xbox, itch, emulators, manually-added games — everything Playnite manages) into your
|
|
library. Launching a title hands it back to Playnite, which performs the real launch, so there are no
|
|
per-store launch commands to maintain. Covers are served by the host, so it scales to large libraries.
|
|
|
|
Playnite is Windows-only, so both halves of this one live on the **Windows host**. Because Playnite
|
|
keeps its library locked while running, there are **two parts**:
|
|
|
|
1. **The plugin** — from an elevated PowerShell:
|
|
|
|
```powershell
|
|
punktfunk-host plugins add playnite
|
|
punktfunk-host plugins enable
|
|
```
|
|
|
|
2. **The Punktfunk Sync extension** (in Playnite) — download `punktfunk-sync.pext` from the
|
|
[plugin's builds](https://git.unom.io/unom/punktfunk-plugin-playnite/actions) and **double-click
|
|
it** to install it in Playnite like any add-on, then restart Playnite once.
|
|
|
|
Open the console's **Playnite** page — it shows "Exporter connected", and your games sync within
|
|
seconds of any library change. Filters (installed-only, per-store, hidden) live on that page or in
|
|
`%ProgramData%\punktfunk\playnite\config.json`. Details are in
|
|
[the plugin's repo](https://git.unom.io/unom/punktfunk-plugin-playnite).
|
|
|
|
## Troubleshooting
|
|
|
|
**`punktfunk-host: command not found`** — on Windows, open a new terminal so it picks up the
|
|
installer's `PATH` change, or call the exe by full path. On Linux the host package installs it to
|
|
`/usr/bin/punktfunk-host`.
|
|
|
|
**"the plugin runner isn't installed"** — the runner ships as its own package. On Debian/Ubuntu:
|
|
`sudo apt install punktfunk-scripting`. On Windows, re-run the installer and keep the scripting
|
|
component.
|
|
|
|
**The plugin doesn't show up in the console** — check the runner is actually running with
|
|
`punktfunk-host plugins status`, then look at its log:
|
|
|
|
<Tabs items={['Linux', 'Windows']}>
|
|
<Tab value="Linux">
|
|
|
|
```sh
|
|
journalctl --user -u punktfunk-scripting -f
|
|
```
|
|
|
|
</Tab>
|
|
<Tab value="Windows">
|
|
|
|
The runner task doesn't write a log file, so run it in the foreground to watch it start your
|
|
plugins (stop it with <kbd>Ctrl</kbd>+<kbd>C</kbd>):
|
|
|
|
```powershell
|
|
& "$env:ProgramFiles\punktfunk\bun\bun.exe" "$env:ProgramFiles\punktfunk\scripting\runner-cli.js"
|
|
```
|
|
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
## Writing your own
|
|
|
|
A plugin is a small TypeScript module built on `@punktfunk/host` (`definePlugin`), supervised by the
|
|
runner. Start from the [SDK README](https://git.unom.io/unom/punktfunk/src/branch/main/sdk) — or the
|
|
two plugins above, which are worked examples of the same shape.
|