fix(skill_manage): _find_skill follows symlinked skill directories - #56420
Closed
val-spc wants to merge 4 commits into
Closed
fix(skill_manage): _find_skill follows symlinked skill directories#56420val-spc wants to merge 4 commits into
val-spc wants to merge 4 commits into
Conversation
Path.rglob does NOT descend into symlinked directories. Skills installed
as directory symlinks (common in multi-profile setups and managed
deployments where ~/.hermes/skills/<namespace>/<slug> symlinks into a
git checkout) are invisible to rglob — but the skill *loader*
(iter_skill_index_files in agent/skill_utils.py) uses
os.walk(followlinks=True) and finds them fine.
This discrepancy meant skill_view could load a skill but skill_manage
could not find it for editing — returning "Skill '<name>' not found in
active profile 'default'" on every call. In our SPC deployment this
caused 575+ errors in 2 weeks across all 47 symlinked skills.
Fix: replace both rglob("SKILL.md") call sites in skill_manager_tool.py
(_find_skill and _find_skill_in_other_profiles) with
iter_skill_index_files(skills_dir, "SKILL.md"), which is the same
function the loader uses. The import already exists in agent.skill_utils.
Tests: two new tests in TestFindSkillSymlinks verify _find_skill and
_find_skill_in_other_profiles can resolve a skill whose directory is a
symlink. All 109 existing skill_manager_tool tests pass.
Co-authored-by: Sahil Shubham <sahil@southparkcommons.com>
Path.rglob does NOT descend into symlinked directories. Skills installed
as directory symlinks (common in multi-profile setups and managed
deployments where ~/.hermes/skills/<namespace>/<slug> symlinks into a
git checkout) are invisible to rglob — but the skill *loader*
(iter_skill_index_files in agent/skill_utils.py) uses
os.walk(followlinks=True) and finds them fine.
This discrepancy meant skill_view could load a skill but skill_manage
could not find it for editing — returning "Skill '<name>' not found in
active profile 'default'" on every call. In our SPC deployment this
caused 575+ errors in 2 weeks across all 47 symlinked skills.
Fix: replace both rglob("SKILL.md") call sites in skill_manager_tool.py
(_find_skill and _find_skill_in_other_profiles) with
iter_skill_index_files(skills_dir, "SKILL.md"), which is the same
function the loader uses. The import already exists in agent.skill_utils.
Tests: two new tests in TestFindSkillSymlinks verify _find_skill and
_find_skill_in_other_profiles can resolve a skill whose directory is a
symlink. All 109 existing skill_manager_tool tests pass.
Co-authored-by: Sahil Shubham <sahil@southparkcommons.com>
This was referenced Jul 31, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
Path.rglobdoes NOT descend into symlinked directories. Skills installed as directory symlinks (common in multi-profile setups and managed deployments where~/.hermes/skills/<namespace>/<slug>symlinks into a git checkout) are invisible torglob— but the skill loader (iter_skill_index_filesinagent/skill_utils.py) usesos.walk(followlinks=True)and finds them fine.This discrepancy meant
skill_viewcould load a skill butskill_managecould not find it for editing — returning"Skill '<name>' not found in active profile 'default'"on every call. In our SPC deployment this caused 575+ errors in 2 weeks across all 47 symlinked skills.Fix
Replace both
rglob("SKILL.md")call sites inskill_manager_tool.py:_find_skill(line ~581)_find_skill_in_other_profiles(line ~644)with
iter_skill_index_files(skills_dir, "SKILL.md"), which is the same function the skill loader uses. The import already exists inagent.skill_utils.Tests
Two new tests in
TestFindSkillSymlinks:test_find_skill_follows_symlinked_dir— verifies_find_skillcan resolve a skill whose directory is a symlinktest_find_skill_in_other_profiles_follows_symlinks— verifies the cross-profile search also follows symlinksAll 109 existing
skill_manager_tooltests pass.Impact
This bug affects any deployment where skills are installed as directory symlinks — which is the default behavior when using multiple profiles or managed dotfiles checkouts. The
skill_resolverplugin hook (if present) self-healsskill_viewfailures but does NOT interceptskill_manage, which goes through a separate_find_skill()code path.Co-authored-by: Sahil Shubham sahil@southparkcommons.com