Extensions are distributed as .beepkg packages — a zip archive with a manifest.json at its root — and managed by ExtensionPackageManager, which installs, updates, and removes them.

Package Manifest

FieldRequiredNotes
id, name, versionyesVersion must be a semantic version
author, description, tagsnoUsed for search and display
minHostVersionnoInstall refuses to run the extension on an older host
dependenciesnoOther extension ids that must already be installed

Building a Package

var manifest = new ExtensionManifest
{
    Id = "acme.gauge",
    Name = "Acme Gauge",
    Version = "1.2.0",
    MinHostVersion = "1.0.0",
    Tags = { "gauge", "dashboard" }
};

var package = ExtensionPackageBuilder.Build("bin/Release/net10.0", manifest, "acme.gauge-1.2.0.beepkg");
Console.WriteLine($"{package.SizeBytes} bytes, sha256 {package.Sha256}");

Registry

LocalExtensionRegistry indexes a folder of packages and supports text and tag search, latest-version lookup, and download. It is the offline default; a hosted registry implements the same IExtensionRegistry interface.

var registry = new LocalExtensionRegistry(@"C:\packages");
foreach (var package in registry.Search("gauge"))
    Console.WriteLine($"{package.Id} {package.Version}");

var latest = registry.GetPackage("acme.gauge");   // newest version

Install, Update, Uninstall

var manager = new ExtensionPackageManager(installRoot, registry);

var installed = manager.InstallFromRegistry("acme.gauge");          // newest version
var updated   = manager.Update("acme.gauge");                       // only when newer exists
manager.Uninstall("acme.gauge");

foreach (var directory in manager.GetLoadDirectories())             // feed these to SkiaExtensionHost
    Console.WriteLine(directory);

Each extension is installed under <root>/<id>/<version> and the active version is tracked in installed.json, which survives restarts. Failed operations are reported as results with a message — and a rejected install leaves no partial state behind.

Safety

  • Zip-slip protection — entries that would extract outside the install folder are rejected.
  • Decompression-bomb limits — per-entry size, total uncompressed size and entry count are capped (configurable).
  • Version gates — minimum host version and dependencies are checked before extracting anything.
  • Integrity — every package exposes its SHA-256 hash for verification.

Package and Registry Types

The marketplace API works with these records. They describe a package before install, an installed extension afterwards, and the log of install operations.

ExtensionPackage

An extension package: manifest plus its source archive.

MemberKindDescription
ExtensionManifest ManifestPropertyGets or sets the manifest.
string PackagePathPropertyGets or sets the package path.
long SizeBytesPropertyGets or sets the size bytes.
string Sha256PropertyGets or sets the sha256.
string IdPropertyGets or sets the id.
string NamePropertyGets or sets the name.
string VersionPropertyGets or sets the version.
override string ToString()Method

InstalledExtension

An extension installed into the local install root.

MemberKindDescription
string IdPropertyGets or sets the id.
string NamePropertyGets or sets the name.
string VersionPropertyGets or sets the version.
string InstallPathPropertyGets or sets the install path.
DateTime InstalledAtPropertyGets or sets the installed at.
bool EnabledPropertyGets or sets the enabled.
override string ToString()Method

InstallLogEntry

A single line in the package-manager operation log.

MemberKindDescription
DateTime TimestampPropertyGets or sets the timestamp.
string ActionPropertyGets or sets the action.
string DetailPropertyGets or sets the detail.
bool SuccessPropertyGets or sets the success.
override string ToString()Method

SemanticVersion

Minimal semantic version (major.minor.patch with optional prerelease/build), used for extension and host version checks.

MemberKindDescription
SemanticVersion(int major, int minor = 0, int patch = 0, string prerelease = null)Method
int MajorPropertyGets or sets the major.
int MinorPropertyGets or sets the minor.
int PatchPropertyGets or sets the patch.
string PrereleasePropertyGets or sets the prerelease.
bool IsPrereleasePropertyGets or sets the is prerelease.
static bool TryParse(string text, out SemanticVersion version)Method
static SemanticVersion Parse(string text)Method
int CompareTo(SemanticVersion other)Method
bool Equals(SemanticVersion other)Method
override bool Equals(object obj)Method
override int GetHashCode()Method
override string ToString()Method
static bool operator >(SemanticVersion left, SemanticVersion right)Method
static bool operator <(SemanticVersion left, SemanticVersion right)Method
static bool operator >=(SemanticVersion left, SemanticVersion right)Method
static bool operator <=(SemanticVersion left, SemanticVersion right)Method

LoadedExtension

Result of loading one extension.

MemberKindDescription
ISkiaExtension ExtensionPropertyGets or sets the extension.
string IdPropertyGets or sets the id.
string NamePropertyGets or sets the name.
string VersionPropertyGets or sets the version.
string DescriptionPropertyGets or sets the description.
List<Type> ComponentTypesPropertyGets or sets the component types.
List<string> ErrorsPropertyGets or sets the errors.
bool SuccessPropertyGets or sets the success.
override string ToString()Method

ExtensionLoadedEventArgs

Raised after an extension has been loaded (successfully or with errors).

MemberKindDescription
ExtensionLoadedEventArgs(LoadedExtension extension)Method
LoadedExtension ExtensionPropertyGets or sets the extension.