Skills consume full token count at startup instead of progressive disclosure (frontmatter only)
Open 💬 17 comments Opened Dec 20, 2025 by atournayre
Problem
According to the skills documentation, skills should use progressive disclosure:
"Claude reads these files only when needed, using progressive disclosure to manage context efficiently."
The expected behavior:
- Metadata (name + description) - Always in context (~100 words)
- SKILL.md body - When skill triggers (<5k words)
- Bundled resources - As needed by Claude
Observed behavior
Running /context shows skills consuming their full token count at startup, not just the frontmatter:
Skills and slash commands · /skills
Plugin
└ Skill Development: 5.5k tokens
└ Command Development: 4.6k tokens
└ Hook Development: 3.9k tokens
└ plugin-dev:create-plugin: 3.7k tokens
└ Plugin Structure: 3.2k tokens
└ MCP Integration: 3.0k tokens
...
These are from the official claude-plugins-official/plugin-dev plugin.
The irony
The "Skill Development" skill (5.5k tokens) explicitly states:
"Keep SKILL.md lean: Target 1,500-2,000 words"
Yet it contains ~5000+ words in its body, and appears to be fully loaded at startup.
Questions
- Is
/contextshowing the total potential size or what's actually loaded? - If progressive disclosure works correctly, why do skills show full token counts?
- If the full body IS loaded at startup, is this intended behavior or a bug?
Impact
With multiple plugins installed, skills alone consume 50k+ tokens before any conversation starts, severely limiting the usable context window.
Environment
- Claude Code version: 2.0.74
- OS: Linux
- Multiple plugins installed from official marketplace
Expected behavior
Only frontmatter (~100 tokens per skill) should be loaded at startup. The body should load only when the skill is invoked.
17 Comments
Additional UX concern
If the workaround is to enable/disable plugins per task, this creates significant friction:
This defeats the purpose of having a plugin ecosystem. Users shouldn't have to manually manage plugin state for every context switch.
Suggested solutions:
The current state makes multi-plugin workflows impractical for users with limited context windows.
Found 2 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Controlled Test Confirms: Full Content Loading (Not Display Bug)
I ran a controlled experiment to definitively answer the question raised in this issue.
Test Methodology
Created a minimal test skill with known token sizes:
Expected vs Actual
| Loading Behavior | Expected Tokens |
|-----------------|-----------------|
| Description only (per docs) | ~10-15 tokens |
| Full content | ~170-220 tokens |
Actual result from
/context:Conclusion
156 tokens ≈ full content, NOT description-only (~10-15)
This proves:
/contextshows actual token consumption, not "potential maximum"Additional Evidence
| Skill | Expected (description-only) | Actual | Matches |
|-------|----------------------------|--------|---------|
| agent-sdk-guide | ~60 tokens | 1.8k tokens | Full content ✓ |
| brainstorming | ~50 tokens | 566 tokens | Full content ✓ |
| test-token-measurement | ~15 tokens | 156 tokens | Full content ✓ |
Environment
Related
@dpaluy quick question, if you remove the skills from your skills directory, does the context go down at all? (i.e. overall percentage)?
I removed all skills and they no longer show on /context, but context hasn't gone down, leading me to believe that perhaps this is just a visual representation of what they WILL load when they load in (which is misleading, but my context window did not reduce more than a very small amount for the meta).
Adding data from investigating this today:
Partial workaround exists:
ENABLE_EXPERIMENTAL_MCP_CLI=trueenables lazy loading for MCP tool schemas (reduced MCP from ~71% → ~16% of context). However, this doesn't affect skills/agents.Potential path forward: Issue #12836 requests Tool Search beta support, which would allow marking tools/skills with
defer_loading: true. This is already available at the API level and could provide a unified solution rather than separate implementations for MCP vs skills.Current state: MCP lazy loading ✅ | Skills lazy loading ❌
@esotericalsolutions removing all skills didn't show me the empty context. I assume either it's a Claude Code bug or Anthropic prefills the context with other content until the limit is reached.
I was experimenting with
ENABLE_TOOL_SEARCH=truebut @gene-jelly recommendation looks interesting.@dpaluy Interesting, I didn't get down to zero (there are lots of things I could see it come up with) but I did notice only a very minor shift (in what I anticipated would just be the meta frontloading) between having any skills in the directory and the directory empty.Twill be interesting to see what the devs find.
Seems to be fixed in 2.1.1
This was just a display/visual bug in
/contextcommand. Skills' token usage was incorrect.See https://github.com/anthropics/claude-code/issues/14834
The bug was fixed in v2.1.1
Token count discrepancy in
/skillsvs actual contentFollowing up on the discussion about token counting accuracy. I ran some tests using the official Claude tokenizer (
Xenova/claude-tokenizerfrom HuggingFace, which is the tokenizer from Anthropic's SDK).Test case
File:
skills/julia-development/SKILL.md(~389 lines)| Method | Token count |
|--------|-------------|
|
/skillscommand | 34 tokens ||
tiktoken(cl100k_base - OpenAI) | 2,180 tokens ||
Xenova/claude-tokenizer(Anthropic SDK) | 2,439 tokens |Analysis
The
/skillsoutput (~34 tokens) matches only the YAML frontmatter (~32 tokens when tokenized):This suggests
/skillsdisplays metadata tokens only, which is correct per the progressive disclosure design. However, there's no way for users to know:/skillsshowsSuggestion
Add a flag or column to
/skillsshowing both:Example:
This would give users visibility into the actual context budget impact.
Environment
Xenova/claude-tokenizerviatransformerslibraryReal-world impact data from a 246-skill power user
I have 246 custom skills. In today's session (2026-03-16), the full skill list was re-injected in every
<system-reminder>block — which fires on nearly every tool result (Bash, Read, Write, Glob, Grep, etc.).Measured impact this session:
The system-reminder attached to THIS comment (visible in the conversation transcript) contains the full 246-skill list. Again. For the 43rd+ time this session.
Proposed fix (progressive disclosure):
<available-deferred-tools>mechanism to defer full skill descriptions until the Skill tool is actually invoked with a specific skill nameWas there a regression recently? I feel this has been happening again in the last few days.
Is this not getting fixed to keep Anthropics earnings up ?
Real-world data from a power user setup (v2.1.92, Opus 4.6 1M context)
I ran forensics on my session startup context consumption and can confirm this issue at scale:
The skill listing alone (name + multi-line description × 81 entries) costs an estimated ~4-5K tokens per session. Combined with CLAUDE.md files, auto-memory, tool schemas, and output reservation, I'm at 81% context remaining after just running
/resume.Notably, MCP tools already have lazy-loading via Tool Search (auto-triggers at 10% context threshold, achieving ~85% token reduction). Skills have no equivalent mechanism — every skill description is fully injected into the system-reminder at startup regardless of whether it will be used.
I've filed a companion feature request for "SkillSearch" — the Tool Search analog for skills — as a constructive design proposal: #43816
The progressive disclosure the docs promise (frontmatter only at startup) would be the minimum fix. SkillSearch would be the proper long-term solution.
Heavy Claude Code user here — the behavior flagged in this issue (skill bodies loading even when frontmatter / description should suffice) is exactly the worst-case I kept running into on my own setup, so I built promptc to measure it.
It walks
.claude/and reports a per-skill exposure multiplier (body_tokens / description_tokens), the aggregate worst-case load if every skill is fully loaded, and an A–F context-debt grade. I cite this issue in the report's methodology section because it's the public evidence that the loading behavior described in the docs isn't always what users observe in practice.Local-only, no API keys:
Would value any feedback — especially whether the multiplier numbers match the intuition of folks who've hit this in production.
Hitting this hard on
2.1.116. With ~50 skills installed (mostly the bundleddocument-skillsplugin pack plus a handful of project + personal skills), the full skill catalog — every skill's name plus its full multi-line description — gets re-injected as a<system-reminder>block after every single tool result and every user prompt.Concrete observation from one session: a smoke-test task that involved ~7 parallel curl calls and a few short follow-up questions reached 120K input tokens after roughly 10 user turns. Scrolling the transcript, the skill catalog blob appears 8+ times verbatim, ~10–15K tokens each. That's the entire token climb — the actual work is a tiny fraction.
This is the same root cause as #35051 / #42650 / #46339. The behavior I'd expect (and what most users seem to expect): the full catalog is sent once at session start, and subsequent reminders only carry deltas or session-relevant context. Today every reminder is a full re-broadcast.
Compounding factors I noticed:
document-skillswith ~15 sub-skills) inject every sub-skill description individually — half the catalog volume comes from one pack the user often doesn't need on a given project.Would strongly support the deferred-skill-discovery design proposed in #42650 (lazy-load like ToolSearch handles deferred tools). Even an interim flag like
skills.alwaysLoad: falseper-skill — mirroring thealwaysLoadMCP option added in 2.1.121 — would unblock heavy users.Confirming on
2.1.xwith 148 SKILL.md files installed (plugins + personal + project). Measured: ~41KB of skill descriptions inject at session start ≈ ~10K tokens before any user turn.This ticket should stay distinct from the
NOT_PLANNEDclosures (#29711, #35051, #42650) because the framing is a docs contract violation, not a feature: the skills docs promise "progressive disclosure" and "Claude reads these files only when needed" — observed behavior loads every description at startup.Precedent already shipped: ToolSearch defers ~75 tool schemas (visible in any session — Cron, Task, MCP tools listed by name only). For comparison: that mechanism saves ~37K tokens per session in my setup — 3-4× larger than the skill surface. The pattern works.
Asymmetry: tools defer, skills don't.