`defineLibraryPlugin` has taken a `launchers()` hook since kit 0.3.0 — entries that open the LAUNCHER rather than a title (design D4) — and nothing implemented it. The host has resolved `launcher_ui` valued `"heroic"` since the same release. So the whole path existed end to end with no producer at either end. One entry, config-toggled and on by default: installing, updating or logging in are exactly the things you cannot do from a game tile. `launcher_ui` is valued by STORE ID, never a command: the host resolves "heroic" to the native binary or the Flatpak, minus the `--no-gui` and the URI that game entries carry, so the window itself opens (D1). That is also the only shape available to a plugin at all — the 2026-08-05 review made `launch.kind = "command"` operator-only, so a plugin publishing one has its entire reconcile refused. CAVEAT carried in the code: Heroic is a single-instance Electron app, so if a window is ALREADY open the spawned process forwards to it and exits. The host documents the same caveat for game launches; keeping the session alive across it is a host-side question (the launcher-tile lease), not this plugin's. Deliberately art-less — see the lutris plugin: a square app icon cover-cropped into a 2:3 tile looks broken, and every client renders an art-less launcher entry as "opens Heroic" on purpose. Gates: tsc --noEmit clean, 7 tests pass (2 new), biome clean. Needs a host carrying the M2 wire (`role` + `launcher_ui`), which is on main.
@punktfunk/plugin-heroic
Adds your installed Heroic Games Launcher titles to a Punktfunk host's library — Epic, GOG and Amazon in one source, with their cover art, and with the session ending when you quit the game.
Install it from the host's plugin store (Library → Game sources → Add a source), or:
punktfunk-host plugins add heroic
Nothing to configure: it finds Heroic's config folder in the usual places ($XDG_CONFIG_HOME/heroic,
~/.config/heroic, Flatpak) and reads the library caches from there. If yours lives somewhere else,
set the path in Library → Game sources → Heroic → Settings.
What it replaces
Punktfunk used to scan Heroic from inside the host. This plugin is that scanner, lifted out — so you install it only if you use Heroic, and it can be updated without updating the host.
It claims the heroic store, which means your games keep exactly the ids they had before
(heroic:legendary:<appName>): Moonlight pins, cached box art, and your enabled/disabled state all
carry over, and the host's built-in scanner switches itself off while this is installed. Remove the
plugin and the built-in comes straight back.
What gets listed
Only titles Heroic reports as installed and whose install directory still exists — the second
check works around Heroic's GOG is_installed bug
(#2691), which otherwise
leaves uninstalled games sitting in your library.
Art comes straight from Heroic's cached CDN URLs, so the client fetches it directly. A sideloaded
title whose art is a local file:// path is listed without art rather than with a picture nothing
can load.
Commands
punktfunk-plugin-heroic detect # is Heroic installed on this host?
punktfunk-plugin-heroic scan --preview # what WOULD be synced, as JSON (works with no host)
punktfunk-plugin-heroic uninstall # drop the games and release the store claim
Parity — the release gate
Unit tests pin the parsing. What actually has to hold is that this plugin reproduces the in-host
scanner it replaces, down to the ids — one that parses perfectly but emits a subtly different
external_id breaks every Moonlight pin on the host, and no unit test notices.
So, on a box with Heroic installed, before installing this plugin:
punktfunk-plugin-heroic parity --snapshot before.json # host still on its built-in scanner
punktfunk-plugin-heroic parity --compare before.json # offline; exits non-zero on any difference
--compare runs this plugin's own scan and diffs it: ids, titles, launch recipes, roles and
metadata exactly; art by presence, not value.
Worth re-checking on-glass specifically: a game launched under Proton. Heroic hands off to
legendary/gogdl/nile, so the HEROIC_APP_NAME environment marker is what lets the host recognise
the running game and end the session when you quit it.
Do not publish a version whose parity run is red.
Development
bun install
bun run typecheck && bun test && bun run build
The framework — store claim, sync engine, __config, CLI verbs, and the launcher-file parsers —
lives in @punktfunk/plugin-kit/library.
This package is the Heroic-specific part: find the config root, read the three store_cache
libraries, map entries. See design/library-scanner-plugins.md in the main repo.
License
MIT OR Apache-2.0.