Files
punktfunk-plugin-playnite/exporter
enricobuehler e832201669
CI / publish (push) Successful in 17s
CI / exporter (push) Successful in 11s
CI / build (push) Successful in 20s
fix: read/write the library via the host ingest inbox (de-privileged runner)
The host plugin runner is de-privileged now (LocalService) and can't read the
interactive user's %APPDATA%\Playnite\ExtensionsData — so it never saw the
export. Bridge it through the host's user-writable ingest inbox:

- exporter (C#): also drop punktfunk-library.json into
  %ProgramData%\punktfunk\ingest\playnite (best-effort, only when a punktfunk
  host is present), alongside its ExtensionsData home.
- plugin (TS): locateExport() reads <config_dir>/ingest/playnite first, then
  falls back to the ExtensionsData scan (same-user/SYSTEM runner, Linux). The
  watcher also watches the inbox so a drop reconciles within seconds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-20 00:40:28 +02:00
..

Punktfunk Sync — Playnite exporter

The Playnite side of @punktfunk/plugin-playnite: a minimal GenericPlugin that writes your library to punktfunk-library.json whenever it changes. The Punktfunk plugin on the host reads that file and reconciles it into the streaming library.

It exists because Playnite keeps its library database (LiteDB) open and locked while running, so the only robust way to read the library — with correct install state, art paths and metadata — is from inside Playnite. This plugin does exactly that and nothing else: no network, no settings, no UI.

What it writes

On startup, on every OnLibraryUpdated, and (debounced) on any per-game add/update/remove, it writes:

%APPDATA%\Playnite\ExtensionsData\<plugin-guid>\punktfunk-library.json

Shape (kept in lockstep with ../src/export-schema.ts):

{
  "schema": 1,
  "generatedAt": "2026-07-18T21:00:00Z",
  "playnite": { "version": "10.x", "mode": "Desktop" },
  "games": [
    {
      "id": "e3b0c442-98fc-1c14-9afb-4c8996fb9242",  // Playnite Guid = reconcile external_id
      "name": "Hollow Knight",
      "installed": true,
      "hidden": false,
      "source": "Steam",
      "platforms": ["PC (Windows)"],
      "cover": "C:\\Users\\me\\AppData\\Roaming\\Playnite\\library\\files\\ab\\cover.jpg",
      "background": null,
      "icon": null
    }
  ]
}

Art paths are absolute (resolved via IPlayniteAPI.Database.GetFullFilePath). Filtering (installed-only, hidden, per-source) happens on the Punktfunk side, so the export is the full library.

You can also trigger a write by hand: Playnite main menu → Punktfunk Sync → Export library to Punktfunk now.

Install (for users)

Double-click punktfunk-sync.pext — Playnite installs it like any add-on — and restart Playnite. Grab the .pext from the repo's CI artifacts.

Build

Targets .NET Framework 4.6.2 (Playnite's runtime). Thanks to Microsoft.NETFramework.ReferenceAssemblies it builds with the plain .NET SDK on any OS — no Windows or MSBuild needed:

dotnet build PunktfunkSync.csproj -c Release
# output: bin/Release/PunktfunkSync.dll + extension.yaml (PlayniteSDK.dll is provided by Playnite)

Package the .pext (a zip of the two files):

( cd bin/Release && zip -j ../../punktfunk-sync.pext extension.yaml PunktfunkSync.dll )