API v1

Plugin development

Build extensions in plain ESM

Plugins extend Meridian without modifying the core. Drop a folder into .meridian/plugins/<your-plugin>/ and Meridian picks it up — with hot reload. Plain ESM, no build step required.

A minimal plugin

Plugins register commands, react to vault events, and render side panels. The smallest useful example is a word counter:

// .meridian/plugins/word-counter/main.js
export default class WordCounter {
  onLoad(api) {
    api.registerCommand({
      id:   'word-counter:show',
      name: 'Word Counter: Show stats',
      run: () => {
        const text = api.editor.getActiveText() ?? '';
        const words = text.trim().split(/\s+/).filter(Boolean).length;
        api.ui.toast(`${words} words`);
      },
    });
  }
}

Save the file. The command appears in the palette (⌘K) immediately — no restart, no rebuild.

Folder layout

A plugin is a folder with one required file:

.meridian/plugins/word-counter/
├── main.js          required
├── plugin.json      optional — metadata shown in Settings
└── README.md        optional — shown in Settings → Plugins

What plugins can do

The api object passed to onLoad lets plugins:

  • Register commands that appear in the command palette
  • React to vault events — note create, change, delete
  • Render side panels in the right sidebar
  • Show toasts and notices in the UI

See the source code in the repo for the full type definitions of the api object.

Hot reload

Save main.js and Meridian re-instantiates the plugin in a fresh context. The previous instance’s onUnload runs first. No restart needed.

Distribution

There is no plugin store. Publish the folder to a GitHub repo or share the zip — users drop it into their .meridian/plugins/ directory. That’s the whole pipeline.