Plugins

Opt in to everything.
Or nothing.

The base dock is intentionally small. Every advanced surface - visual git, voice, browser embed, cloud dashboards, an LLM coordinator - is a plugin you toggle on per project.

  • Sandboxed by default
  • Consent-gated on first detection
  • Hot-updatable archive
  • Per-project enable / disable
How it works

Three files. Drop the folder. Restart.

A plugin is a manifest, a main module, and (optionally) a window UI. Drop the folder in your plugins directory, restart the dock, approve the consent dialog, and it loads.

01

Manifest

Declare your id, version, toolbar entry, window dimensions, and per-project settings schema.

02

Main module

Export an activate(context) function. Use the context to register IPC handlers, listen on the event bus, log, and open windows.

03

Window UI (optional)

Ship an index.html for plugins that need their own surface. Or skip it and live in the toolbar.

plugin.json
{
  "id": "my-plugin",
  "name": "My Plugin",
  "version": "1.0.0",
  "description": "What this plugin does",
  "defaultEnabled": true,
  "main": "./main.js",
  "toolbar": {
    "title": "My Plugin",
    "action": "my-plugin:open",
    "order": 90
  }
}
main.js
function activate(context) {
  context.ipc.handle('my-plugin:open', async (projectDir) => {
    await context.openPluginWindow(projectDir)
  })

  context.bus.on('project:postOpen', 'my-plugin', ({ projectDir }) => {
    context.log(`Project opened: ${projectDir}`)
  })
}

module.exports = { activate }
Built-in

Plugins ship in the box. None are running yet.

All built-ins are bundled in the plugin archive. They sit dormant on disk until you toggle them on per-project.

Trust model

Plugins are powerful. So they're explicit.

Consent-gated

The first time the dock detects a new plugin folder, it surfaces a dialog with the plugin's name and description. No code runs until you say yes.

Per-project enable

A plugin can be on for one project and off for another. The toggle is local; nothing is uninstalled.

Sandboxed surfaces

Windows are separate BrowserWindows with explicit IPC channels. The dock window doesn't load plugin code into its own React tree (with documented exceptions for renderer-embedded plugins).

Hot-updatable archive

Built-ins ship as a signed archive (plugins.zip + plugins.update) with deterministic content hashes. Updates don't require a full app reinstall.

Ready to build one?

Drop a folder in the plugins directory, restart, and approve the consent dialog. The full guide ships with the app.