4.3 KiB
Plugin Authoring Guide
Slopsmith's plugin system is the primary extension point. Each plugin lives in plugins/<name>/ with a plugin.json manifest that declares the capability domains, UI contributions, settings metadata, diagnostics, and runtime files the plugin participates in.
This guide is the entry point. Each topic below has a dedicated doc — read what's relevant to what you're building.
Quickstart
plugins/my_plugin/
├── plugin.json Manifest (required) — see docs/plugin-manifest.md
├── screen.html Optional — UI declared through `ui` contributions
├── screen.js Optional — hydrates declared frontend capabilities
├── routes.py Optional — backend provider/requester implementation
├── settings.html Optional — settings UI declared through `ui.settings`
└── requirements.txt Optional — pip deps auto-installed on load
Start every new plugin by describing its Slopsmith-facing behavior in the manifest. A plugin with no behavior beyond metadata can be this small:
{
"id": "my_plugin",
"name": "My Plugin",
"version": "0.1.0"
}
Any plugin that participates in app behavior should also declare standards: ["capability-pipelines.v1"], native capabilities, and redaction-safe ui metadata. Capability declarations are the source of truth for diagnostics, the Capability Inspector, and migration tooling.
Topics
| Topic | Doc | When to read |
|---|---|---|
| Manifest reference | plugin-manifest.md | Field-by-field reference for plugin.json. Read first. |
| Capability declarations | plugin-manifest.md#capabilities | Declaring provider/requester/observer intent with capability-pipelines.v1. |
| Capability domains | capability-domains.md | Active domains, planned domains, and promotion rules. |
| Capability recipes | capability-recipes.md | Copyable manifest patterns for provider/requester/observer plugins. |
| Visualization contracts | plugin-visualization-contracts.md | Building a highway renderer (setRenderer), an overlay layer, or a note-state provider. |
| Plugin styles | plugin-styles.md | Shipping a plugin-owned prebuilt stylesheet via styles: "assets/plugin.css". |
| Backend logging | plugin-logging.md | Plugin has a routes.py. Use context["log"], never print(). |
| Diagnostics contribution | plugin-diagnostics.md | Adding plugin state to the Export Diagnostics bundle. |
| Sibling Python imports | plugin-sibling-imports.md | Multi-file backend plugins. Use context["load_sibling"]. |
| WebSocket protocol | websocket-protocol.md | Plugins that read the highway stream directly. |
| Testing plugins | testing-plugins.md | Conftest fixtures and Playwright patterns for plugin tests. |
| Diagnostics bundle spec | diagnostics-bundle-spec.md | Existing in-depth spec — what's inside a diagnostics export. |
| Sloppak format spec | sloppak-spec.md | Existing in-depth spec — for plugins that read/write sloppaks. |
General guidelines
- Wrap your plugin code in an IIFE:
(function () { 'use strict'; ... })(); - Declare
standards: ["capability-pipelines.v1"]and nativecapabilitieswhen your plugin participates in a Slopsmith capability domain. - Use
ui/ui_contributionsfor plugin-owned UI surfaces so the host can attribute them in diagnostics and support bundles. - Use
localStoragefor user-facing settings, prefixed with your plugin id. - Prefer native capability commands, events, and provider registration over private globals. If a domain you need is not active yet, document the gap in the PR instead of baking in a new private integration.
Licensing for curated plugins
Plugins submitted for inclusion in the curated list must be AGPL-3.0 or AGPL-compatible (MIT, BSD, Apache-2.0). See CONTRIBUTING.md for the full policy. The plugin.json schema enforces this via the license field enum — see plugin-manifest.md.