Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Plugin System

This page is the single current-state overview for the plugin-system work. The normative runtime contract still lives in Plugin Runtime and Community Plugin Host Boundary; this page summarizes what is implemented now and points to the consolidated design specification for the remaining model.

What Exists Today

Lapis still uses the Obsidian community plugin folder layout under /.obsidian/plugins/<id>/ with manifest.json, main.js, optional styles.css, and compatibility data.json. PluginManager in @lapis-notes/api remains the only lifecycle owner for community plugins: it discovers plugins, runs manifest preflight, chooses an execution host, evaluates code, manages activation and rollback, tracks diagnostics, and keeps the existing boot rule that layout restore happens only after plugin activation attempts finish.

The runtime now supports three plugin classes:

  • Obsidian-compatible plugins, which continue to use main.js.
  • Lapis extensions, which may be manifest-only or may load host-specific runtime entries.
  • Hybrid plugins, which keep main.js compatibility while also declaring Lapis metadata.

Before code runs, Lapis validates and indexes the optional lapis namespace. That index now supports declarative commands and configuration without code evaluation, activation-event driven lazy activation for code-backed Lapis extensions, scoped service registration for language-service providers, and app-owned generated extension state stored in AppDatabase metadata rather than under shipped plugin folders. App-shipped system extensions can now also be registered through PluginManager.registerSystemExtensions(...), which supports manifest-only registrations, renderer code-backed system plugins, declarative services bound to app-owned implementations, and explicit privilege metadata while keeping those extensions in the core-plugin settings surface instead of the community plugin list. Plugin settings diagnostics also now surface plugin class, selected host mode, activation mode, last activation trigger, selected runtime entry when known, requested and granted capabilities, requested and granted app permissions, explicit system-extension privileges, unsupported indexed contributions, and the last failure message.

Runtime Model

Community plugin evaluation goes through CommunityPluginExecutionHost.

  • The renderer host remains the compatibility fallback and still evaluates CommonJS bundles in process.
  • Electron desktop now has a brokered sidecar path for trusted desktop community plugins, with one trusted child process per plugin ID and vault/window context.
  • PluginManager selects lapis.runtime.workspace for renderer-hosted Lapis code and lapis.runtime.trustedDesktop or lapis.runtime.desktop for sidecar-hosted Lapis code.
  • Obsidian-compatible and hybrid plugins still resolve code through main.js.

Runtime-aware manifest fields such as supportedRuntimes, requiredCapabilities, and executionHints participate in preflight when declared. Lapis runtime-entry selection is also enforced in preflight: selected entries must stay inside the plugin root and currently must end in .js, .cjs, or .mjs.

Desktop Host State

Electron is the active desktop shell. The renderer runs with contextIsolation: true, nodeIntegration: false, and sandbox: false. Preload exposes typed native capability access. Electron main owns the plugin sidecar lifecycle and supports prepare, evaluate, activate, deactivate, and shutdown for trusted desktop community plugins, with restart budgets and cooldown failures isolated per hosted plugin.

This is a stronger boundary than renderer execution, but it is not a sandbox guarantee. The current trusted desktop host is still a normal Node process with brokered app capabilities layered on top, not a fully isolated per-plugin security boundary.

Permissions And Trust

Permissions currently map to brokered capabilities such as vault I/O, plugin data, commands, notices, settings, metadata queries, events, and logging. Permission and trust decisions happen during preflight and are shown in the workspace plugin settings UI.

Important constraint: app permissions only govern brokered APIs. They do not restrict arbitrary Node access once a trusted desktop extension is allowed to run in the sidecar. The docs and UI should keep describing trusted desktop execution as trusted, not sandboxed.

What Is Still Missing

Several planned pieces remain intentionally incomplete:

  • richer manifest-only contribution coverage beyond the currently installed command and configuration contributions
  • browser-worker runtime support
  • multi-host hybrid activation beyond the current main.js compatibility path
  • broader benchmark and regression coverage for the plugin/runtime matrix

The remaining plugin-runtime work is centered on richer manifest-only contribution models plus follow-on runtime expansion such as browserWorker and multi-host hybrid activation.

Current Phase Snapshot

The plugin-system phases are no longer mostly speculative.

  1. Done: manifest classification and contribution indexing.
  2. Done: manifest-only commands and configuration. Declarative settings widget coverage, VS Code parity gaps, and the plugin-test e2e-vault matrix are documented in Configuration and Settings.
  3. Done: scoped service registration, starting with language services.
  4. Done: Electron sidecar evaluation and lifecycle for trusted desktop community plugins.
  5. Done: permission and trust diagnostics in the settings UI.
  6. Done: bundled system extensions with manifest-only contributions, renderer code-backed registrations, service bindings, and explicit privilege diagnostics.
  7. Done for the current desktop host scope: per-plugin Electron sidecars, restart budgets, and trust/isolation diagnostics. Remaining runtime-model work is limited to the follow-on items listed above.

Design Specification

The forward-looking design now lives in one document instead of a cluster of planning notes: Plugin System Design.