
Build a Hermes Desktop Plugin with the Official SDK
Hermes Desktop disk plugins can add panes, pages, navigation entries, status or title-bar items, palette commands, keybindings, themes, and composer extensions. A plugin is a single ESM file at $HERMES_HOME/desktop-plugins/<id>/plugin.js that default-exports a HermesPlugin.
Respect the extension boundary
Disk plugins require no build step and hot-reload during development. Imports are intentionally restricted to the official SDK, React, and the JSX runtime. This system is separate from web-dashboard plugins and from Python CLI or gateway plugins; do not mix their APIs or packaging conventions.
A plugin may also have a Python plugin_api.py backend, but backend loading is separately gated by plugins.enabled. Treat that as a stronger trust boundary because Python code can reach host capabilities that a UI contribution cannot.
Build checklist
- Choose a unique stable plugin ID.
- Keep
plugin.jswithin the profile'sdesktop-pluginsdirectory. - Import only documented SDK and React surfaces.
- Give every command and keybinding a clear, non-conflicting name.
- Make the UI useful without requiring an optional backend.
- Enable and review Python backend code separately.
- Test hot reload, disable, and uninstall paths.
Common pitfalls
- Confusing Desktop plugins with dashboard plugins. They are different extension systems.
- Importing arbitrary packages. Disk-plugin imports are deliberately allowlisted.
- Putting secrets in frontend code. UI modules are not secret storage.
- Treating hot reload as release QA. Reload success does not prove navigation, keyboard, or profile isolation.
Verification
Load the plugin in a disposable profile, exercise every contributed surface, inspect the Desktop console, and verify disable or removal returns the app to its prior state. If a Python backend exists, confirm plugins.enabled gates it and test unauthorized or malformed calls.
Official reference: Hermes Desktop Plugin SDK.
