Plugins
Extend Lite Suite with sandboxed community panels built on the @litesuite/plugin-sdk
Overview
Lite Suite is extensible. Every panel you see on the canvas is a plugin, and you can add your own. There are two kinds, and they share one panel registry — the only difference is isolation:
- First-party plugins — the 20 built-in panels (editor, terminal, browser, git, command center, model hub, …) are first-party plugins that run in-process. They ship with the app.
- Community plugins — third-party panels you install. Each runs in a sandboxed WebView (an Electron
WebContentsViewwithcontextIsolationand no Node integration) and talks to the host over a permission-gated bridge.
This hybrid model means a community plugin is a first-class canvas pane — it pans, zooms, and docks exactly like a built-in panel — but it can never touch your filesystem, shell, or other panels except through APIs you've granted.
Installing a plugin (end users)
Plugins install into LiteSuite/plugins under your user data directory. Use the litesuite CLI that ships with the SDK:
# From a local folder, a Git repo, or an npm package
litesuite install ./my-plugin
litesuite install https://github.com/someone/cool-panel.git
litesuite install @someone/cool-panel
# Manage what's installed
litesuite list # show installed plugins + status
litesuite disable cool-panel # keep it installed but stop loading it
litesuite enable cool-panel
litesuite uninstall cool-panel
Before installing, the CLI prints the permissions the plugin requests so you can decide whether to trust it. After installing, restart Lite Suite — the plugin's panel appears in the pane picker, and opening it spins up its sandboxed view on the canvas.
Building a plugin (developers)
Scaffold
litesuite create-plugin my-panel
cd my-panel
bun install
litesuite dev # Vite dev server + live reload in the host
create-plugin emits a complete project: the manifest, an index.html webview entry, a src/main.ts that calls createPlugin, and a Vite config. While litesuite dev runs, the host loads your panel live from the dev server with hot reload.
The manifest
Every plugin has a litesuite-plugin.json validated against the SDK schema:
{
"name": "my-panel",
"version": "0.1.0",
"description": "What my panel does",
"author": "you",
"license": "MIT",
"sdkVersion": "1.0.0",
"runtime": "webview",
"permissions": ["ui", "storage"],
"main": "dist/index.html",
"dev": "http://127.0.0.1:5200/",
"panel": {
"type": "plugin:my-panel",
"label": "My Panel",
"icon": "puzzle",
"defaultSize": { "width": 480, "height": 360 }
}
}
| Field | Notes |
|-------|-------|
| name | Lowercase kebab-case. Identity of the plugin; the host registers its panel as plugin:<name>. |
| permissions | Subset of canvas, ui, storage. The bridge denies any API call in a namespace you didn't declare. |
| main | Built entrypoint (dist/index.html). Loaded when the plugin is installed. |
| dev | Optional dev-server URL. Loaded only in a dev build, as a fallback when no build exists — installed plugins always load their built main. |
| panel.type | Must equal plugin:<name> — the host keys the panel off it. |
The entry point
Your src/main.ts calls createPlugin. The host handshakes, grants the permissions you declared, and runs your setup:
import { createPlugin, parseManifest } from "@litesuite/plugin-sdk";
import rawManifest from "../litesuite-plugin.json" with { type: "json" };
createPlugin({
manifest: parseManifest(rawManifest),
async setup({ api }) {
const theme = await api.ui.getTheme();
const count = (await api.storage.get<number>("clicks")) ?? 0;
document.getElementById("root")!.textContent = `Clicked ${count} times`;
await api.ui.showToast("Hello from my-panel!", { level: "success" });
},
});
The API
setup receives an api object whose namespaces map to the permissions you declared:
| Namespace | Methods | Permission |
|-----------|---------|------------|
| api.canvas | createPane, removePane, listPanes | canvas |
| api.ui | showToast, getTheme, onThemeChange | ui |
| api.storage | get, set, delete (plugin-scoped key/value, persisted) | storage |
| api.permissions | check | always available |
Build and ship
litesuite build # bundles index.html → dist/, copies the manifest
litesuite install . # install the built plugin locally to test it
The built dist/ is self-contained and installable as a folder, a Git repo, or an npm package.
Architecture & security
- One sandboxed view per pane. Opening a plugin panel creates a dedicated
WebContentsViewpositioned over the canvas pane; closing the pane destroys it. The view runs withsandbox,contextIsolation, andnodeIntegration: false. - Permission-gated bridge. All host calls cross a bridge that checks the plugin's declared permissions, rate-limits requests, and caps permission-denial floods. A plugin can only do what its manifest declares.
- Plugin-scoped storage.
api.storageis namespaced per plugin and persisted to disk — one plugin can never read another's data. - No ambient authority. There is no filesystem, shell, or network namespace in v1. A plugin reaches the outside world only through the APIs you grant.
The Plugin SDK is
@litesuite/plugin-sdk. First-party panels use the same panel registry as community plugins, so anything the built-in panels can do on the canvas, a plugin can do too — within its granted permissions.
