Clipbus plugins
Plugins let Clipbus act on what you copy — detect the content, render a rich inline preview, and add quick actions. They're built with the open @clipbus/plugin-sdk, and their UI is a web page (the official template and examples are built with Vue 3).
Overview
A Clipbus plugin is a small module that hooks into the clipboard. Each plugin can provide up to three kinds of capability — you implement only the ones you need.
Inspect copied content and produce structured artifacts (attachments).
Resolve an attachment in Node, then draw its card in a WebView — tables, swatches, highlighted code.
Run an operation on a single item on demand — auto-run, or a draft form.
npm install read node_modules/@clipbus/plugin-sdk/docs/README.md (map) and API.md (capability truth). This page explains the concepts; the SDK docs are the source of truth.How it works
When you copy something, Clipbus runs the registered detectors over the content. A detector that recognizes the content returns one or more artifacts — typed payloads that become attachments on the clipboard item. A renderer then draws a card for each attachment, shown in the attachment panel under the item.
Cards are collapsible: a chip labels the type, a one-line preview sits beside copy and expand controls, and the expanded body shows the full result.
Runtime & UI
A plugin spans two isolated contexts. Your Node code is registered through one definePlugin({ detectors, attachmentRenderers, actions, messageHandlers }) call and runs headless; every visible surface is a separate HTML page declared as a uiEntry in the manifest. The two halves never share memory — they talk over a bridge: the UI calls clipbus.runtime.invoke(), and the runtime answers from its messageHandlers.
| Node runtime | WebView UI | |
|---|---|---|
| Entry | runtime.nodeEntry | uiEntry HTML |
| You write | definePlugin({ … }) | HTML + clipbus.* calls |
| Host API | host.* | clipbus.* |
Not every capability needs both halves — that is the distinction that matters:
| Capability | Runs in | Runtime handler | UI entry |
|---|---|---|---|
detector | Node only | detect() | — |
attachmentRenderer | Node + WebView | resolveAttachment() | uiEntry card |
action · auto-run | Node only | runAutoAction() | — |
action · draft | Node + WebView | resolveSession() | uiEntry form |
Detector
A detector turns raw clipboard input into typed artifacts. It receives the input and returns an array — empty when nothing matches, so several detectors can coexist. Detectors typically run a priority chain and stop at the first hit.
// detect(input) -> artifact[] export const decodeDetector = { async detect(input) { if (input.content.kind !== "text") return []; const { header, payload } = tryDecodeJwt(input.content.text); if (!header) return []; return [{ attachmentType: "plugin.example.decode.preview", attachmentKey: input.item.id, payloadJson: JSON.stringify({ header, payload }), }]; }, }; // no match — return empty; other detectors still run return [];
Renderer
A renderer owns one attachment type. Its runtime side, resolveAttachment, returns the card's display name and the buttons to seed. Its UI side is the uiEntry HTML that draws the card — the official template uses Vue 3.
export const decodeRenderer = { async resolveAttachment(input) { const payload = JSON.parse(input.attachment.payloadJson); return { displayName: "JWT", buttons: [{ id: "copy", label: "Copy" }], }; }, };
Each renderer sets height in its manifest entry — a fixed number (1–800), "auto" (content-driven, default bounds 80–800), an explicit { min, max }, or omit for the default 80–400. For "auto" and { min, max } the card UI calls clipbus.window.autoFit(), a SDK DOM helper that observes content size and calls window.setHeight.
clipbus.settings.get(key) / getAll().Action
Actions run on the current Action value. The runtime receives the original sourceItem separately from the current content, so auto-run results can feed the next Action. lifecycle: 'auto-run' runs via runAutoAction with no UI, while lifecycle: 'draft' opens a uiEntry form backed by resolveSession. During development you can preview a draft form with ?view=action, just like ?view=renderer for renderers. In the real host, a completed draft with a text, image, or path-reference result is presented for confirmation and can be explicitly advanced by the user; none cannot advance, and completion never auto-advances. The Preview harness records submission but does not simulate the host's result-confirmation, next-step filtering, rollback, or focus state machine.
The Toolbox plugin
The open-source plugin.clipbus.toolbox (awesome-clipbus-plugins/clipbus-toolbox-plugin) is a complete real example demonstrating all three capability kinds.
Detector + Renderer — decode preview
The decode-detector (with supportedInputKinds: ["text"]) produces a plugin.clipbus.toolbox.decode.preview attachment. Its renderer card uses height: { min: 32, max: 480 }. The detector runs a priority chain and stops at the first hit:
| Order | Type | Detects & shows |
|---|---|---|
| 1 | JWT | header.payload.signature structure — decoded header / payload JSON. |
| 2 | Escaped JSON | A "…" or \"-escaped string, unescaped and formatted. |
| 3 | URL | Percent-encoded %XX text, decoded. |
| 4 | Timestamp | 10-digit (s) or 13-digit (ms) Unix epoch in a sane year window. |
| 5 | Date string | A Date.parse-able string with date/time separators. |
| 6 | Base64 | Standard or URL-safe, printable ratio ≥ 95%, decoded text. |
The collapsible card shows a type chip, a one-line preview, a copy button, and an expand chevron. The expanded body shows the full decoded content with JSON highlight, or time details — local / UTC / ISO / epoch — using the toolbox's own default format yyyy-MM-dd HH:mm:ss.
Auto-run actions — case convert
Six auto-run actions rewrite the copied text in place: uppercase, lowercase, camelCase, pascalCase, snakeCase, and kebabCase. All declare supportedInputKinds: ["text"].
Draft action — image edit
A Crop & Compress draft action (with supportedInputKinds: ["image"]) opens a uiEntry form to crop and recompress an image item.
Plugin anatomy & manifest
A plugin is split by feature — each capability in its own self-contained folder. plugin.ts is the definePlugin entry that registers every handler. manifest.json declares the plugin's identity, runtime, and permissions.
{ "schemaVersion": 3, "plugin": { "id": "plugin.example.my-plugin", "title": "My Plugin", "version": "1.0.0" }, "runtime": { "nodeEntry": "dist/plugin.js", "uiRoot": "dist/ui" }, "install": "npm install --prefix . --ignore-scripts", "permissions": ["setTags", "setPinned", "setAttachment", "setSearchExtension"], "attachmentRenderers": [/* ... */], "detectors": [/* ... */], "actions": [/* ... */] }
your-plugin/ ├── manifest.json # plugin id, permissions, install hook ├── package.json # depends on @clipbus/plugin-sdk ├── src/ │ ├── features/<name>/ │ │ ├── payload.ts # artifact / draft types │ │ ├── detector.ts # detect → artifact[] │ │ ├── renderer.ts # resolveAttachment │ │ ├── action.ts # runAutoAction / resolveSession │ │ ├── app.vue # card / form UI │ │ └── main.ts # or index.html for standalone UI │ ├── shared/ │ ├── preview/ │ └── plugin.ts # definePlugin — registers handlers └── tests/runtime/
Getting started
Start by forking the official template github.com/scubers/clipbus-template-plugin — public, mirrors the in-repo template, and minimal but covers every extension point (detector, a compact and an expanded renderer, an auto-run action, a draft action). A fork gives you a production-ready skeleton.
Recommended — vibe-code on the template. It ships complete docs — a bilingual README / GUIDE and an AGENTS.md written for AI assistants — and depends on @clipbus/plugin-sdk, whose API.md / SPECIFICATION.md are the capability truth source. Point an AI assistant at these bundled docs and let it build on your fork: full context, no need to dig into SDK internals.
Local development requires Node.js ≥ 18.
npm install # pulls & builds @clipbus/plugin-sdk npm run dev # Vite preview workbench # ?view=renderer → preview an attachment card # ?view=action → preview a draft action form npm test # integration tests npm run build # typecheck + lint + build → dist/
To debug inside the app, open Settings → Plugins → Developer Plugins and Add Path to the directory containing your manifest.json. A declared install hook runs automatically (cwd = that directory); logs go to <AppData>/development-plugins/<id>/install-logs/ and stay out of your git status. Use Reload to re-read the manifest, Run Install to re-run the install hook, and View Logs if install fails.
API reference (SDK)
Everything an author can use is generated into the SDK package, always matching your installed version, so it never drifts from this page. You don't need to read the SDK's internal source.
- Docs map —
node_modules/@clipbus/plugin-sdk/docs/README.md - Capability truth source —
node_modules/@clipbus/plugin-sdk/API.md(generated; wins on any conflict) - Extending capabilities —
SPECIFICATION.md, Ch. 3 - npm — @clipbus/plugin-sdk · refresh with
npm update @clipbus/plugin-sdk
API.md is authoritative.Plugin limits
The free tier includes up to 3 active plugins per type (detector / renderer / action). Clipbus Pro lifts these limits to unlimited plugins (and adds Cloud Sync) as a one-time purchase. See pricing for details.