diagnosing-plugins
Skill6 starsChanged 8 days agoMITView on GitHub
Diagnose Hermes plugins that do not load or run — the plugins.enabled opt-in gate, capability consent, discovery locations, and sub-category selection keys.
In this repository32 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- diagnosing-authSkill
- diagnosing-backupSkill
- diagnosing-bot-modeSkill
- diagnosing-browserSkill
- diagnosing-cli-tuiSkill
- diagnosing-commandsSkill
- diagnosing-configSkill
- diagnosing-cronSkill
- diagnosing-desktopSkill
- diagnosing-gatewaySkill
- diagnosing-hooksSkill
- diagnosing-host-pressureSkill
- diagnosing-mcpSkill
- diagnosing-memoriesSkill
- diagnosing-memorySkill
- diagnosing-pathSkill
- diagnosing-profilesSkill
- diagnosing-providersSkill
- diagnosing-runtimeSkill
- diagnosing-secretsSkill
- diagnosing-sessionsSkill
- diagnosing-skillsSkill
- diagnosing-storageSkill
- diagnosing-triageSkill
- diagnosing-updateSkill
- diagnosing-voiceSkill
- hermes-configuration-guideSkill
- hermes-post-updateSkill
- installing-hermesSkill
- plugin-authoringSkill
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 73
After applying the fix:
- Very specific: line 100
Run hermes plugins enable my-plugin, then restart the session.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Diagnosing Plugins
A Hermes plugin is a Python package: a directory with a plugin.yaml manifest and a register(ctx) function. The single most common failure: the plugin is discovered but not enabled — Hermes deliberately loads nothing from third-party code until you add it to plugins.enabled.
Disambiguation: if a provider sub-category (e.g.
context.engine,image_gen.provider) is misconfigured, seediagnosing-providers— that is a provider configuration problem, not a plugin-loading problem.
1. Discovery locations (later sources override same-name earlier ones)
| Source | Path | Gate |
| Bundled | <install>/plugins/ | Platform/backend sub-plugins auto-load; bundled standalone plugins still need opt-in |
| User | $HERMES_HOME/plugins/<name>/ | plugins.enabled allow-list |
| Project | <repo>/.hermes/plugins/ | Requires HERMES_ENABLE_PROJECT_PLUGINS=true at startup |
| pip | hermes_agent.plugins entry points | plugins.enabled |
| Nix | services.hermes-agent.extraPlugins | Nix config |
hermes plugins install owner/repo [--ref <40-char SHA>] [--enable|--no-enable] installs from Git (pinned commits only); hermes plugins update refuses to move a pinned plugin. Sub-category directories have their own loaders and selection keys — they do not obey plugins.enabled. Verified present at current main: platforms/<name>/ (messaging channels, gated per messaging platform in config), memory/<name>/ (one active, memory.provider), context_engine/<name>/ (context.engine), model-providers/<name>/ (picked via --provider/config), image_gen/<name>/ (image_gen.provider), plus browser/, video_gen/, cron_providers/, dashboard_auth/, web/, computer_use/ (plugins/computer_use/__init__.py: bundled plugins/computer_use/<name>/ providers plus the built-in cua driver, one active), and delegation/ (delegation.backend selects the bundled strategy; the default strategy then reads delegation.provider / model / base_url; plugins/delegation/default/plugin.yaml). observability/ is not one of these — it was listed here from v2026.9.11 until 2026-10-19 but plugins/observability/ exists neither at the pinned baseline nor at upstream main. Not every bundled entry auto-loads: upstream's discovery reports disabled bundled plugins as "not enabled in config (run hermes plugins enable <key> to activate)" (hermes_cli/plugins_discovery.py), and bundled Kanban is one of them — check hermes plugins list for the real state instead of assuming a bundled directory is live. The set grows — list plugins/ in the installed source instead of trusting this list.
2. The enable gate and capabilities
plugins:
enabled: [my-plugin]
disabled: [noisy-plugin] # deny-list always wins over enabledThree ways to flip: hermes plugins (interactive), hermes plugins enable <name>, hermes plugins disable <name>. Declared capabilities require a separate one-time consent recorded under plugins.entries.<id>.granted_capabilities (legacy allow_* keys are still read). Verified capability ids at current main: tools.override and gateway.platform_actions — this list is code-defined and grows, so check plugin_capability_granted() / ctx.has_capability() rather than trusting any doc (an earlier revision of this skill named a llm.model_override id that does not exist). Two behaviours worth knowing: bundled plugins are trusted for tools.override (no consent needed), and unknown ids or unreadable consent fail closed (False). Non-interactive installs/enables grant nothing — the plugin runs with capabilities off and must degrade gracefully (ctx.has_capability()).
3. How to inspect
hermes plugins— interactive UI (SPACE toggles enabled).hermes plugins list— enabled / disabled / not-enabled per plugin.hermes plugins capabilities [name]— declared vs granted./pluginsin chat — status listing.hermes logs --follow— a plugin whoseregister()raises is skipped with a logged error (never crashes Hermes), so read the log for load failures.
4. Pitfalls (symptom → cause → fix)
- Installed but tools/hooks/commands absent — not in
plugins.enabled(install defaults to disabled;--enableor the post-install prompt is opt-in). → Permanent: add it toplugins.enabled(hermes plugins enable <name>) and restart. Temporary: there is no read-only way to load a disabled plugin — enabling is the fix, so do it deliberately rather than working around it. Bundled standalone plugins are opt-in too — only platform/backend sub-plugins auto-load. - Plugin works but a privileged feature is off — capability declared but never granted (non-TTY install, or declined). →
hermes plugins capabilities <name>; re-consent via interactivehermes plugins enable <name>. - Project plugin ignored —
.hermes/plugins/is disabled by default. → SetHERMES_ENABLE_PROJECT_PLUGINS=truebefore starting Hermes, and only for trusted repos. - Plugin in
listbut nothing loads at all —register()raised (bad code, missing dependency). → Checkhermes logsfor the load error; fix the plugin or its requirements. If the log instead saysload timed out after Ns(optionally followed bycalled register_*() after its load timed out; ignored), the loader's own budget expired beforeimport()+register()returned. That budget covers the plugin's work as much as the host's, so the message alone does not tell you which one was too slow — a slow import or a blockingregister()reaches the same deadline on a healthy host. Compare the configuredplugins.load_timeout_secondsagainst what that plugin's import andregister()actually do, and rundiagnosing-host-pressure(bash skills/diagnosing-host-pressure/scripts/host_pressure_probe.sh) to rule the host in or out. Only treat it as host pressure once the probe says so. Re-run the same load once before blaming either side: a cold first load — fresh install, pin change, empty caches — can exceed the default on a slow host and pass on immediate retry. The loader's per-plugin budget is configurable:plugins.load_timeout_secondsinconfig.yaml(default 10; negatives and non-numbers fall back to 10 with a warning; values above 600 clamp to 600;0disables the deadline and loads the plugin inline) — raise it or set it to0only once the probe or a repeated pattern establishes the cause, then restart. - Edits to a bundled plugin don't apply — a same-name user plugin at
$HERMES_HOME/plugins/<name>/overrides the bundled copy. → Edit the user copy (the one that actually wins) or remove it. hermes plugins updaterefuses — the install is pinned to an exact commit SHA. → Choose a new commit explicitly:hermes plugins install <source> --force --ref <new-sha>. Note:--forceexists oninstallonly, NOT onupdate(which takes just a name). To bypass a security-scan block onupdate, temporarily setplugins.scan_on_install: falsethen restore totrue. Manualgit pullin the plugin checkout bypasses the supported scan path and is not recommended. 6b. CLI surface check fails on skill edits — citing a non-existent CLI flag/subcommand in a skill causestools/check_cli_surface.pyto fail. Verify flags against the live CLI or the CLI surface test before adding them to skills; when the review says a flag exists in upstream but not in the checked CLI, revert to the supported form.- Plugin edits after install lost on update — updates autostash and re-apply local edits, but conflicts can drop them. → Keep plugin customizations in your own fork/repo and install from that.
- It's not really a plugin — TTS/STT command providers are config-driven (
tts.providers.<name>/stt.providers.<name>withtype: command); MCP integrations aremcp_servers:entries; gateway hooks are directories. → Route to the right surface:diagnosing-mcp,diagnosing-hooks, or the config docs. - Core plugin gone after update (e.g. Spotify) — some bundled plugins moved to the catalog; an enabled entry with no matching directory is not a broken install. →
hermes plugins install <name>from the catalog (or remove it fromplugins.enabled). - Installed directory exists but the plugin is never listed — discovery could not read the directory, so it skipped it and moved on:
Skipping unreadable plugin directory <path>: [WinError 5] Access is denied(Windows) orPermission denied(POSIX).hermes plugins listsimply omits the plugin, andhermes update/hermes pm installaddsCould not inspect plugin manifest <path>/plugin.yaml. → Check the ACL:icacls <path>failing withAccess is denied, or on Windowsdir /qshowing an owner other than you, means the DACL grants your account no read (an orphaned owner SID does this). Fix from an elevated prompt —takeown /f <path> /r /d Ythenicacls <path> /grant "<you>:(OI)(CI)F" /T— or delete the directory and reinstall the plugin, then confirm it appears inhermes plugins list. Skipping one unreadable directory is deliberate: it must not abort discovery for every other plugin (hermes_cli/plugins_discovery.py::scan_directory;hermes_cli/config.py::_platform_plugin_manifests). hermes plugins updateblocked by security scan — community plugins with many LOW findings (e.g., persistence warnings) get a "Blocked (community source + caution verdict)" decision. → Fix 1: if the plugin is pinned to an exact SHA, usehermes plugins install <source> --force --ref <new-sha>(pitfall 6). Fix 2: if you temporarily setplugins.scan_on_install: falseinconfig.yamlto bypass the scan, restore it totrueafter the update. Manualgit pullin the plugin checkout bypasses the supported scan path and is not recommended. Non-interactive installs with missing dependencies require--yes-deps(without it: "Non-interactive install — skipping dependency install" then "Reinstall declined"). The scan error message says "Use --force to override" butupdatehas no--forceflag — known upstream issue. If a displayed version looks stale, check the discovered plugin directory and its manifest (the list reads installed manifests). Scanner scans the entire repo (tests, docs, CI configs) producing false positives — known upstream issue.
5. Localization workflow
hermes plugins list— is it discovered? No → wrong location / not installed (§1 table; project plugins → pitfall 3).- Discovered but "not enabled" → pitfall 1 (
hermes plugins enable). - Enabled but broken →
hermes logsfor aregister()failure (pitfall 4) or a capability gap (pitfall 2). A load-timeout message alone does not tell you which side was slow — check pitfall 4 and rundiagnosing-host-pressure(bash skills/diagnosing-host-pressure/scripts/host_pressure_probe.sh) to rule the host in or out; only treat it as host pressure once the probe says so. - Sub-category plugin (memory/context/model-provider/platform) → check its selection key in config, not
plugins.enabled. - Restart the session/gateway and verify: tools appear in
/tools list, commands in/autocomplete, hooks viahermes hooks list. - Re-run the detector:
hermes guide pluginsheadless or/hermes-doctor pluginsin-session;+means healthy,~means informational, andx/?means unresolved.
Verification
After applying the fix:
hermes plugins list # plugin shows enabled
hermes plugins capabilities <name> # capabilities granted
hermes guide plugins # plugin check healthyPass: plugin enabled with correct capabilities; no load errors in logs.
Fail: re-check the pitfall matched and re-apply the fix.
Report
This skill diagnoses plugins that do not load or run — the plugins.enabled opt-in gate, capability consent, discovery locations, and provider sub-categories. When you run the diagnostic workflow, present findings in the standard format below.
Summary
Your plugin is installed but its tools and commands are absent because it is not in the plugins.enabled allowlist. Hermes deliberately loads nothing from third-party code until you explicitly enable it.
Findings
| Severity | What | Evidence |
| HIGH | Plugin not in plugins.enabled | hermes plugins list shows my-plugin: not enabled; no tools or commands from the plugin appear in the session |
| MEDIUM | Plugin discovered but not enabled after install | hermes plugins list shows the plugin under "Installed" but not under "Enabled" |
Recommended Fix
Run hermes plugins enable my-plugin, then restart the session. Verify with hermes plugins list (should show "Enabled") and check that the plugin's tools appear in /tools list.
References
$HERMES_HOME/config.yaml—plugins.enabledlisthermes_cli/plugins.py—plugins.enabledhandlinghermes_cli/plugins_discovery.py— plugin discovery and "not enabled" message
Facts re-verified 2026-10-26 against upstream source at commit edfa1c2a135532a8b64f7825c0ac0af6cfe73d4d: has_capability now lives on hermes_cli/plugins_capability_ctx.py::PluginCapabilityCtxMixin (it moved out of hermes_cli/plugins.py in upstream a8db834, 2026-10-23); the capability set and fail-closed behaviour are unchanged. Earlier entry, 2026-09-28 at 46a0daee58abbc1b07f84f505a5ba90f1958295c (corrective pass): entry-point group hermes_agent.plugins and the project-plugins gate HERMES_ENABLE_PROJECT_PLUGINS (plugins/memory/__init__.py, hermes_cli/plugin_dev.py); the capability set and fail-closed behaviour (hermes_cli/plugins_capability_ctx.py::has_capability, plugin_capability_granted); plugins.enabled handling (hermes_cli/plugins.py); the sub-category directory list (plugins/, narrowed in the corrective pass — bundled Kanban is gated by plugins.enabled, per hermes_cli/plugins_discovery.py); selection keys context.engine (hermes_cli/web_server_config.py) and image_gen.provider (agent/image_gen_*.py). One claim was corrected (the nonexistent llm.model_override id). Spotify core-to-catalog move verified 2026-10-15 against the installed source at 9bda154d (v0.21.7): absent from bundled plugins/, present as official catalog entry (spotify 2.0.0); migration in hermes_cli/left_core_migration.py. Sub-category directory list re-verified 2026-10-19 against upstream main (git ls-tree -d on plugins/, and plugins/computer_use/__init__.py): the guide's pin gained computer_use/ -- a provider directory with no plugin.yaml of its own and its own selection key -- and lost observability/, which was never an upstream directory (absent at baseline d97007c, at upstream main, and at every fetched commit). Upstream plugins/ lists the same 22 directories at both ends of the window, so the 44->46 VALID_HOOKS growth and the post_compaction / on_session_delete additions need no change here -- those names are read from the installed source, never enumerated. Re-verified 2026-10-20 against the installed source at dd519c74 (v0.22.2+1915): the per-plugin load deadline is configurable via plugins.load_timeout_seconds — default 10s, negatives and non-numbers fall back to 10 with a warning, >600 clamps to 600, 0 disables the deadline and loads inline (hermes_cli/plugins_loader.py::_resolve_plugin_load_timeout, hermes_cli/plugins_loader.py::run_with_load_deadline); matching observation on this host: one cold first load after a fresh pin-install timed out on the default and the immediate retry passed (hermes plugins doctor hermes-guide --ci: rc=1 once, then rc=0 twice). Corrected 2026-10-20: the budget is per plugin, not global, and it is set only in config -- no plugin's __init__.py carries a load-timeout figure. Re-verified 2026-10-20 against the installed source at 9bda154d: an unsearchable plugin directory is skipped with a warning and the plugin is absent from discovery (hermes_cli/plugins_discovery.py::scan_directory), and the platform-manifest scan records the skip (hermes_cli/config.py::_platform_plugin_manifests); observed on this host (Windows, WinError 5) on a directory owned by an unresolved SID. Re-checked 2026-10-23 against upstream main: plugins/delegation/<name>/ plugins are kind: backend, selected by delegation.backend; the bundled default strategy then reads delegation.provider / model / base_url (agent/delegation_registry.py, plugins/delegation/default/plugin.yaml, website/docs/developer-guide/delegation-provider-plugin.md). Upstream discovery scans plugins/delegation/ (it is not in the excluded-category set), so it is documented here but deliberately not in constants.PLUGIN_SUBCATEGORY_DIRS, which drives the guide's discovery skip. Re-verify before reuse. CLI update facts re-verified 2026-10-31 against upstream main 7020ea3e96c3fdbc768c5296493e186df46f075b: hermes plugins update refuses pinned installs (hermes_cli/plugins_cmd_update.py::_pull_plugin_update, hermes_cli/plugins_cmd_git.py::pinned_revision) and has no --ref (--force only accepts a caution scan verdict; it does not move a pinned install); escape: install <source> --force --ref <40-hex> to move a pin (install <source> --force alone keeps the pinned revision and does not unpin); --yes-deps covers Python dependency consent only (Node dependencies still prompt interactively); plugins.scan_on_install temporarily disables the scan; the scanner scans the whole repo (tests/docs/CI), producing false positives. Re-verify before reuse.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

