Skill injection is O(n) per tool call — unusable at 100+ skills
Problem
Every tool call response injects the full skill catalog as <system-reminder> blocks. With 160+ skills, this adds ~25K tokens to every single tool response. This is not a theoretical concern — it makes Claude Code unusable for power users with large skill libraries.
Impact
- Token waste: ~25K tokens × ~50 tool calls per session = ~1.25M wasted tokens per session
- Context pressure: Fills the context window with repeated skill descriptions instead of actual work
- Latency: Every tool response is larger than it needs to be
- Cost: Users on metered plans pay for tokens that provide zero value after the first injection
Reproduction
- Create 100+ skills in
.claude/skills/(each with aSKILL.mdcontaining frontmatter) - Start a conversation and use any tool (Read, Bash, Grep, etc.)
- Observe the full skill catalog injected into every tool response as
<system-reminder>blocks
Current Workaround
Replace the skills directory symlink with a curated directory containing symlinks to only ~25 essential skills. This drops injection from 160+ to 25 skills. All skills remain accessible by path — they just aren't auto-injected.
Suggested Fixes (any one would help)
- Inject once, not per-tool-call: Load the skill catalog into the system prompt once at conversation start. Don't re-inject on every tool response.
- Lazy loading: Only inject skill descriptions when a trigger phrase is matched, not preemptively.
- Token budget cap: Allow users to set a max token budget for skill injection (e.g.,
skill_injection_budget: 5000in settings). - LRU / relevance filtering: Only inject the N most relevant skills based on conversation context.
- User config: Let users mark skills as
auto-inject: falsein frontmatter to exclude them from the catalog while keeping them invocable. - Tiered injection: Inject skill names + triggers only (compact), and load full descriptions on-demand when a skill is actually invoked.
Environment
- Claude Code CLI
- 160+ skills across 7 domains (security, extraction, creative, ops, ML, compliance, persona)
- Skills are composable — they reference each other via
composes:frontmatter - This is a real production engineering platform, not a toy setup
Context
The skill system is a great idea — composable, specialized capabilities with trigger-based routing. The injection strategy just doesn't scale. A simple fix (inject once at session start, or lazy-load on trigger match) would make this work perfectly at any scale.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗