Hook signatures and dispatch#
| Hook | Arguments and contract |
|---|---|
onInit(context) | Called when an enabled module is loaded/reloaded or enabled. Returned promises are not awaited. Catch asynchronous failures inside the hook. |
onClipSaved(clip, context) | Manual/replay and edited-video exports: runs after library insertion and clip:created. Awaited for each enabled plugin. |
onScreenshot(clip, context) | Screenshot notification hook, separate from onClipSaved. Awaited. |
onRecordingStart(context) | Manual session begins before this hook is awaited. Keep it short so starting feedback can complete. |
onRecordingStop(context) | After the manual clip is saved and the manual-start marker is cleared. Awaited. |
onAction(actionId, context, data) | Preferred action handler. The action dispatcher awaits its return value. |
onButtonAction(actionId, context, data) | Legacy fallback used only when onAction is not a function. |
There is no current onDispose, onDisable, per-frame hook, deletion hook or recorder-control method in the plugin context. Hooks from other plugin systems do not become available merely by exporting them.
Context method contracts#
| Method / member | Return and side effects |
|---|---|
manifest | Current in-memory manifest object. Treat metadata as read-only and use explicit APIs for changes. |
getConfig() | The current manifest config object, or {}. No automatic schema-default expansion. |
saveConfig(values) | Shallow merge and synchronous manifest save. Returns no success flag; check logs and read back during development. |
log(message, level?) | info by default; supported levels info, warn, error, success. Console contains at most 200 entries. |
showNotification(title, message, type?) | Default success. Supports info, success, warning, error, recording; warning maps to info. |
fetch(url, options?) | Promise resolving to the bundled Node fetch Response. HTTP 4xx/5xx require checking response.ok. |
ui.registerButton / registerTab | Upsert by ID and persist the manifest. |
ui.removeButton / removeTab | Remove matching ID and persist. |
ui.updateTab(id, updates) | Mutate an existing tab and notify the renderer; no immediate persistence. |
ui.setTabContent(id, html) | Update an existing tab’s HTML and notify the renderer; no immediate persistence. |
Clip and action result data#
{
"id": "example-id",
"name": "Recording_example",
"filePath": "C:\\Users\\you\\Videos\\HydroClips\\Recording_example.mp4",
"duration": 12.5,
"size": 2500000,
"createdAt": "2026-10-09T12:00:00.000Z",
"type": "manual",
"driveStatus": "idle"
}duration is seconds and size is bytes. Video types are manual and instant_replay; screenshots use screenshot with duration zero. Optional fields include thumbnailPath, thumbnailDataUrl, durationFormatted, driveProgress, driveFileId, driveLink and error. Drive states are idle, pending, uploading, synced and failed.
An action invocation returns { success: true, result } or { success: false, error }. An action with no handler logs its ID and can still return success with an undefined result. Do not treat success as proof that an absent handler performed work.
Available globals#
The module evaluator explicitly supplies module, exports, routed console, four timer functions, Buffer, path, fs and __dirname. JavaScript intrinsics such as Promise, JSON, Date and Map are also usable. Use context.fetch for network requests.
There is no supplied require, ES-module loader, process, browser window/document, Electron API, or AbortController global. Bundle dependencies into the entry file when needed, and test the output for unsupported imports.
Implementation reference: src/main/plugins/PluginManager.ts; src/types/index.ts · native 2.0.7.
Optional audio and editing metadata#
Version 2.0.7 adds optional audioTracks: [{index, role, label}]. Roles are mix, system, microphone or other. Older clips can omit this field. Edited videos also carry sourceClipId and edit: {start, end, systemGain, microphoneGain, mixedGain}. Times are relative to the immediate source, in seconds; gains range from 0 to 2. A source type stays manual or instant_replay so existing plugins keep working.
onClipSaved is invoked for edited videos after library insertion. A clip counter will therefore count saved edits too; use sourceClipId to exclude them if desired. These fields are descriptive metadata. There is no plugin context method for invoking the editor or arbitrary recording controls.