Claude Code skills bloat: two surfaces, not one.
Most of the advice circulating about this problem treats "skills bloat" as one thing: too many files, cut them. That is half right. The two surfaces behave differently, cost differently, and want different fixes. This page walks the math on both, shows what ccmd flags inside an actual bloated SKILL.md, and gives the 3-step audit you can run in 10 minutes.
1. The cost, in numbers
The listing-budget piece is small per turn but compounds across every session you open. The per-invocation body is the inverse: large when it fires, zero when it does not. Both matter for different reasons.
Plug those into Opus 4.7 input pricing ($15 per million tokens). One bloated skill that fires 30 times costs 6,000 × 30 × $15 / 1,000,000 = $2.70 of input cost per session, on top of everything you actually wanted to spend Claude on. Twelve such skills sitting in your global directory, half of them never invoked, still ship their listing entries every turn of every session. That is the part the "just disable unused" advice gets right.
“If your skill files consume 20,000 tokens out of a 200,000-token context, that's 10% of total capacity gone before a single line of code is read.”
MindStudio, Context Rot in Claude Code Skills
2. The listing budget (the cheap fix)
Claude Code reserves a slice of context for the skill listing on every turn. The fraction is set by skillListingBudgetFraction and defaults to 0.01. On a 200K-token model that is about 2,000 tokens; on a 1M-token model it is 10,000. Each entry costs around 75-150 tokens with the XML wrapper Claude Code adds. Run /skills to see your installed set:
That session is 57% over the default budget. Seven of twelve skills were never invoked. The fix is two clicks: disable the seven unused ones and the listing drops from 3,140 to roughly 1,800 tokens. The skill catalog on disk is unchanged; you can flip them back on next time you need them.
The other 90% solution is location-based. Anything in ~/.claude/skills/ counts against the budget in every project you open, including projects where it is irrelevant. A skill that only makes sense inside one repo belongs at <repo>/.claude/skills/ where it is scoped to that repo's sessions only. Anthropic's own docs recommend this as the second-pass fix after the disable pass.
3. The SKILL.md body (where ccmd earns its keep)
Once a skill survives the disable pass and the relocate pass, what is left is the body. When that skill fires inside a session, the full markdown of its SKILL.md enters context. The same patterns that rot a CLAUDE.md (vague language, unbounded absolutes, missing-why prohibitions, cache-busting timestamps) rot a SKILL.md identically. ccmd's detector at src/lib/analyzer.ts:41 inspects only the first 300 chars of any paste, which means the same rubric runs on every flavor of agent config you feed it. Here is a real-shape bloated skill:
The analyzer finds eight things wrong with it without leaving the browser. Three of those are the description line itself, which is what ships in the per-session listing whether the skill fires or not.
The threshold for the bloat finding is set at src/lib/analyzer.ts:150: any single line over 28 words is flagged, because compound rules beyond that length consistently lose the second clause to attention dilution. The vague-terms list at src/lib/analyzer.ts:124 has 14 entries ("appropriately", "carefully", "cleanly", "good", "best", and friends). The cache-bust check at line 194 flags any ISO date in the first 20 lines because Anthropic's prompt cache invalidates on any change, and a daily timestamp near the top is the cheapest cache-buster there is.
4. The 10-minute audit
Disable unused skills (free, instant)
Run /skills in Claude Code, sort by last-invoked, toggle off every skill you have not used in 30 days. Most users find half their installed skills are dead weight from a long-ago install spree. The listing budget drops immediately and nothing else changes. The skills stay on disk; re-enable later in two clicks.
Relocate project-only skills (free, one-time)
For every skill that only makes sense in one repo (codebase-specific generators, project-specific QA flows, repo-internal style enforcers), move the directory from ~/.claude/skills/<name>/ to <repo>/.claude/skills/<name>/. It still works inside the repo and stops counting against your global listing budget when you open other projects.
Score the survivors against the rubric
What is left after step 2 is the small set of skills you actually use across many projects. For each one, paste the SKILL.md body into the analyzer on ccmd.dev. The same Karpathy-12 rubric and 7-finding pipeline that scores a CLAUDE.md scores a SKILL.md identically. The high-leverage cuts are the description (because it ships in the listing every turn) and the bloat/cache-bust findings (because they fire on every invocation).
Optional: PR-comment monitoring on drift
The free analyzer is one-shot. If your SKILL.md files are checked into the repo and edited by multiple engineers, the ccmd paid tier comments the score on every PR that touches a SKILL.md or CLAUDE.md, so drift gets caught at review time instead of on a Wednesday rate-limit. That is the only piece behind a paywall; everything in steps 1-3 is free.
5. Which approach pays back fastest
| Feature | generic advice | ccmd analyzer |
|---|---|---|
| Tells you which skills cost the most tokens | generic 'most users have too many' | exact char/4 token count per file |
| Flags bloated description lines (listing budget) | trim to 100-150 chars (guess) | flagged at 28-word threshold, line-by-line |
| Scores SKILL.md body for the same rot as CLAUDE.md | not covered | Karpathy-12 + 7 bloat heuristics |
| Catches cache-busting timestamps in skill bodies | not covered | ISO date in first 20 lines = flag |
| Flags missing-why on NEVER/DO NOT prohibitions | not covered | 4-line lookahead for the Why |
| Runs in browser, no upload | varies | all logic in src/lib/analyzer.ts |
| Recurring monitoring on PR diff | manual re-audit | paid tier, $9/mo solo |
6. What "cut" looks like
The pdf-handler example above has eight findings. Four edits resolve seven of them and cut the file from 318 tokens to about 150. The description goes from 54 words to 16, which means the listing-budget cost drops from 72 tokens to about 20 every single turn the skill is installed.
Same skill, after the 4 edits ccmd suggests
Long catch-all description. Five 'Always' lines with no escape clauses. A 42-word stack paragraph that drops half its rules. A 'today is 2026-05-17' line that busts the prompt cache on every session.
- description is 54 words
- 5 unbounded 'Always' lines
- stack paragraph is 42 words
- ISO date near the top
- 2 NEVER lines with no Why
Want a 15-minute pass on your skills directory?
Free. Bring your /skills output and your three biggest SKILL.md files. We will tell you which ones to cut, which to relocate, and which to rewrite.
Frequently asked questions
What is Claude Code skills bloat?
Two distinct things stacked on top of each other. (1) Listing bloat: every skill installed in `~/.claude/skills/` puts its `name` and `description` into a YAML-like listing that ships on every turn of every session. Anthropic's docs put the typical per-skill cost at 75-150 tokens with the XML wrapper. The default skill-listing budget is `skillListingBudgetFraction = 0.01`, about 2,000 tokens on a 200K Sonnet/Opus context. Stack 25 skills with verbose descriptions and you exceed the budget before Claude reads any code. (2) Body bloat: when a skill is actually invoked, its full `SKILL.md` body is loaded into context. A 6,000-token skill with vague prose, missing Why lines, and 30-word rules acts like a bad CLAUDE.md whenever it fires.
How do I see which skills are costing me the most tokens?
Run `/skills` inside Claude Code. The official UI shows the installed list and lets you toggle each one off. It does not currently surface per-skill token counts, so for the precise number paste the skill's `description` and `SKILL.md` body into the analyzer on ccmd.dev. The token estimate (chars / 4) matches what every Claude Code CLI heuristic uses; see `src/lib/analyzer.ts:37` in the open ccmd source.
Should I just disable every skill I don't use today?
Yes, as the first pass. Anthropic's own skill-listing budget guidance treats `/skills` toggle-off as the primary fix, and most teams find half their installed skills were never invoked in the last 30 days. The bigger win after that is moving project-specific skills out of `~/.claude/skills/` (which loads on every session) and into the project repo's `.claude/skills/` directory, where they only count against context when you're working in that repo.
Why does the SKILL.md body matter if it only loads when invoked?
Because the same skill can fire 30 times in a long session, and a 6,000-token bloated body is 180,000 input tokens of the same drift. At Opus 4.7 input pricing ($15 per million), that single bloated skill is $2.70 of input cost per session you'd otherwise spend on actual code. Worse, after about 50% context fill the model starts dropping instructions silently — the bloated half of the SKILL.md is the half it forgets.
What does ccmd do that `/skills` doesn't?
`/skills` is a toggle UI: on or off, with no per-line analysis. ccmd takes the body of any agent-config file (SKILL.md, CLAUDE.md, AGENTS.md, .cursorrules, .grokrules) and runs the same Karpathy-12 rubric and bloat heuristics against every line. Findings: bloat (over 28 words), vague (one of 11 banned terms like 'appropriately'), aspirational (an absolute with no escape clause), missing_why (a NEVER/DO NOT with no incident), cache_bust (a timestamp near the top), and duplicate (the same rule said twice). The logic is one file: `src/lib/analyzer.ts`. No upload, no signup, runs in the browser.
Is the skill-listing budget configurable?
Yes. The Claude Code config supports a `skillListingBudgetFraction` setting that controls what fraction of the context window is reserved for skill listings. The default is 0.01 (1%, about 2,000 tokens on a 200K model, 10,000 on a 1M-token model). Bumping it up is a real option on 1M-token models where the percentage overhead matters less. On 200K models it is almost always cheaper to trim the description text instead.
How much per-turn workload does skill bloat actually add?
Two separable workloads, both per turn. (1) The listing workload: every installed skill's name and description ships in the system prompt on every turn of every session, default budget 1% of context (about 2,000 tokens on 200K). Twelve skills at 125 tokens each is 1,500 tokens of attention every turn, whether any of them fires or not. The model still has to read those tokens to decide if a skill applies. (2) The invocation workload: when a skill fires, its full SKILL.md body enters context for that turn and every subsequent turn in the session. A 6,000-token bloated skill that fires 30 times in a long session is 180,000 input tokens of dead weight on top of whatever you actually wanted Claude to do. The cheap fix targets the first workload (disable unused), the leveraged fix targets the second (score the surviving SKILL.md bodies on ccmd.dev).
Does the same logic apply to AGENTS.md (Codex) or .cursorrules?
Yes. Codex's AGENTS.md and Cursor's `.cursorrules` and Grok Build's `.grokrules` all load the same way: the entire file enters context every turn (or every session, depending on the agent). The rubric that scores a bloated CLAUDE.md scores those identically. ccmd's detector at `src/lib/analyzer.ts:41` just inspects the first 300 chars of your paste and picks the right label. The findings are the same.
Next: the 12-rule rubric in full, the .grokrules walkthrough, or paste your SKILL.md on the analyzer.
Comments (••)
Leave a comment to see what others are saying.Public and anonymous. No signup.