Sharkord
Plugins

Overview

What a plugin can do, what one is made of, and how the load, upgrade and unload lifecycle works.

A plugin is a folder of JavaScript that Sharkord loads into the server and, optionally, into every user's browser. Plugins add commands, buttons and whole screens, react to events, intercept writes before they happen, expose HTTP endpoints, moderate users, and push audio and video into voice channels.

Experimental

The plugin SDK is version 2 and still moving. Expect breaking changes between releases; a plugin's sdkVersion must match the server exactly or it will not load.

Security warning

A plugin runs with the full privileges of the server process and of every user's browser session. Read Security before installing anything.

Shape of a Plugin

Every plugin is a folder inside plugins/ in the data directory, containing:

my-plugin/
  manifest.json    # id, name, version, sdkVersion
  server/index.js  # runs in the server process
  client/index.js  # runs in every user's browser

All three are required, even when a plugin has no interface. The folder name must match the id in the manifest.

Lifecycle

server/index.js exports up to three functions:

import type {
  PluginContext,
  TUpgradeInfo,
  UnloadPluginContext,
  UpgradePluginContext,
} from "@sharkord/plugin-sdk";

const onLoad = async (ctx: PluginContext) => {
  // register everything here
};

const onUnload = async (ctx: UnloadPluginContext) => {
  // stop timers, close connections, remove streams
};

const onUpgrade = async (ctx: UpgradePluginContext, info: TUpgradeInfo) => {
  // migrate anything under ctx.dataPath
};

export { onLoad, onUnload, onUpgrade };
FunctionWhen it runs
onLoadAt server start, and again after every enable or update. Required.
onUnloadOn disable, update, removal, and server shutdown.
onUpgradeBefore onLoad, only when the installed version changed.

Each of the three is given 30 seconds. Throwing in onLoad or onUpgrade stops the load and shows the reason to admins; a failed onUpgrade leaves the recorded version alone, so the migration is retried on the next load instead of running half-applied.

onUnload is optional for now: a plugin without one loads, and the server logs a warning saying it will be required in a future SDK version. Write it anyway. Commands, actions, events, settings, hooks, and HTTP routes are unregistered for you, but timers, sockets, and voice streams you started are not. A leaked timer survives a reload and fires against the next load.

Two Folders on Disk

PathWhat it is
ctx.pathThe plugin's own folder. An update deletes and rewrites it, so treat it as read-only.
ctx.dataPathA folder that survives updates and is deleted with the plugin. Everything you write goes here.

What the Context Gives You

APIUse it for
CommandsSlash commands users can run
ActionsServer functions your UI can call
ComponentsReact components in fixed slots, and your own admin tabs
EventsReacting to 33 things that happened on the server
SettingsTyped options an admin edits in the UI
MessagesSending, editing, reading, pinning and reacting
DataUsers, channels, categories, roles, permissions, per-user storage
HooksRejecting or rewriting a write before it happens
HTTPYour own HTTP endpoints, authenticated or public
VoicePublishing external streams, and consuming what users send

The Contract is what types all of it, the Client SDK covers the browser half, and API Reference lists the whole surface in one place.

Getting Started

Start with Create a Plugin, then Installation. To share what you build, see Marketplace.

The SDK source is the ground truth: packages/plugin-sdk.

On this page