Skip to content

Manifest & capabilities ​

The manifest (plugin.json) is read before your module is imported — it is the contract that decides whether your code runs at all.

json
{
	"id": "org.example.hello",
	"name": "Hello",
	"version": "1.0.0",
	"description": "Says hello.",
	"homepage": "https://github.com/you/hello-plugin",
	"license": "GPL-3.0",
	"entry": "./index.ts",
	"capabilities": ["jobs", "httpRoute", "mediaRead"]
}

Point it at the TypeScript source; bun run build-catalog bundles it and rewrites the path to the emitted .js file in the package.

Fields ​

FieldMeaning
idUnique identifier, reverse-domain style (e.g. org.reelvault.tmdb). Only [A-Za-z0-9._-].
name / versionDisplay name and your plugin's semver.
entryModule path (relative to the plugin dir) that default-exports the plugin object.
capabilitiesWhat the plugin uses from the host. Verified at runtime — touching an undeclared capability aborts loading immediately.
description / homepage / licenseMetadata for catalogs and the admin UI.

That is the whole manifest. Configuration lives next to your code (see Configuration) and the plugin's UI is described in ui.json.

Capabilities ​

Capabilities are the only access gate: every host.* call asserts the matching capability the first time it runs. Declaring the capability in plugin.json is therefore mandatory — using an undeclared one aborts loading with an error naming it.

CapabilityUnlocks
metadataProviderhost.providers.register — serve metadata to the server
providerAccesshost.providers.list/search/getDetails/… — consume other plugins' providers
subtitleProviderhost.subtitles.register
mediaAnalyzerhost.media.registerAnalyzer — derive source/edition/quality tags
mediaReadhost.media.get/getRevision/listEpisodeFilesBySeason/listAllMediaFiles
metadataReadhost.metadata.get/findByExternalId/findManyByExternalIds
artifactsReadhost.artifacts.list
artifactsWritehost.artifacts.write/deleteByKind
ffmpegRunhost.ffmpeg.runAnalyse/extractFrame/extractSprite
markershost.markers — intro/credits/recap markers
jobshost.jobs and host.tasks — queue work and cron-style tasks
eventHandlerhost.events.on, host.hooks.*, host.realtime.*
storagehost.storage — per-plugin KV + blobs
httpRoutehost.routes.register — expose endpoints under /v1/plugins/<id>/*
accessPolicyhost.access.register — veto stream playback
notificationhost.notifications.create
httpFetchhost.http.fetch — outbound HTTP

Declare the narrowest set you can get away with. Capabilities are shown to the administrator when the plugin is installed, and enforced at runtime.

In practice ​

Add the capability to plugin.json before you call the matching host.* API. The abort happens on the first call, and the error names the capability — so declaring upfront is easier than debugging the abort after the fact.

Released under the GNU GPL v3.