Plugins now require explicit consent to load. Discovery still finds every plugin — user-installed, bundled, and pip — so they all show up in `hermes plugins` and `/plugins`, but the loader only instantiates plugins whose name appears in `plugins.enabled` in config.yaml. This removes the previous ambient-execution risk where a newly-installed or bundled plugin could register hooks, tools, and commands on first run without the user opting in. The three-state model is now explicit: enabled — in plugins.enabled, loads on next session disabled — in plugins.disabled, never loads (wins over enabled) not enabled — discovered but never opted in (default for new installs) `hermes plugins install <repo>` prompts "Enable 'name' now? [y/N]" (defaults to no). New `--enable` / `--no-enable` flags skip the prompt for scripted installs. `hermes plugins enable/disable` manage both lists so a disabled plugin stays explicitly off even if something later adds it to enabled. Config migration (schema v20 → v21): existing user plugins already installed under ~/.hermes/plugins/ (minus anything in plugins.disabled) are auto-grandfathered into plugins.enabled so upgrades don't silently break working setups. Bundled plugins are NOT grandfathered — even existing users have to opt in explicitly. Also: HERMES_DISABLE_BUNDLED_PLUGINS env var removed (redundant with opt-in default), cmd_list now shows bundled + user plugins together with their three-state status, interactive UI tags bundled entries [bundled], docs updated across plugins.md and built-in-plugins.md. Validation: 442 plugin/config tests pass. E2E: fresh install discovers disk-cleanup but does not load it; `hermes plugins enable disk-cleanup` activates hooks; migration grandfathers existing user plugins correctly while leaving bundled plugins off.
5.5 KiB
| sidebar_position | sidebar_label | title | description |
|---|---|---|---|
| 12 | Built-in Plugins | Built-in Plugins | Plugins shipped with Hermes Agent that run automatically via lifecycle hooks — disk-cleanup and friends |
Built-in Plugins
Hermes ships a small set of plugins bundled with the repository. They live under <repo>/plugins/<name>/ and load automatically alongside user-installed plugins in ~/.hermes/plugins/. They use the same plugin surface as third-party plugins — hooks, tools, slash commands — just maintained in-tree.
See the Plugins page for the general plugin system, and Build a Hermes Plugin to write your own.
How discovery works
The PluginManager scans four sources, in order:
- Bundled —
<repo>/plugins/<name>/(what this page documents) - User —
~/.hermes/plugins/<name>/ - Project —
./.hermes/plugins/<name>/(requiresHERMES_ENABLE_PROJECT_PLUGINS=1) - Pip entry points —
hermes_agent.plugins
On name collision, later sources win — a user plugin named disk-cleanup would replace the bundled one.
plugins/memory/ and plugins/context_engine/ are deliberately excluded from bundled scanning. Those directories use their own discovery paths because memory providers and context engines are single-select providers configured through hermes memory setup / context.engine in config.
Bundled plugins are opt-in
Bundled plugins ship disabled. Discovery finds them (they appear in hermes plugins list and the interactive hermes plugins UI), but none load until you explicitly enable them:
hermes plugins enable disk-cleanup
Or via ~/.hermes/config.yaml:
plugins:
enabled:
- disk-cleanup
This is the same mechanism user-installed plugins use. Bundled plugins are never auto-enabled — not on fresh install, not for existing users upgrading to a newer Hermes. You always opt in explicitly.
To turn a bundled plugin off again:
hermes plugins disable disk-cleanup
# or: remove it from plugins.enabled in config.yaml
Currently shipped
disk-cleanup
Auto-tracks and removes ephemeral files created during sessions — test scripts, temp outputs, cron logs, stale chrome profiles — without requiring the agent to remember to call a tool.
How it works:
| Hook | Behaviour |
|---|---|
post_tool_call |
When write_file / terminal / patch creates a file matching test_*, tmp_*, or *.test.* inside HERMES_HOME or /tmp/hermes-*, track it silently as test / temp / cron-output. |
on_session_end |
If any test files were auto-tracked during the turn, run the safe quick cleanup and log a one-line summary. Stays silent otherwise. |
Deletion rules:
| Category | Threshold | Confirmation |
|---|---|---|
test |
every session end | Never |
temp |
>7 days since tracked | Never |
cron-output |
>14 days since tracked | Never |
| empty dirs under HERMES_HOME | always | Never |
research |
>30 days, beyond 10 newest | Always (deep only) |
chrome-profile |
>14 days since tracked | Always (deep only) |
| files >500 MB | never auto | Always (deep only) |
Slash command — /disk-cleanup available in both CLI and gateway sessions:
/disk-cleanup status # breakdown + top-10 largest
/disk-cleanup dry-run # preview without deleting
/disk-cleanup quick # run safe cleanup now
/disk-cleanup deep # quick + list items needing confirmation
/disk-cleanup track <path> <category> # manual tracking
/disk-cleanup forget <path> # stop tracking (does not delete)
State — everything lives at $HERMES_HOME/disk-cleanup/:
| File | Contents |
|---|---|
tracked.json |
Tracked paths with category, size, and timestamp |
tracked.json.bak |
Atomic-write backup of the above |
cleanup.log |
Append-only audit trail of every track / skip / reject / delete |
Safety — cleanup only ever touches paths under HERMES_HOME or /tmp/hermes-*. Windows mounts (/mnt/c/...) are rejected. Well-known top-level state dirs (logs/, memories/, sessions/, cron/, cache/, skills/, plugins/, disk-cleanup/ itself) are never removed even when empty — a fresh install does not get gutted on first session end.
Enabling: hermes plugins enable disk-cleanup (or check the box in hermes plugins).
Disabling again: hermes plugins disable disk-cleanup.
Adding a bundled plugin
Bundled plugins are written exactly like any other Hermes plugin — see Build a Hermes Plugin. The only differences are:
- Directory lives at
<repo>/plugins/<name>/instead of~/.hermes/plugins/<name>/ - Manifest source is reported as
bundledinhermes plugins list - User plugins with the same name override the bundled version
A plugin is a good candidate for bundling when:
- It has no optional dependencies (or they're already
pip install .[all]deps) - The behaviour benefits most users and is opt-out rather than opt-in
- The logic ties into lifecycle hooks that the agent would otherwise have to remember to invoke
- It complements a core capability without expanding the model-visible tool surface
Counter-examples — things that should stay as user-installable plugins, not bundled: third-party integrations with API keys, niche workflows, large dependency trees, anything that would meaningfully change agent behaviour by default.