verstak-desktop/docs/DEV_PLUGINS.md

4.7 KiB

Verstak Desktop — Development Plugin Flow

Overview

Official plugins live in the verstak-official-plugins monorepo and are developed separately from the desktop core. During development, plugins are installed into the desktop's local plugins/ directory as packaged bundles (not source code).

git/
  verstak-desktop/                ← desktop core
  verstak-official-plugins/       ← official plugin source + dist output

Plugin Source → Package Flow

  1. Source code lives in verstak-official-plugins/plugins/<plugin-id>/
  2. Running build.sh in official-plugins:
    • Builds frontend (if frontend/package.json exists)
    • Builds backend Go binary (if backend/main.go exists)
    • Packages the result into dist/<plugin-id>/
  3. Package structure (dist/platform-test/):
    plugin.json
    frontend/dist/index.js
    backend/platform-test          (compiled binary)
    

Installing Dev Plugins in Desktop

From the verstak-desktop/ directory:

./scripts/install-dev-plugins.sh

This script:

  • Locates ../verstak-official-plugins/
  • Builds packages there if dist/ is stale
  • Creates ./plugins/<plugin-id>/ from the dist package
  • Does not affect other plugins in ./plugins/

The plugins/ directory is in .gitignore — it is never committed.

Smoke Test

After installing, verify that the desktop runtime discovers the plugin:

./scripts/smoke-platform.sh

This validates:

  • Plugin directory exists
  • plugin.json manifest is valid
  • All required manifest fields are present
  • DiscoverPlugins() finds verstak.platform-test
  • Capabilities are registerable

Desktop Runtime Scanning Paths

The desktop resolves plugin directories in one shared backend resolver. Priority:

Path Purpose
VERSTAK_PLUGIN_DIR Dev/test override. Multiple paths can be separated with the OS path separator
./plugins/ Bundled/dev plugins relative to the current working directory
<binary-dir>/plugins/ Packaged plugins shipped next to the desktop executable
~/.config/verstak/plugins/ User-installed plugins

The resolver normalizes paths and removes duplicates before scanning. Missing directories are ignored by discovery.

Discovery scans all resolved directories in order. If two plugin packages declare the same id, the first package wins and later duplicates are skipped. The warning includes both package paths, so during development check the log if an updated plugin appears to be ignored.

Bundled Plugin API During Development

Frontend bundles are mounted with a plugin-scoped API created by createPluginAPI(pluginId). The current API supports:

  • settings.read/write/writeAll
  • capabilities.list/get/has
  • commands.register/execute for handlers declared in contributes.commands
  • events.publish/subscribe using the bundled frontend event bus
  • files.list/metadata/readText/writeText/createFolder/move/trash for canonical vault-relative slash paths guarded by files.read, files.write, and files.delete. Backslashes, Windows absolute paths, UNC paths, traversal, .verstak variants, and symlink read/write/move/trash operations are rejected. Text read/write is UTF-8 only and limited to 2 MB for reads.
  • workbench.openResource/editResource for routing vault resources to contributed openProviders. Plugins must declare workbench.open; this is a policy/contract check. Files and Notes plugins call this API and do not import a concrete editor plugin.

Editor/viewer plugins contribute providers with contributes.openProviders. Workbench selects by resource kind, extension/mime, context (generic-text, generic-markdown, notes-markdown), user preference, priority, then deterministic pluginId/providerId tie-break. If nothing matches, Workbench shows no-provider fallback instead of a core editor.

The official verstak.default-editor plugin provides three openProviders: verstak.default-editor.text (generic-text), verstak.default-editor.markdown (generic-markdown), and verstak.default-editor.notes-markdown (notes-context). It uses a single unified DefaultEditor component with textarea-based editing, simple markdown preview, dirty state tracking, and Ctrl+S save.

This is a cooperative contract, not a sandbox. Bundled plugins run in the same JS context as the desktop frontend; real isolation is deferred to the sidecar/sandbox milestone.

Important Rules

  • Never commit plugins/ to verstak-desktop — it's in .gitignore
  • Never copy source code from verstak-official-plugins/plugins/ directly — always use the dist package from verstak-official-plugins/dist/
  • Run install-dev-plugins.sh after any change in the plugin source
  • Run smoke-platform.sh after installing to verify discovery