Skip to content

Public SDK reference

Import definePlugin and types from @fluxplugs/plugin-api. SDK_API_VERSION is 2. All services below are accessed through the PluginAPI passed to start.

PluginDefinition has manifest: { id }, start(api), and optional stop(). Start/stop can be synchronous or return a promise. definePlugin registers the definition inside the sandbox.

JsonValue is null, boolean, number, string, an array of JSON values, or an object of JSON values. DOM nodes, functions, and credentials cannot be passed through RPC.

Unless noted, service calls are asynchronous. Registration calls return Promise<() => void>; save the disposer for cleanup. Getters and theme snapshots return promises of their values.

API Result and behavior
pluginId Read-only string identity
logger.debug/info/warn/error(message, fields?) Synchronous log methods; fields are JSON-valued records
capabilities.has(capability) Synchronous boolean grant check
storage.get<T>(key) T or undefined
storage.set(key, value) / delete(key) Save/remove plugin-private JSON
settings.get<T>(key) / set(key, value) Read/write manifest-defined boolean/string/number values

Generic type parameters describe expected data; validate structured values at runtime. Never log secrets or signed URLs.

API Inputs and result
ui.registerPanel(panel) { id, title, body }; disposer
ui.registerAttachmentAction(action, onInvoke) { id, label, submenu? }; disposer
ui.openDialog(description, validate) NativeDialog and validation callback; values or undefined on cancellation
ui.openView(description) { title, kind: “dialog” or “panel” }; disposer
ui.setOverlay(description, onAction?) Geometry, color, text, optional actionLabel; null removes overlay
ui.theme() Record of allowed CSS variables
ui.onThemeChange(handler) Theme snapshot callback; disposer
ui.notify(message) Display a text notice

NativeDialog contains title, description, submitLabel, and sections. NativeSection has title, controls, optional repeatKey/maxRows. NativeControl has key, label, kind, optional placeholder/maxLength. See native UI and sandbox views.

API Inputs and result
styling.apply(rules) StyleRule[] with selector, declarations, optional imageHandle; disposer
inspection.subscribe(handler, interceptClicks?) InspectionEvent callback; disposer
shortcuts.register(shortcut, handler) Shortcut string and callback; disposer
clipboard.writeText(text) Bounded, interaction-associated write
images.load(url) ImageResource { handle, width, height }
images.url(handle) / release(handle) Sandbox URL / release owned resource
messages.sendEmbed(draft) Validated EmbedDraft to current channel
attachments.registerContextAction(action, onInvoke) Posted-file action and AttachmentContext callback; disposer
attachments.resolve(contextHandle) ResolvedAttachment { id, filename, size, url }
externalLinks.open(url) Authorized browser navigation

EmbedDraft supports title, url, description, color, author, thumbnail, image, footer, timestamp, and fields. InspectionEvent includes kind, sanitized metadata, and geometry. Follow each guide for context and resource restrictions.

patcher.register(hook, handler) receives { hook, value } and returns a disposer. The handler returns JSON, synchronously or asynchronously.

cleanup.push(
await api.patcher.register("client-info.lines", (event) =>
Array.isArray(event.value)
? [...event.value, "My plugin is active"]
: event.value,
),
);

This requires patcher and targets the currently registered client-info.lines hook. Handlers run in registration order; throwing or timed-out handlers are skipped. This is not arbitrary function replacement.

The public SDK source contains exact TypeScript signatures and exported types. Use errors and limits alongside this reference.