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
ui.registerContextMenuItem(item, onInvoke) { id, label, targets, submenu?, only? } and ContextMenuTarget callback; disposer
ui.registerSettingsPage(page, handlers?) { title } and optional { onShow, onHide }; disposer

NativeDialog contains title, description, submitLabel, and sections. NativeSection has title, controls, optional repeatKey/maxRows. NativeControl has key, label, kind, optional placeholder/maxLength. A context menu item’s only is “self” or “others”. A settings page shows the plugin’s frame while open. 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
network.fetch(request) NetworkRequest to a listed host; NetworkResponse, without a user action
messages.sendEmbed(draft) Validated EmbedDraft to current channel, after a user action
messages.insertText(text) Text typed into the message box, never sent, after a user action
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
badges.registerRoleBadgeProvider(provider, options?) RoleBadgeRequest callback returning RoleBadgeResult; disposer
decorations.registerProvider(options, provide, onAction?) DecorationRequest callback returning DecorationResult; disposer
decorations.refresh(keys?) Ask again about some or all places

NetworkRequest has url, optional method (GET or POST), headers and body; NetworkResponse has status, optional contentType, and body as text. EmbedDraft supports title, url, description, color, author, thumbnail, image, footer, timestamp, and fields. InspectionEvent includes kind, sanitized metadata, and geometry. RoleBadgeRequest carries a community’s roles; RoleBadgeResult maps role ids to badges, plus an optional owner style. Follow each guide for context and resource restrictions.

API Inputs and result
navigation.current() RouteInfo { kind, guildId?, channelId? }
navigation.onChange(handler) RouteInfo callback, called at once and on every change; disposer
guildData.info(guildId?) GuildInfo { id, name, icon? }
guildData.roles(guildId?) GuildRoleInfo[], highest position first
guildData.channels(guildId?) GuildChannelInfo[] { id, name, type, parentId?, position }
guildData.onChange(handler) GuildDataChange { guildId, kind } callback; disposer
activity.current(options?) ActivityState { focused, visible, idle }
activity.onChange(handler, options?) ActivityState callback, called at once and on every change; disposer
voice.current() VoiceState { state, channelId?, guildId? }
voice.onChange(handler) VoiceState callback, called at once and on every change; disposer

ActivityOptions has idleAfterSeconds, 60 to 3600 (default 300). A VoiceState’s state is disconnected, connecting or connected.

See navigation and community data, activity and voice, right-click menus and the message box, decorations and network requests.

patcher.register(hook, handler) receives { hook, value } and returns a disposer. The handler returns the new value, synchronously or asynchronously; for the hooks in PatchHookValues, TypeScript knows its type.

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

This requires patcher. The hooks are client-info.lines and badges.merge; see patch hooks. Handlers run in registration order; throwing, timed-out or refused results 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.