A plugin isa platform unit
Install one package — the engine registers CLI commands, REST routes, and a Studio page. No manual config. Permissions declared in the manifest — visible before install.
import { defineCommand, type CLIInput, type PluginContextV3 } from '@kb-labs/sdk';
import { requireApiKey, createTask } from '@kb-labs/clickup-core';
export default defineCommand({
id: 'clickup:task.create',
handler: {
// intent() — declare what the plugin will do before it does it
async intent(_ctx, input: CLIInput<TaskCreateFlags>) {
const { list, name } = input.flags;
return {
summary: `Create task "${name}" in list ${list}`,
operations: [{ type: 'create', resource: 'task' }],
};
},
async execute(ctx: PluginContextV3, input: CLIInput<TaskCreateFlags>) {
const { list, name, desc, status, json } = input.flags;
// business logic — the only thing the plugin author writes
const task = await createTask(requireApiKey(), list, {
name,
markdown_content: desc,
status,
});
// ctx.ui — same code, different surface: CLI, REST, Studio
if (json) {
ctx.ui.json({ id: task.id, name: task.name, url: task.url });
} else {
ctx.ui.success('Task created', {
sections: [{ items: [`id: ${task.id}`, `url: ${task.url}`] }],
});
}
return { exitCode: 0, result: task };
},
},
});Just the business logic
A plugin talks to abstractions — ctx.ui, useLLM(). Which provider is behind them, how requests are routed, where logs go — that's the platform's job.
ctx.ui.success() works the same from CLI or a Workflow step.
kb review --stagedkb review runPOST /api/reviewGET /api/review/runs/p/reviewfull pageOne manifest — three surfaces
A plugin declares CLI commands, REST routes, and a Studio page in one file — manifest.ts. On install, the engine registers everything automatically.
No router config, no command registration, no Studio config. Install the package — everything works.
Plugins are isolated: each gets only the platform resources it declared. Full OS isolation available in container/remote execution mode.
Plugin lifecycle
After install the platform records the package in .kb/marketplace.lock with a SHA-256 checksum. On every start, discovery verifies integrity and loads the manifest.
The manifest extracts entity kinds — seven types: CLI commands, REST routes, Studio pages, workflow handlers, webhook handlers, WebSocket channels, cron schedules. One plugin can register any combination.
On command invocation the engine picks an execution backend. In-process is the default — minimal overhead. Subprocess and worker-pool add process isolation. Remote gives full OS isolation on a separate machine.
See permissions before install
Every plugin declares in its manifest what it needs: read git, call LLM, write to fs. You see this before running install.
This isn't a hard guarantee — with in-process execution the platform enforces declared permissions, but full OS isolation requires container or remote mode.
Like mobile app permissions: you know what the plugin wants and make an informed decision.
import { combinePermissions, kbPlatformPreset } from '@kb-labs/sdk';
export default {
schema: 'kb.plugin/3',
id: '@kb-labs/review',
version: '2.94.0',
permissions: combinePermissions()
.with(kbPlatformPreset)
.allow('git.read') // can read git history
.allow('llm.call') // can call LLM
.deny('fs.write') // no filesystem writes
.deny('shell.exec') // no shell access
.build(),
cli: {
commands: [
{ id: 'review', handler: './commands/run.js#default' },
{ id: 'review:ci', handler: './commands/ci.js#default' },
],
},
} as const;# 1. scaffold
kb scaffold run plugin my-plugin
# 2. build
pnpm build
# 3. publish to KB Labs Registry
kb marketplace publish
# --- anyone can now install ---
kb marketplace install @you/my-plugin
# or share privately
kb marketplace share --with user123
kb marketplace share --linkBuild and publish your own plugin
First plugin in 5 minutes.
Install KB Labs, run scaffold, add your logic. CLI, REST API, and Studio are ready automatically.