-
Notifications
You must be signed in to change notification settings - Fork 0
Plugin Development Deep Dive
Joshua Ivoe edited this page Apr 13, 2026
·
1 revision
This page explains advanced plugin engineering patterns for robust production plugins.
Start from host contracts, not implementation assumptions.
Primary references:
- ../../src/extensions/PluginContracts.h
- ../../src/extensions/PluginSettingsRegistry.h
- ../../src/extensions/SettingsSchema.h
- ../EXTENSIBILITY.md
Declare only required capabilities.
Examples:
- commands only plugin: avoid settings_pages capability if not used
- settings-only plugin: avoid menu capabilities if no UI entry point
- content provider plugin: include space_content_provider and implement refresh/state paths
Why: smaller blast radius and easier compatibility analysis.
- Use deterministic, namespaced command ids.
- Treat command handlers as failure boundaries.
- Never assume active space context exists.
- Validate all external input before state mutation.
Good pattern:
- Read context from appCommands
- Validate state
- Execute
- Emit diagnostics for warnings/failures
For every setting key:
- define default that is safe
- define clear key namespace
- avoid exposing implementation internals to consumers
- use enums for bounded choices
Migration pattern:
- new key read first
- fallback to legacy key
- mirror value during transition
- remove legacy path after validation period
Use host diagnostics intentionally:
- startup success/failure summaries
- invalid configuration warnings
- command failure context with key identifiers
Never crash host due to plugin issues.
Host behavior includes plugin fault isolation, but plugin code must still:
- guard external operations
- avoid throwing uncaught exceptions across boundaries
- fail closed for risky actions
If plugin supplies custom space content:
- keep provider id stable
- implement enumerate, drop, and delete semantics predictably
- map provider state to user-facing recoverable states
- support refresh without forcing host restart
- Treat file operations as high-risk.
- Prefer non-destructive defaults.
- Validate paths and ownership assumptions.
- Avoid hidden side effects in command handlers.
- avoid heavy work on UI paths
- debounce polling/refresh operations where needed
- cache expensive results with clear invalidation strategy
- measure before and after when changing refresh cadence
Before merge:
- Manifest compatibility verified
- Settings keys reviewed for naming and defaults
- Commands validated against all menu entry points
- Startup and shutdown paths tested
- Persistence behavior tested across restart
- Regression tests or manual proof added