unom

Software development

Baden-Württemberg

@punktfunk/plugin-heroic (0.2.0)

Published 2026-08-26 17:56:30 +00:00 by enricobuehler in unom/punktfunk-plugin-heroic

Installation

@punktfunk:registry=https://git.unom.io/api/packages/unom/npm/
npm install @punktfunk/plugin-heroic@0.2.0
"@punktfunk/plugin-heroic": "0.2.0"

About this package

Punktfunk plugin: adds your installed Heroic Games Launcher titles (Epic, GOG, Amazon) to the host's library, with their cover art.

@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 the host's own scanner gave them (heroic:legendary:<appName>): Moonlight pins, cached box art, and your enabled/disabled state all carry over. Hosts through v0.27.x also had the scanner compiled in and switched it off while this plugin was installed; from v0.28.0 the built-ins are gone and this plugin is the only way to get Heroic titles into the library.

What gets listed

Titles Heroic has installed, whose install directory still exists. The directory check works around Heroic's GOG is_installed bug (#2691) and prunes a library cache that has gone stale, either of which would otherwise leave uninstalled games sitting in your library.

Where "installed" is read from matters, and getting it wrong is what made this plugin list Epic titles and nothing else before v0.2.0. Heroic keeps two files per backend:

library cache (store_cache/…) installed state
Epic (legendary) every owned title + art; install state baked in on refresh legendaryConfig/legendary/installed.json
GOG every owned title + art; install state deliberately stripped out gog_store/installed.json
Amazon (nile) every owned title + art; install state baked in on refresh nile_config/nile/installed.json

Heroic writes the GOG cache from a copy with the install data removed on purpose and merges the real state back in when it reads it, so every GOG row on disk says is_installed: false. A scan that believed the cache dropped your whole GOG library. Epic and Amazon do bake it in, but only when a full library refresh rewrites the file — installing a game leaves the cache stale until then. So this plugin takes each runner's own installed.json as the authority and uses the cache for the title and the art, which also means a game you just installed appears without waiting for Heroic to refresh.

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.

Heroic's sideloaded titles are not listed. They live in a different file again (sideload_apps/library.json) and record an executable rather than an install directory, and the host's heroic launch kind does not accept a sideload runner — so listing them would only produce tiles that refuse to start.

The launcher tiles

Two tiles open Heroic itself rather than a game, both on by default and each switchable in Library → Game sources → Heroic → Settings:

  • Heroic Console Mode — Heroic's fullscreen gamepad UI, the one worth having on a stream. Needs Heroic 2.21 or newer; an older Heroic ignores the flag and opens fullscreen on the normal UI.
  • Heroic — the ordinary window.

The host builds both command lines; the plugin only names which UI to open. Console mode in particular needs two flags (--console routes the UI, --fullscreen fills the screen) and cannot be reached through a heroic:// URI at all, which is why that knowledge lives in the host.

Packaging note. The console tile publishes launch.value = "heroic-console", which a host older than the release that added it refuses — and a refused reconcile takes the whole batch with it. The plugin index entry for any version from 0.2.0 on must carry a minHost at or above that release.

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 an upgrade does not silently change 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.

parity --snapshot captures the host's CURRENT library for the heroic store — whatever produced it. So, on a box with Heroic installed, snapshot with the old version still running, upgrade, then compare:

punktfunk-plugin-heroic parity --snapshot before.json   # host still on the previous version
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.

Read the 0.2.0 diff rather than requiring it to be empty — it is expected to be non-empty, and the additions are the point: every GOG title, every Amazon title, and the new heroic:console tile. What must NOT appear is a changed or removed heroic:legendary:* id.

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. And the console tile itself — that it opens Heroic's gamepad UI fullscreen, on both a native and a Flatpak Heroic.

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 and the three installed.json files behind them, map entries. See design/library-scanner-plugins.md in the main repo.

License

MIT OR Apache-2.0.

Dependencies

Dependencies

ID Version
@punktfunk/plugin-kit ^0.4.4
effect 4.0.0-beta.99

Development Dependencies

ID Version
@biomejs/biome ^2.5.2
@types/bun ^1.3.0
typescript ^5.9.3

Keywords

punktfunk plugin heroic epic gog game-library game-streaming
Details
npm
2026-08-26 17:56:30 +00:00
28
MIT OR Apache-2.0
latest
5.2 KiB
Assets (1)
Versions (3) View all
0.2.0 2026-08-26
0.1.1 2026-08-12
0.1.0 2026-08-06