hermes - 💡(How to fix) Fix Skills overlay architecture: separate bundled (upstream) from custom (user) layers [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#16852Fetched 2026-04-29 06:38:30
View on GitHub
Comments
0
Participants
1
Timeline
3
Reactions
0
Participants
Timeline (top)
labeled ×3

Fix Action

Fix / Workaround

~/.hermes/skills/
├── bundled/              ← managed, read-only for users, fully replaced on each update
│   ├── mlops/axolotl/
│   ├── media/youtube-content/
│   └── ...
├── custom/               ← user territory, never touched by update
│   ├── my-psychoanalysis-skill/
│   └── youtube-content.diff     ← patch against bundled version
└── .bundled_manifest

At runtime, skill resolution works in layers:

  1. Load the bundled skill (fresh copy every time after update)
  2. If a corresponding patch file exists in custom/, apply it in-memory before returning the skill to the agent
  3. Pure custom skills (no bundled counterpart) load directly from custom/

1. Patch Format

Code Example

~/.hermes/skills/
├── bundled/              ← managed, read-only for users, fully replaced on each update
│   ├── mlops/axolotl/
│   ├── media/youtube-content/
│   └── ...
├── custom/               ← user territory, never touched by update
│   ├── my-psychoanalysis-skill/
│   └── youtube-content.diff     ← patch against bundled version
└── .bundled_manifest
RAW_BUFFERClick to expand / collapse

Problem

Currently, bundled skills and user customizations live in the same flat directory (~/.hermes/skills/) without any distinction. When a user edits a bundled skill directly, the sync mechanism detects the hash mismatch and permanently skips upstream updates for that skill (see tools/skills_sync.py lines 256-261).

This means:

  • User who customizes a skill loses all future upstream improvements to it. The "fix" is to run hermes skills reset --restore, which destroys the customization entirely.
  • No way to layer a small user tweak on top of a skill that the upstream actively evolves.
  • No namespace separation between bundled skills and user-created skills — they coexist in the same tree, making it unclear what will be overwritten on next update.
  • The user has no way to know what upstream changed when their custom version was skipped.

Proposed Architecture: Overlay Layers

~/.hermes/skills/
├── bundled/              ← managed, read-only for users, fully replaced on each update
│   ├── mlops/axolotl/
│   ├── media/youtube-content/
│   └── ...
├── custom/               ← user territory, never touched by update
│   ├── my-psychoanalysis-skill/
│   └── youtube-content.diff     ← patch against bundled version
└── .bundled_manifest

At runtime, skill resolution works in layers:

  1. Load the bundled skill (fresh copy every time after update)
  2. If a corresponding patch file exists in custom/, apply it in-memory before returning the skill to the agent
  3. Pure custom skills (no bundled counterpart) load directly from custom/

Key Design Decisions to Resolve

1. Patch Format

  • Full-copy approach: custom/ stores the complete modified SKILL.md + supporting files. Simplest to implement, but means the user misses upstream changes to non-edited parts of the skill (e.g., upstream adds a new section: user never sees it).
  • Patch/diff approach: custom/ stores only the diff against the current bundled version. When upstream updates, the patch is re-applied. If the patch fails to apply (context changed), the system flags a conflict and falls back to keeping the user version.
  • Hybrid: Store the full modified copy, but also track which bundled version it was based on. On update, show the user a structured diff of upstream changes they missed.

2. Conflict Detection

When upstream changes conflict with a user patch, the system needs a fallback strategy:

  • Keep user version, mark conflict in CLI output
  • Offer a hermes skills merge <name> command that shows both versions side-by-side

3. CLI Commands

Current commands like hermes skills reset would need to be reframed for the overlay model. Suggested additions:

  • hermes skills diff <name> — show changes between bundled and user version
  • hermes skills patch <name> — create/edit a patch
  • hermes skills conflicts — list skills with unapplied patches

Scope

This touches:

  • tools/skills_sync.py — rewrite of sync logic for layered structure
  • agent/skill_commands.py — slash command resolution changes
  • cli.py / hermes_cli/ — update or add hermes skills subcommands
  • Migration: existing ~/.hermes/skills/ structure needs a one-time migration script

References

  • Current sync logic: tools/skills_sync.py lines 240-261 (user-modified skip)
  • Manifest-based tracking: .bundled_manifest with MD5 hashes
  • Skills load path: agent/skill_commands.py, tools/skills_tool.py

extent analysis

TL;DR

Implement an overlay layer architecture to separate bundled skills from user customizations, allowing for layered updates and conflict detection.

Guidance

  • Introduce a new directory structure with bundled/ and custom/ subdirectories to separate managed skills from user modifications.
  • Develop a patch format, such as a diff approach, to store user changes against the bundled version, enabling re-application of patches on upstream updates.
  • Implement conflict detection and a fallback strategy, such as keeping the user version and marking conflicts in CLI output.
  • Update CLI commands, like hermes skills diff and hermes skills patch, to support the new overlay model.

Example

# Example of a diff-based patch format
def apply_patch(bundled_skill, user_patch):
    # Load the bundled skill and user patch
    bundled_skill_content = load_skill(bundled_skill)
    user_patch_content = load_patch(user_patch)
    
    # Apply the patch to the bundled skill
    updated_skill = apply_diff(bundled_skill_content, user_patch_content)
    
    return updated_skill

Notes

The proposed architecture requires significant changes to the existing codebase, including the sync logic, skill resolution, and CLI commands. A one-time migration script will be necessary to update the existing ~/.hermes/skills/ structure.

Recommendation

Apply the workaround by implementing the proposed overlay layer architecture, as it addresses the current limitations and provides a more flexible and maintainable solution for managing bundled skills and user customizations.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING