Developers / Plugin SDK
Extend the channel. Not an iframe.
Plugins are part of the product, not embedded in a 90s frame. Add custom blocks, channel tabs and slash commands that read and write the same data model the rest of Slick uses.
Install
One package. TypeScript first.
The SDK is published on npm and ships full types for every block and event.
npm install @slick/plugin-sdkAnatomy
A plugin in a dozen lines.
Declare what you contribute — a slash command, a block renderer, a channel tab — and the runtime wires it into the composer, the feed and the channel rail.
import { definePlugin, block, command } from "@slick/plugin-sdk";
export default definePlugin({
id: "standup",
name: "Standup",
// A /standup slash command that posts a structured block.
commands: [
command("standup", async (ctx) => {
await ctx.post(block.card({
title: "Daily standup",
rows: ctx.members.map((m) => ({ who: m.handle, status: "—" })),
}));
}),
],
// A channel tab backed by your own state.
tabs: [{ id: "board", title: "Board", mount: "./board" }],
});Capabilities
What a plugin can touch.
Blocks
Custom block types
Render interactive blocks inline in the feed — tables, cards, forms — with actions that round-trip to your handler.
Tabs
Channel tabs
Mount a full surface alongside the message feed. State is yours; navigation, theming and identity come from Slick.
Commands
Slash commands
Register
/your-command in the composer with typed arguments and autocomplete.Events
Workspace events
Subscribe to messages, reactions, pins and membership changes over a signed webhook or SSE stream.
Identity
Scoped principals
Every plugin acts as a bot identity with explicit RBAC/ABAC scope. Nothing runs unaudited.
Distribute
Private or public
Ship a plugin to one workspace or list it in the Slick directory. Revenue share lands at GA+1.
Build something worth installing.