Graphite and yellow modular components arranged around a central metal hub
A desktop plugin should add a precise, reviewable module rather than blur the host application's boundaries.

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.js within the profile's desktop-plugins directory.
  • 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.