run-skill-generator: step-0 probe cannot see an existing skill in the target unit, silently rewrites it
What happened
Step 0 of the bundled run-skill-generator skill tells the agent to find any existing run-skill before writing one, using this probe:
d=$PWD; while :; do
grep -Hm1 '^description:' "$d"/.claude/skills/*/SKILL.md 2>/dev/null
[ -e "$d/.git" ] || [ "$d" = / ] && break
d=$(dirname "$d")
done
The probe only ever walks upward from $PWD. But the next section of the same skill tells the agent the unit is often a subdirectory:
Large repo with many apps: one per app, colocated —apps/billing/.claude/skills/run-billing/,apps/desktop/.claude/skills/run-desktop/
So whenever the chosen unit is below the invocation directory — the normal case in a monorepo, and the case the skill explicitly instructs you to handle by asking the user which app to target — an existing skill inside that unit is invisible to the probe. The agent concludes "no skill exists", takes the create branch, and overwrites SKILL.md wholesale.
This directly contradicts the skill's own instruction:
If one is about launching/driving this app — whatever it's named — refine, don't rewrite: verify its claims, fix what's wrong, add what's missing, preserve what works.
The shipped probe cannot satisfy that instruction in exactly the repo layout the skill recommends.
Steps to reproduce
- A repo
foo/with a committed skill atfoo/apps/bar/.claude/skills/run-bar/SKILL.md. cd foo, invoke/run-skill-generator.- The generator asks which unit to target; answer
apps/bar. - Run the step-0 probe from
foo: it checksfoo/.claude/skills/*/SKILL.md, then walks up to/. It never looks underapps/bar/. - Output is empty → the agent creates rather than refines, replacing the existing skill and its driver.
Observed
Invoked from a workspace directory; the operator selected a nested unit one level down. The probe returned nothing, but a skill was already committed in that unit, with a working driver script alongside it.
It was caught only by accident — an unrelated git worktree add checked the tracked files out, and a Write to SKILL.md then failed with "File has not been read yet". Without that guard the existing skill and its driver would have been silently replaced.
Worth noting: in that repo .claude/ is gitignored with the skill force-added, so git status gave no hint either. Any check based on working-tree dirtiness would also have missed it.
Suggested fixes
Any one closes it; the first two are cheap.
- Re-run the probe after entering the unit. Add to the discovery step: "once the unit is chosen, re-run the step-0 probe from inside it before deciding create-vs-refine."
- Search downward too. Replace the upward walk with a repo-wide lookup that also finds nested units, e.g.
``bash`
git ls-files '*/.claude/skills/*/SKILL.md' '.claude/skills/*/SKILL.md'
.claude/`.
This also catches force-added skills under a gitignored
- Make the create path non-destructive — refuse to overwrite an existing
SKILL.mdwithout an explicit read-and-merge step.
Environment
- Claude Code 2.1.220
- macOS (arm64)
- Bundled skill path:
bundled-skills/2.1.220/<hash>/run-skill-generator
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗