Plugin API Reference
This page follows the current Services/Plugins/ source. A plugin using the interfaces introduced in 1.8 should declare MinHostVersion: "1.8.0" in manifest.json; use 1.8.1 when it also depends on the 1.8.1 fixes.
Core interface and lifecycle
Every plugin implements IFolderRewindPlugin:
public interface IFolderRewindPlugin
{
PluginInstallManifest Manifest { get; }
IReadOnlyList<PluginSettingDefinition> GetSettingsDefinitions();
void Initialize(IReadOnlyDictionary<string, string> settingsValues);
void SetHostContext(PluginHostContext hostContext) { }
string? OnBeforeBackupFolder(BackupConfig config, ManagedFolder folder,
IReadOnlyDictionary<string, string> settingsValues);
void OnAfterBackupFolder(BackupConfig config, ManagedFolder folder, bool success,
string? generatedArchiveFileName,
IReadOnlyDictionary<string, string> settingsValues);
object? OnBeforeRestoreFolder(BackupConfig config, ManagedFolder folder,
string archiveFileName, IReadOnlyDictionary<string, string> settingsValues) => null;
void OnAfterRestoreFolder(BackupConfig config, ManagedFolder folder, bool success,
string archiveFileName, object? state,
IReadOnlyDictionary<string, string> settingsValues) { }
}
Configuration discovery and full takeover members have default implementations: GetSupportedConfigTypes, CanHandleConfigType, TryDiscoverManagedFolders, TryCreateConfigs, WantsToHandleBackup, PerformBackupAsync, WantsToHandleRestore, and PerformRestoreAsync.
The usual call order is:
load manifest → Initialize → SetHostContext
discover/create config → backup hook or full takeover → after-backup hook
restore hook/interceptor → standard restore or full takeover → after-restore hook
Manifest and target framework
{
"Id": "com.example.myplugin",
"Name": "MyPlugin",
"Version": "1.0.0",
"EntryAssembly": "MyPlugin.dll",
"EntryType": "MyPlugin.MyPlugin",
"MinHostVersion": "1.8.0"
}
The application target framework is net10.0-windows10.0.19041.0. Plugin projects should use a compatible .NET 10 Windows target and reference the interface assembly from the actual installation/build output; do not copy a target path from older site content.
Backup filters and scopes
IFolderRewindBackupFilterProvider
PluginBackupFilterContribution? GetBackupFilterContribution(
BackupConfig config,
ManagedFolder folder,
IReadOnlyDictionary<string, string> settingsValues);
The contribution applies to one backup invocation. The Host clones the effective config and does not mutate the saved whitelist/blacklist.
IFolderRewindBackupScopeProvider
IReadOnlyList<PluginBackupScopeDefinition> GetBackupScopeDefinitions(
BackupConfig config,
IReadOnlyDictionary<string, string> settingsValues);
PluginBackupScopeResolution ResolveBackupScope(
BackupConfig config,
ManagedFolder folder,
PluginBackupScopeContext scope,
IReadOnlyDictionary<string, string> settingsValues);
PluginBackupScopeDefinition supplies an ID, display name, description, and parameter definitions. PluginBackupScopeContext carries the selected ScopeId and parameters. A resolution is Applied, NotApplicable, or Invalid, and can merge rules with Append or Replace. Selected-region backup uses Replace, so its calculated scope replaces the regular whitelist.
Backup preparation and folder details
IFolderRewindBackupPreparationProvider
string? OnBeforeBackupFolder(
BackupConfig config,
ManagedFolder folder,
BackupInvocationOptions invocationOptions,
IReadOnlyDictionary<string, string> settingsValues);
This interface can inspect trigger source and consistency preferences. If it is not implemented, the core OnBeforeBackupFolder hook still runs.
IFolderRewindFolderDetailsProvider
Task<IReadOnlyList<FolderDetailsSection>> GetFolderDetailsSectionsAsync(
BackupConfig config,
ManagedFolder folder,
IReadOnlyDictionary<string, string> settingsValues,
CancellationToken cancellationToken);
Plugins return read-only key/value data; the Host renders the details dialog. An exception from one provider does not prevent other details from rendering.
Restore interception and config augmentation
IFolderRewindRestoreInterceptor
Task<PluginRestoreInterceptionResult> TryInterceptRestoreAsync(
BackupConfig config,
ManagedFolder folder,
string archiveFileName,
IReadOnlyDictionary<string, string> settingsValues,
CancellationToken cancellationToken);
Return Continue to let the Host proceed, Handled when the plugin completed the request, or Blocked to reject it. Use PluginRestoreInterceptionResult.Continue/Handled/Blocked(...).
IFolderRewindConfigAugmenter
PluginConfigAugmentationResult AugmentConfigs(
PluginConfigAugmentationRequest request,
IReadOnlyDictionary<string, string> settingsValues);
bool ShouldAugmentAfterSettingsChange(
IReadOnlyDictionary<string, string> previousSettings,
IReadOnlyDictionary<string, string> currentSettings) => false;
Return folders to suggest adding. The Host deduplicates, filters conflicts, saves, and notifies the user. Do not mutate ConfigService.CurrentConfig directly.
KnotLink and hotkeys
IFolderRewindParameterizedKnotLinkCommandHandlerimplementsTryHandleParameterizedKnotLinkCommandAsync(KnotLinkCommandRequest, settingsValues, hostContext); see KnotLink Command API.IFolderRewindKnotLinkCapabilityProviderimplementsGetKnotLinkCapabilities()and publishes discoverable commands and signals.IFolderRewindHotkeyProviderimplementsGetHotkeyDefinitions()andOnHotkeyInvokedAsync(...)for global or in-app hotkeys.
PluginHostContext exposes the plugin ID, KnotLink state, event broadcasting, query/send operations, signal subscriptions, and logging. KnotLink payloads must follow strict key-value protocol v2.
Full backup/restore takeover
Return WantsToHandleBackup/Restore = true only when the plugin owns a genuinely different archive format or workflow, then implement:
Task<PluginBackupResult> PerformBackupAsync(
BackupConfig config, ManagedFolder folder, string comment,
IReadOnlyDictionary<string, string> settingsValues,
Action<double, string>? progressCallback = null);
Task<PluginRestoreResult> PerformRestoreAsync(
BackupConfig config, ManagedFolder folder, string archiveFileName,
IReadOnlyDictionary<string, string> settingsValues,
Action<double, string>? progressCallback = null);
PluginBackupResult has Success, GeneratedFileName, and Message; PluginRestoreResult has Success and Message. Prefer hooks and extension interfaces for ordinary plugins so Host history, cleanup, and safety policy remain active.
Exceptions, threads, and compatibility
- Plugins run in the Host process; catch expected exceptions in hooks, handlers, and detail providers.
- Do not perform long I/O on the UI thread; use async APIs and honor
CancellationToken. - Do not cache internal models across versions or mutate Host service state directly.
- New interfaces require 1.8.0. The current MineRewind manifest uses
MinHostVersion: 1.8.1; set the minimum to the actual API you require. - A ZIP root must contain
manifest.jsonand the entry assembly, with dependencies beside it.