punktfunkpunktfunk

Plugins

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). 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.

Two first-party plugins today:

PluginWhat it does
ROM ManagerScans your ROM directories, matches each platform to an installed emulator, and syncs them into the library with box art.
PlayniteMirrors your Playnite library — every store and emulator it manages — into the library, launched back through Playnite.

Installing from the console

Open the web consolePlugins. 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:

BadgeWhere it came from
VerifiedThe 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.
UnverifiedInstalled 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

SourcesAdd 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 — 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.

punktfunk-host plugins add playnite     # or: rom-manager
punktfunk-host plugins enable           # turn the runner on (once)

On SteamOS the host installer 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.

Run these from an elevated PowerShell — right-click PowerShellRun 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).

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.

Open the 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

CommandWhat it does
punktfunk-host plugins add <name…>Install one or more plugins.
punktfunk-host plugins remove <name…>Uninstall.
punktfunk-host plugins listList what's installed, with versions.
punktfunk-host plugins enableEnable + start the runner.
punktfunk-host plugins disableStop + disable the runner.
punktfunk-host plugins statusIs 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.

punktfunk-host plugins add rom-manager

Then add a root or two — from the console's ROM Manager page, or in the config file:

~/.config/punktfunk/rom-manager/config.json:

{
  "roots": [
    { "dir": "/mnt/roms/snes", "platform": "snes" },
    { "dir": "/mnt/roms/ps1", "platform": "ps1", "excludes": ["*.sav"] }
  ],
  "art": { "provider": "auto", "steamGridDbKey": "" }
}

%ProgramData%\punktfunk\rom-manager\config.json:

{
  "roots": [
    { "dir": "D:\\roms\\snes", "platform": "snes" },
    { "dir": "D:\\roms\\ps1", "platform": "ps1", "excludes": ["*.sav"] }
  ],
  "art": { "provider": "auto", "steamGridDbKey": "" }
}

Full options and the platform/emulator list are in the plugin's repo.

Playnite

@punktfunk/plugin-playnite — mirrors your Playnite 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:

    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 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.

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:

journalctl --user -u punktfunk-scripting -f

The runner task doesn't write a log file, so run it in the foreground to watch it start your plugins (stop it with Ctrl+C):

& "$env:ProgramFiles\punktfunk\bun\bun.exe" "$env:ProgramFiles\punktfunk\scripting\runner-cli.js"

Writing your own

A plugin is a small TypeScript module built on @punktfunk/host (definePlugin), supervised by the runner. Start from the SDK README — or the two plugins above, which are worked examples of the same shape.

On this page