Adds plugin management with three interfaces: hermes plugins # interactive curses checklist (like hermes tools) hermes plugins enable # non-interactive enable hermes plugins disable # non-interactive disable hermes plugins list # table with status column Disabled plugins are stored in config.yaml under plugins.disabled and skipped during discovery. Uses the same curses_checklist component as hermes tools for the interactive UI. Changes: - hermes_cli/plugins.py: _get_disabled_plugins() + skip disabled during discover_and_load() - hermes_cli/plugins_cmd.py: cmd_toggle() interactive UI, cmd_enable(), cmd_disable(), updated cmd_list() with status column - hermes_cli/main.py: enable/disable subparser entries - website/docs/reference/cli-commands.md: updated plugins section - website/docs/user-guide/features/plugins.md: updated managing section
4.6 KiB
sidebar_position
| sidebar_position |
|---|
| 20 |
Plugins
Hermes has a plugin system for adding custom tools, hooks, slash commands, and integrations without modifying core code.
→ Build a Hermes Plugin — step-by-step guide with a complete working example.
Quick overview
Drop a directory into ~/.hermes/plugins/ with a plugin.yaml and Python code:
~/.hermes/plugins/my-plugin/
├── plugin.yaml # manifest
├── __init__.py # register() — wires schemas to handlers
├── schemas.py # tool schemas (what the LLM sees)
└── tools.py # tool handlers (what runs when called)
Start Hermes — your tools appear alongside built-in tools. The model can call them immediately.
Project-local plugins under ./.hermes/plugins/ are disabled by default. Enable them only for trusted repositories by setting HERMES_ENABLE_PROJECT_PLUGINS=true before starting Hermes.
What plugins can do
| Capability | How |
|---|---|
| Add tools | ctx.register_tool(name, schema, handler) |
| Add hooks | ctx.register_hook("post_tool_call", callback) |
| Add slash commands | ctx.register_command("mycommand", handler) |
| Ship data files | Path(__file__).parent / "data" / "file.yaml" |
| Bundle skills | Copy skill.md to ~/.hermes/skills/ at load time |
| Gate on env vars | requires_env: [API_KEY] in plugin.yaml |
| Distribute via pip | [project.entry-points."hermes_agent.plugins"] |
Plugin discovery
| Source | Path | Use case |
|---|---|---|
| User | ~/.hermes/plugins/ |
Personal plugins |
| Project | .hermes/plugins/ |
Project-specific plugins (requires HERMES_ENABLE_PROJECT_PLUGINS=true) |
| pip | hermes_agent.plugins entry_points |
Distributed packages |
Available hooks
Plugins can register callbacks for these lifecycle events. See the Event Hooks page for full details, callback signatures, and examples.
| Hook | Fires when |
|---|---|
pre_tool_call |
Before any tool executes |
post_tool_call |
After any tool returns |
pre_llm_call |
Once per turn, before the LLM loop — can return {"context": "..."} to inject into the system prompt |
post_llm_call |
Once per turn, after the LLM loop completes |
on_session_start |
New session created (first turn only) |
on_session_end |
End of every run_conversation call |
Slash commands
Plugins can register slash commands that work in both CLI and messaging platforms:
def register(ctx):
ctx.register_command(
name="greet",
handler=lambda args: f"Hello, {args or 'world'}!",
description="Greet someone",
args_hint="[name]",
aliases=("hi",),
)
The handler receives the argument string (everything after /greet) and returns a string to display. Registered commands automatically appear in /help, tab autocomplete, Telegram bot menu, and Slack subcommand mapping.
| Parameter | Description |
|---|---|
name |
Command name without slash |
handler |
Callable that takes args: str and returns `str |
description |
Shown in /help |
args_hint |
Usage hint, e.g. "[name]" |
aliases |
Tuple of alternative names |
cli_only |
Only available in CLI |
gateway_only |
Only available in messaging platforms |
gateway_config_gate |
Config dotpath (e.g. "display.my_option"). When set on a cli_only command, the command becomes available in the gateway if the config value is truthy. |
Managing plugins
hermes plugins # interactive toggle UI — enable/disable with checkboxes
hermes plugins list # table view with enabled/disabled status
hermes plugins install user/repo # install from Git
hermes plugins update my-plugin # pull latest
hermes plugins remove my-plugin # uninstall
hermes plugins enable my-plugin # re-enable a disabled plugin
hermes plugins disable my-plugin # disable without removing
Running hermes plugins with no arguments launches an interactive curses checklist (same UI as hermes tools) where you can toggle plugins on/off with arrow keys and space.
Disabled plugins remain installed but are skipped during loading. The disabled list is stored in config.yaml under plugins.disabled:
plugins:
disabled:
- my-noisy-plugin
In a running session, /plugins shows which plugins are currently loaded.
See the full guide for handler contracts, schema format, hook behavior, error handling, and common mistakes.