[BUG] Skill loader silently drops project-level SKILL.md files when total exceeds ~120 (137 files → 116 available)
Summary
In a project with a large number of project-level skills under .claude/skills/**/SKILL.md (137 in our case), Claude Code's skill loader silently drops a non-trivial subset (~21 files, ~15%) from the session's available skills list. Affected skills cannot be invoked via the Skill tool (returns Unknown skill: <name>) even though:
SKILL.mdexists at a valid path (.claude/skills/{category}/{name}/SKILL.md)- frontmatter is structurally identical to other working skills (
name,description,user-invocable: true,allowed-tools,roleall present) - the same project loads 116/137 skills successfully — there is no parse error reported anywhere
The dropping appears non-deterministic across path/alphabet ordering, and we have not been able to identify a frontmatter property that distinguishes loaded vs. dropped skills.
Reproduction
Tested in archway/archway_harness (a framework repository with extensive project-level skills).
# 1. Total SKILL.md files on disk
find .claude/skills -name SKILL.md -type f | wc -l
# → 137
# 2. With user-invocable: true
grep -l "^user-invocable: true" .claude/skills/*/*/SKILL.md | wc -l
# → 136
# 3. Run a structural validator (in-repo) — all PASS
python3 .parasol/validators/skill-registry-check.py --stage 3
# → SKILL-REGISTRY-001 PASS: 137 skills, no violations.
Then in a fresh Claude Code session (CLI v2.1.142, macOS 26.4.1 / Darwin 25.4.0), the available skills section of the system prompt contains ~116 entries. 21 SKILL.md files are silently missing.
Comparison of loaded vs. dropped skills
Both have identical frontmatter shape:
# .claude/skills/parasol/parasol7.context/SKILL.md ← LOADED
---
name: parasol7.context
description: Parasol V7 Phase 1: コンテキスト理解 — 組織・市場・ステークホルダー分析
user-invocable: true
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
role: planner
---
# .claude/skills/parasol/parasol7.inception/SKILL.md ← DROPPED
---
name: parasol7.inception
description: Phase 1.5 インセプションデッキ — Phase 1 分析結果を顧客すり合わせ形式に変換し、Phase 2 への合意ゲートとする
user-invocable: true
allowed-tools: Read, Write, Edit, Glob, Grep, Bash
role: planner
---
Both files:
- live in the same parent directory (
.claude/skills/parasol/) - have a valid
workflow.mdsibling - were added in the same git commit
But only parasol7.context appears in available skills; parasol7.inception returns Unknown skill: parasol7.inception when invoked via the Skill tool.
Sample of dropped skills (15 of ~21)
.claude/skills/parasol/parasol7.backflow/SKILL.md
.claude/skills/parasol/parasol7.bo-detail/SKILL.md
.claude/skills/parasol/parasol7.complete-phase/SKILL.md
.claude/skills/parasol/parasol7.consult-chef/SKILL.md
.claude/skills/parasol/parasol7.full-design/SKILL.md
.claude/skills/parasol/parasol7.golden-thread/SKILL.md
.claude/skills/parasol/parasol7.imagination-detect/SKILL.md
.claude/skills/parasol/parasol7.inception/SKILL.md
.claude/skills/parasol/parasol7.inheritance/SKILL.md
.claude/skills/parasol/parasol7.necessity-check/SKILL.md
.claude/skills/parasol/parasol7.quality-gate/SKILL.md
.claude/skills/parasol/parasol7.quick-start/SKILL.md
.claude/skills/parasol/parasol7.testspec/SKILL.md
.claude/skills/parasol/parasol7.trace/SKILL.md
.claude/skills/parasol/parasol7.usecase/SKILL.md
Expected Behavior
One of the following:
- All 137 SKILL.md files with
user-invocable: trueare loaded and discoverable via theSkilltool, OR - A clear error / warning is emitted to the session (or to a debug log) when a SKILL.md is rejected — currently the drop is silent, which makes it impossible to debug from the user side
- Document the registry capacity / discovery semantics (any total limit, ordering, parse rules) so framework authors can stay within bounds intentionally
Actual Behavior
- 21 SKILL.md silently absent from the session's available skills list
- No warning, no debug message, no failure indicator
Skill: <dropped-skill-name>returnsUnknown skill: <name>at invocation time- Users / agents fall back to manually
Read-ing the workflow.md, which bypasses framework registration and re-introduces drift the framework was designed to prevent
Investigation Notes
The downstream project (archway_harness) has an in-repo validator (.parasol/validators/skill-registry-check.py, Closes #1688) that verifies:
- R-1: SKILL.md existence at every skill directory
- R-2: required frontmatter fields (
name / description / user-invocable / allowed-tools / role) - R-3:
name↔ path basename consistency - R-4: name uniqueness
- R-5: workflow.md reference validity
All 137 SKILL.md PASS this validator at stage 3 (strict). So the issue is not on the SKILL.md authoring side.
The repro tracking issue downstream: https://github.com/archway/archway_harness/issues/1787 (with previous fixes #1544, #1688 that addressed adjacent symptoms but not the drop-on-overflow root cause).
Hypotheses (unconfirmed)
- Total skill count limit — Claude Code may cap project-level skills at ~120 to prevent excessive system-prompt growth. If so, this should be documented and ideally configurable.
- Per-directory or per-category limit — possibly an enumerator that stops early in deep directory trees
- Token budget on system prompt — skills loaded until a token threshold is hit, then truncated silently
- Frontmatter parser edge case with multi-byte description text (all our affected skills use Japanese description)
We could not narrow it down further without access to the loader source / a debug flag.
Workaround
We are currently:
- Falling back to manually
Read-ingworkflow.mdfrom within other skills (defeats the purpose ofuser-invocable) - Considering archiving deprecated skills to reduce total count below the apparent threshold
Neither is sustainable for a framework that grows over time.
Request
Any of these would help downstream framework projects:
- A documented hard limit (e.g. "max 128 project-level skills per session") so we can architect within it
- A
claude debug skillssubcommand that prints the discovered/loaded/dropped lists with reasons - A non-silent failure mode when SKILL.md is rejected (write to stderr or a
.claude/logs/file) - An override config like
.claude/settings.json→"skills.maxProjectSkills": 200for projects that knowingly need more
Environment
- Claude Code CLI: v2.1.142
- OS: macOS 26.4.1 (Darwin 25.4.0, arm64 / Apple Silicon)
- Project size: 137 SKILL.md files across 11 categories under
.claude/skills/ - Tested in: fresh
claudesession in repoarchway/archway_harness@ commitf78574fb(main) - Behaviour reproduced in: a mirror repository (
saibugas_webportal_chef) with the same.claude/skills/structure — same skills dropped
Thank you for looking into this — happy to provide additional diagnostics if there is a debug flag we can enable.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗