Lite SuiteLite Suite

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 WebContentsView with contextIsolation and 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 WebContentsView positioned over the canvas pane; closing the pane destroys it. The view runs with sandbox, contextIsolation, and nodeIntegration: 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.storage is 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.