skill-creator: run_eval.py writes skills to .claude/commands/, so description optimization always measures recall=0%
Summary
The skill-creator plugin's description-optimization harness (scripts/run_eval.py, driven by scripts/run_loop.py) writes the skill under test to .claude/commands/<name>.md. In current Claude Code builds, files in .claude/commands/ are slash commands (invoked explicitly via /name) and do not appear in the model's autonomously-selectable skills list. As a result, the skill under test can never trigger, every candidate description scores recall=0%, and the optimization loop silently returns the initial description as "best".
Environment
- Claude Code CLI (macOS, darwin 25.2.0)
- skill-creator invoked from
~/.claude/skills/skill-creator - Eval model:
claude-sonnet-5
Repro
- Create any skill with a broad description (ours: a "goal-first execution" discipline skill).
- Build a 20-query eval set (10 should-trigger / 10 should-not).
- Run:
``bash``
python3 -m scripts.run_loop \
--eval-set eval_set.json \
--skill-path <skill> \
--model claude-sonnet-5 --max-iterations 5 --verbose
- Observe every iteration reports
precision=100% recall=0%— should-trigger queries never trigger, across all candidate descriptions (each query run 3x).
Isolation
claude -p "hello"works fine — CLI itself is healthy.- A query that names the skill explicitly ("use the <name> skill for this") still scores as not-triggered under the harness's
.claude/commands/placement. - Moving the same content to
.claude/skills/<name>/SKILL.md(proper skill placement) and re-running the explicit-name query: the skill triggers (verified with a marker word in the skill body appearing in the response).
So the harness's placement is the bug: it measures triggering of a file that is not in the triggering surface at all.
Suggested fix
In run_single_query(), write the skill as .claude/skills/<clean_name>/SKILL.md with name + description frontmatter (and clean up the directory afterward) instead of a command file in .claude/commands/.
Related caveat (maybe worth documenting rather than fixing)
Even with correct placement, single-shot claude -p runs rarely trigger skills from natural-language queries (0/3 in our test with a realistic debugging query) — consistent with the documented behavior that skills are only consulted for tasks the model can't handle directly, which seems amplified in non-interactive mode. This makes -p-based trigger rates a weak proxy for interactive-session triggering even after the placement fix; the docs for the description-optimization loop may want to note this.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗