Home › Articles

Too many agent skills? What they cost in context and how to prune

Updated 2026-10-30

In short: an installed skill costs context in two ways. Its name and description sit in a listing the model sees on every turn. Its full SKILL.md enters the conversation once it's used and stays there. The listing has a budget (1% of the context window in Claude Code, 2% in Codex by default), and when it overflows, descriptions get cut and skills stop triggering. Audit what's installed, turn off what you don't use, make side-effect skills manual-only, move repo-specific skills into the repo, and keep every description short with the trigger words first.

How skills load

All three tools follow the Agent Skills standard and use progressive disclosure: the model starts with a short entry per skill and reads the rest only when it picks one.

ToolAt session startWhen a skill is usedListing budget
Claude CodeName and description of every skill Claude can invokeRendered SKILL.md enters the conversation and stays across turnsScales at 1% of the context window; each entry capped at 1,536 characters
CodexName, description and file pathReads the full SKILL.mdAt most 2% of the context window, or 8,000 characters if unknown
CursorDiscovers skills and presents them to Agent, which decides when they're relevantLoads the skill; resources load on demandNot documented

So the skill you never use isn't free. Claude Code's docs put it plainly: every skill in the listing adds to your context on every turn, whether or not Claude ever uses it.

What actually costs context

Part of a skillWhen it costs context
name + description (+ when_to_use in Claude Code)Every turn, for every skill the model can invoke on its own
Body of SKILL.mdFrom the moment it's invoked. In Claude Code it stays in the conversation on later turns, so every line is a recurring cost
Supporting files (references/, examples.md)Only when the agent reads them
Scripts (scripts/)Executed, not loaded. Only their output reaches the context
Manual-only skills (disable-model-invocation: true)Claude Code leaves the description out of the listing entirely, so nothing until you type /name
Skills preloaded into a Claude Code subagentThe full content is injected when that subagent starts

The listing is where too many skills hurt. In Claude Code every skill name always stays in it, but when the descriptions don't fit the budget, Claude Code drops descriptions, starting with the skills you invoke least. A skill listed by name only loses the keywords Claude matches against, so it stops triggering on its own. Codex works the same way in its own terms: it shortens descriptions first, and with a large skill set it may leave some skills out of the initial list and show a warning.

After auto-compaction, Claude Code re-attaches each invoked skill but keeps only its first 5,000 tokens, within a combined 25,000-token budget filled from the most recently used skill. Invoke many skills in one long session and the older ones can drop out entirely.

How many skills is too many?

None of the three tools publishes a maximum count, and the number that matters isn't the count. It's whether the descriptions you rely on still fit. Signs you're past it:

You can raise the budget (skillListingBudgetFraction, for example 0.02 for 2%, or SLASH_COMMAND_TOOL_CHAR_BUDGET in Claude Code; skills.max_context_tokens, up to 10,000 tokens, in Codex). That trades context for discoverability. Pruning usually gets you more.

Step 1: audit what's installed

Skills come from more places than most people check. Claude Code loads them from enterprise, personal (~/.claude/skills), project (.claude/skills, from the launch folder up to the repo root), nested subfolders, --add-dir directories, plugins (as /plugin-name:skill-name), and skills synced from your claude.ai account (~/.claude/skills/synced/). Codex reads .agents/skills from the launch folder up to the repo root, ~/.agents/skills, /etc/codex/skills and its bundled system skills. Cursor reads .agents/skills, .cursor/skills and their ~/ versions, and for compatibility also .claude/skills, .codex/skills, ~/.claude/skills and ~/.codex/skills.

For a quick look across all three tools' folders, this script lists every SKILL.md visible from the current folder (personal folders, then project folders up to the repo root), sorted by description length, and marks manual-only skills:

#!/usr/bin/env python3
"""List agent skills visible from this folder, with description size and body length."""
import pathlib, re, subprocess

home, cwd = pathlib.Path.home(), pathlib.Path.cwd()
try:
    root = pathlib.Path(subprocess.run(["git", "rev-parse", "--show-toplevel"],
                        capture_output=True, text=True, check=True).stdout.strip())
except Exception:
    root = cwd
dirs = [home / d for d in (".claude/skills", ".agents/skills", ".cursor/skills", ".codex/skills")]
p = cwd
while True:  # project folders from here up to the repo root
    dirs += [p / d for d in (".claude/skills", ".agents/skills", ".cursor/skills", ".codex/skills")]
    if p == root or p == p.parent:
        break
    p = p.parent

rows, seen = [], set()
for d in dirs:
    found = (list(d.glob("*/SKILL.md")) + list(d.rglob("SKILL.md"))) if d.is_dir() else []
    for f in sorted(found):
        if f.resolve() in seen:
            continue
        seen.add(f.resolve())
        text = f.read_text(errors="replace")
        m = re.match(r"---\n(.*?)\n---\n?(.*)", text, re.S)
        meta, body = (m.group(1), m.group(2)) if m else ("", text)
        desc = re.search(r"^description:\s*(.*)$", meta, re.M)
        manual = re.search(r"^disable-model-invocation:\s*(true|yes|on|1)\s*$", meta, re.M | re.I)
        rows.append((str(d).replace(str(home), "~").replace(str(root), "."), f.parent.name,
                     len(desc.group(1).strip().strip("\"'")) if desc else 0, body.count("\n") + 1, "manual" if manual else ""))

print(f"{'location':<40} {'skill':<26} {'desc':>5} {'lines':>6}")
for loc, name, dl, lines, flag in sorted(rows, key=lambda r: -r[2]):
    print(f"{loc:<40} {name:<26} {dl:>5} {lines:>6} {flag}")
auto = sum(r[2] for r in rows if not r[4])
print(f"\n{len(rows)} skills, {auto} description characters in auto-invocable skills")

Run it with python3 list_skills.py from your project. It reads single-line description: values only, follows symlinked skill folders and counts each target once. It can't see plugin, bundled or enterprise skills, or nested skills below the current folder, so use /skill-doctor for the full Claude Code picture. We tested it on a sample repo; it doesn't call any of the tools.

Step 2: turn off or remove what you don't use

Where the skill comes fromTo remove itTo keep it but hide it
Claude Code personal or projectDelete ~/.claude/skills/<name>/ or .claude/skills/<name>/skillOverrides, or disable-model-invocation: true
Claude Code plugin/plugin uninstall or disable it in /pluginNot covered by skillOverrides; manage it in /plugin
Synced from claude.aiTurn it off for your claude.ai account (deleting the folder makes the next sync download it again)Same
Claude Code bundleddisableBundledSkills: true"off" in skillOverrides
Codex localDelete the folder[[skills.config]] with enabled = false, then restart
CursorDelete the folderdisable-model-invocation: true

Claude Code's skillOverrides has four states. In the /skills menu, highlight a skill and press Space to cycle them, then Esc to save to .claude/settings.local.json:

ValueListed to ClaudeIn the / menu
"on"Name and descriptionYes
"name-only"Name onlyYes
"user-invocable-only"HiddenYes
"off"HiddenHidden
// .claude/settings.local.json
{
  "skillOverrides": {
    "old-helper": "off",
    "release-notes": "user-invocable-only",
    "legacy-context": "name-only"
  }
}
# ~/.codex/config.toml
[[skills.config]]
path = "/home/you/.agents/skills/old-helper/SKILL.md"
enabled = false

Step 3: make side-effect skills manual-only

Deploy, commit, release and "send a message" skills shouldn't fire on their own anyway. Marking them manual-only also takes them out of the budget in Claude Code, where the description is no longer in context at all.

---
name: deploy
description: Deploys the current branch to staging or production. Only when the user asks to deploy.
disable-model-invocation: true
---

Cursor reads the same field: the skill is included only when you type /skill-name. In Codex, set allow_implicit_invocation: false under policy in the skill's agents/openai.yaml; explicit $skill invocation still works. The Codex docs don't say whether that also removes it from the initial list.

Step 4: consolidate and slim the rest

Step 5: short, trigger-first descriptions

The description does two jobs: it's what the model matches your request against, and it's the part every skill pays for on every turn. Claude Code caps each entry's combined description and when_to_use at 1,536 characters, and Codex shortens descriptions when the list is crowded. Both docs say the same thing: put the key use case and trigger words first.

description: This skill is a comprehensive helper that can assist with many aspects of testing, including writing new tests, reviewing existing tests, improving coverage, and general quality work across the codebase.
description: Writes and runs unit tests for changed code. Use when the user asks to add tests, raise coverage, or reproduce a bug with a failing test. Not for end-to-end tests.

The second is shorter and names the requests people actually type. For the full pattern and a test loop, see how to write a SKILL.md that actually triggers.

Step 6: scope skills to where they're used

A personal skill loads in every project on your machine. If you use it in one repo, move it there.

---
name: migration-rules
description: Rules for writing database migrations. Use when creating or editing a migration.
paths:
  - "db/migrations/**"
---

A ten-minute cleanup

  1. Run /skill-doctor in Claude Code (or the script above) and list skills you haven't used in a month.
  2. Delete or turn off each one. For plugin skills, disable the plugin.
  3. Add disable-model-invocation: true to every skill with side effects.
  4. Merge skills that answer the same requests.
  5. Move repo-specific personal skills into their repos, and package-specific ones into nested folders.
  6. Rewrite each remaining description: what it does, then "Use when..." with real phrasings, under a few hundred characters.
  7. Check /context or /doctor again, then test the skills you kept in a fresh session.

The same thinking applies to instruction files: see why a long CLAUDE.md gets ignored, and for keeping one set of rules across tools, AGENTS.md vs CLAUDE.md. MCP servers have their own per-tool files, covered in one MCP server, three configs.

FAQ

How many Claude Code skills is too many?

None of the three tools publishes a maximum. The limit that matters is the skill listing budget. In Claude Code it scales at 1% of the context window, and when the listing overflows, Claude Code drops descriptions, starting with the skills you invoke least. Once a skill's description is gone, Claude can't match your request to it. Run /doctor for the listing's cost and /skill-doctor to find skills you never use.

Do installed skills use context even if I never use them?

Their listing entry does. Claude Code's docs say every skill in the listing adds to your context on every turn, whether or not Claude uses it. The SKILL.md body loads only when the skill is invoked. A skill with disable-model-invocation: true is left out of the listing, so it costs nothing until you call it.

How do I turn off a skill without deleting it?

In Claude Code, set it to "off" or "name-only" in skillOverrides, or use the /skills menu, which saves to .claude/settings.local.json. Plugin skills ignore skillOverrides, so disable the plugin with /plugin. In Codex, add a [[skills.config]] entry with the SKILL.md path and enabled = false to ~/.codex/config.toml, then restart Codex.

How much of the context window can Codex's skill list use?

By default the initial list uses at most 2% of the model's context window, or 8,000 characters when the window size is unknown. With many skills, Codex shortens descriptions first and may leave some skills out with a warning. skills.max_context_tokens sets a different budget, up to 10,000 tokens.

Should skills be personal or per project?

Keep only skills you use in every repo in ~/.claude/skills or ~/.agents/skills. Put repo-specific skills in that repo's .claude/skills or .agents/skills, and module-specific ones in a nested folder. Claude Code loads nested skills only once it works on files there, and Cursor scopes nested skills to their directory.

Sources

Official docs, checked 2026-10-30.

Get the free rules sampler + new tips by email

Confirm your email and we'll send you straight to the sampler download. Then one short email every two weeks covering tool format changes (Cursor, Claude Code, Codex, Windsurf, Copilot), new rules and kit updates. No spam.

We store only your email, with our email provider Resend. See the privacy policy.

Unsubscribe anytime from any email. Rather skip email? Get the sampler on GitHub or download the zip directly.