@hearthforge/plugin-sdk
v0.2.0
Published
Adapter interfaces, descriptor types and compliance tests every HearthForge game plugin implements
Maintainers
Readme
@hearthforge/plugin-sdk
The contract every HearthForge game plugin is written against. A plugin is one npm package that implements GamePlugin: seven adapters (compose, monitor, bootstrap, backup, auth, command, data), a manifest, optional modules and optional React UI. The panel and the agent know nothing about any specific game — everything game-specific lives in the plugin, and this package defines the seam. It also ships the compliance runner that checks a plugin against that seam, the build presets that produce the dist/ layout the panel loads, and the safe-command helpers (composeShell, execShell, envArg, …) that keep operator config out of shell text.
Install
pnpm add -D @hearthforge/plugin-sdk @hearthforge/shared zodNode >= 22. Most of the package is types and pure functions, so a backend-only plugin needs no React.
Usage
Implement each adapter interface directly — the SDK ships interfaces, not base classes:
import type {
ComposeAdapter,
DockerComposeConfig,
InstanceContext,
PortRequirement,
ResolvedModule,
ValidationResult,
} from "@hearthforge/plugin-sdk";
export class MyGameComposeAdapter implements ComposeAdapter {
constructor(private readonly ctx: InstanceContext) {}
generateCompose(_config: unknown, _modules: ResolvedModule[]): DockerComposeConfig {
return { services: { server: { image: "example/my-game:1.0", init: true } } };
}
getRequiredEnvVars() {
return [];
}
validateConfig(_config: unknown): ValidationResult {
return { valid: true };
}
getPortRequirements(): PortRequirement[] {
return [{ containerRole: "server", port: 7777, protocol: "tcp", description: "my-game:ports.game" }];
}
}Then hold the whole plugin to the contract in your own test suite:
import { runAdapterComplianceTests } from "@hearthforge/plugin-sdk";
import MyGamePlugin from "./index";
const result = runAdapterComplianceTests(new MyGamePlugin(), mockCtx);
if (!result.passed) {
throw new Error(result.checks.filter((c) => !c.passed).map((c) => `${c.id}: ${c.errors.join("; ")}`).join("\n"));
}mockCtx is an InstanceContext whose config your validateConfig accepts. Pass { messages, packageJson, ui } as the third argument to switch on the i18n, package-manifest and UI-registration checks.
Subpath entries: @hearthforge/plugin-sdk/schemas (zod schemas for the package manifest and registry index), @hearthforge/plugin-sdk/build (the backendConfig / uiConfig vite presets), @hearthforge/plugin-sdk/relay-channel (the browser-safe relay frame policy).
The full walkthrough — package layout, every adapter, building, modules — is the plugin-authoring guide. Start a new plugin from the plugin-template repository; @hearthforge/plugin-reference is a complete plugin to read alongside it.
Peer dependencies
| peer | range | |
|---|---|---|
| @hearthforge/shared | the matching 0.x line | required |
| zod | ^4.0.0 | required |
| react | ^18.0.0 \|\| ^19.0.0 | optional — only for a plugin that ships UI |
| @tanstack/react-query | >=5.0.0 <6 | optional — only for a plugin that ships UI |
A plugin's UI bundle never bundles React: the panel supplies its own copy through the host share scope (HOST_SHARED_MODULES), so the plugin's components run on the panel's one React. HOST_API_VERSION names the generation of that host API a bundle's register(host) is written against.
Versioning
Pre-1.0: a minor release may break the contract; a patch never does. Declare hearthforge.sdk in your package manifest as the range your plugin was built against, and the panel refuses to load a plugin outside it. Maintenance lines publish from release/X.Y branches under the release-X.Y npm dist-tag and never move latest — see Maintenance releases. Every release is listed in CHANGELOG.md.
License
Apache-2.0 — a plugin built against this contract does not inherit the panel's licence.
Links
- Repository: hearthforge/hearthforge-sdk
- Plugin-authoring guide: docs/plugin-authoring.md
- Plugin template: hearthforge/plugin-template
- Contributing: CLA.md (required for every contribution)
- HearthForge core: hearthforge/hearthforge
