hermes - 💡(How to fix) Fix [Bug]: hermes skills reset <name> without --restore returns misleading success message for user-modified bundled skills [2 pull requests]

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…

Root Cause

Two locations in tools/skills_sync.py:

1. Lines 409-411reset_bundled_skill() non---restore path:

action = "manifest_cleared"
message = (
    f"Cleared manifest entry for '{name}'. Future `hermes update` runs "
    f"will re-baseline against your current copy and accept upstream changes."
)

This is incorrect when the skill was modified. Clearing the manifest causes sync_skills() to treat it as a new skill conflict (lines 204-226), which skips the skill without writing a manifest entry when _dir_hash(dest) != bundled_hash. The next sync repeats the same loop.

2. Lines 222-225sync_skills() new-skill-conflict path:

print(
    f"  ⚠ {skill_name}: bundled version shipped but you "
    f"already have a local skill by this name — yours "
    f"was kept. Run `hermes skills reset {skill_name}` "
    f"to replace it with the bundled version."
)

Suggesting reset is circular—reset without --restore cannot replace anything for modified skills. The correct suggestion should be reset --restore.

Fix Action

Fixed

Code Example

action = "manifest_cleared"
message = (
    f"Cleared manifest entry for '{name}'. Future `hermes update` runs "
    f"will re-baseline against your current copy and accept upstream changes."
)

---

print(
    f"  ⚠ {skill_name}: bundled version shipped but you "
    f"already have a local skill by this name — yours "
    f"was kept. Run `hermes skills reset {skill_name}` "
    f"to replace it with the bundled version."
)
RAW_BUFFERClick to expand / collapse

Bug Description

When a user modifies a bundled skill (e.g. edits the SKILL.md in ~/.hermes/skills/), sync_skills() detects the hash mismatch and correctly marks it as user-modified, skipping future updates. However, hermes skills reset <name> (without --restore) claims to resolve this but actually does nothing for truly modified skills.

Two misleading messages are involved:

  1. reset_bundled_skill() returns: "Future hermes update runs will re-baseline against your current copy and accept upstream changes." — This is false when the skill was actually modified. The next sync_skills() call hits the not_in_manifest + dest.exists() + dir_hash(dest) != bundled_hash branch, which skips the skill without writing a manifest entry. The skill remains permanently skipped for future updates.

  2. sync_skills() prints: "yours was kept. Run hermes skills reset {name} to replace it with the bundled version." — But reset without --restore does not replace it. The user gets a circular suggestion: run reset → it says "yours was kept, run reset."

Steps to Reproduce

  1. Start Hermes. A bundled skill foo is synced to ~/.hermes/skills/foo/.
  2. Edit ~/.hermes/skills/foo/SKILL.md so the user hash diverges from the origin hash.
  3. Next launch: ~ foo (user-modified, skipping) is printed.
  4. Run hermes skills reset foo (no --restore). Output says "Cleared manifest entry for 'foo'. Future hermes update runs will re-baseline..."
  5. Next launch: ~ foo (user-modified, skipping) again. Nothing changed.

Expected Behavior

hermes skills reset <name> without --restore should either:

  • (a) Actually unblock the skill so future bundled updates can come in (write the current bundled hash into the manifest so the next sync can detect bundled-vs-user divergence properly), or
  • (b) Honestly tell the user "Your local copy is preserved and will never receive bundled updates. Use --restore to revert to the shipped version."

Actual Behavior

The command returns a success message that is demonstrably false for user-modified skills. The skill remains permanently stuck in "user-modified" limbo, and the command output implies a resolution that never happens.

Affected Component

Skills (skill loading, skill hub, skill guard)

Root Cause Analysis

Two locations in tools/skills_sync.py:

1. Lines 409-411reset_bundled_skill() non---restore path:

action = "manifest_cleared"
message = (
    f"Cleared manifest entry for '{name}'. Future `hermes update` runs "
    f"will re-baseline against your current copy and accept upstream changes."
)

This is incorrect when the skill was modified. Clearing the manifest causes sync_skills() to treat it as a new skill conflict (lines 204-226), which skips the skill without writing a manifest entry when _dir_hash(dest) != bundled_hash. The next sync repeats the same loop.

2. Lines 222-225sync_skills() new-skill-conflict path:

print(
    f"  ⚠ {skill_name}: bundled version shipped but you "
    f"already have a local skill by this name — yours "
    f"was kept. Run `hermes skills reset {skill_name}` "
    f"to replace it with the bundled version."
)

Suggesting reset is circular—reset without --restore cannot replace anything for modified skills. The correct suggestion should be reset --restore.

Proposed Fix

Option A (honest messaging, minimal fix): Fix the two messages to be accurate about what happens. The reset_bundled_skill() message should say something like: "Cleared manifest entry for '{name}'. If you modified this skill, your local copy is preserved and will not receive upstream updates. Use --restore to revert to the shipped version." The sync_skills() message should suggest hermes skills reset --restore instead of plain reset.

Option B (behavioral fix): Have reset without --restore record the current bundled hash in the manifest, so the next sync sees user_hash != origin_hash and processes it through the existing user-modified path (which at least warns predictably) rather than falling through to the new-skill-conflict path each time. This makes the behavior consistent and understandable.

Option C (full fix): Combine A + B, and add a --preserve-mine / --accept-upstream flag on reset to let the user choose explicitly.

Related Issues

  • #18402 — proposes offering reset for user-modified skills after update
  • #29714 — broader feature request for skill overlay lifecycle
  • #28121 — made user-modified skill names visible in sync output

Operating System

macOS 15.x

Hermes Version

Latest main

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

hermes - 💡(How to fix) Fix [Bug]: hermes skills reset <name> without --restore returns misleading success message for user-modified bundled skills [2 pull requests]