DEV Community

Cover image for How Claude Code and Codex Decide Which Skill Descriptions the Model Reads
Mayur Agnani
Mayur Agnani

Posted on Originally published at theaicommit.com

How Claude Code and Codex Decide Which Skill Descriptions the Model Reads

Engineer's view. This is a cache that evicts the least-used entry. A key you just added has the lowest hit count, so it goes first, and it never earns the hits that would keep it. Claude Code trims its skill list the same way. A skill you installed today is the first to lose its description.

TL;DR. A coding agent shows the model only a short list of your skills, and that list has a size limit. Past the limit, descriptions get cut, and a skill the model cannot read about is a skill it rarely picks.

Explain Like I'm 5

A school has one small board by the door. Every club pins a card with its name and what it
does. Kids read the board to decide where to go after lunch.

Then too many clubs sign up. The teacher keeps every name on the board but crosses out the
descriptions of the clubs that got the fewest visitors lately. A brand-new club has had no
visitors yet, so its description is crossed out first.

A kid who loves chess walks past a card that just says "Knights". Nothing tells them it is the
chess club. So the new club stays empty, and its card stays crossed out.

The Problem

You have shipped this bug already, in a system with no model in it.

Your service wrote one log line per request. Someone added a field near the front, and the line
crossed the log shipper's size limit. The shipper did not fail. It cut each line at the limit and
sent the rest. The request ID sat at the end of the line, so searching by request ID stopped
finding anything. No alert fired, because every line still arrived.

The bug was not in any one field. It was a shared size limit, plus a rule for what gets cut when
the limit is hit. Adding something new quietly took words away from something old.

A skill in a coding agent has the same bug. A skill is a folder with a SKILL.md file: a
name, a description, and instructions for one kind of task. Coding agents that support the open
Agent Skills format do not load your skills up front. They show the model
a skill listing: each skill's name and description, and nothing else. The model reads that
listing and decides which skill fits your request.

The listing has a size limit, a fixed share of the context window, the model's working
memory for the session. Install enough skills, and the listing overflows. Each tool then cuts
it by its own rule. A skill whose description was cut can still be listed and still never be
chosen.

The fix: keep the listing under its budget, put each skill's use case in its first sentence
and its name, and check what the model actually sees.

The Fix: Keep the Listing Under Budget and Put the Use Case First

What reaches the model when the skill listing overflows

What does the model actually see?

Agent Skills loads in three steps, which the spec calls progressive disclosure. At the start
of a session the model sees only the listing. When a request matches a description, it reads
that skill's full SKILL.md. Scripts and reference files load only when the instructions point
at them.

So the description does all of the choosing. There is no keyword matcher behind it. The model
reads the words and makes a judgment.

How big is the listing allowed to be?

Claude Code gives it 1% of the context window. Codex gives it 2%, or 8,000 characters when the
window size is unknown. On a 200K-token model, 1% is about 8,000 characters, at roughly four
characters per token.

That is not much. The 41 skills on the machine this article was written on have a median
description of 408 characters. About eighteen such skills fill Claude Code's listing.

What gets cut when it overflows?

The two tools use different rules. Claude Code keeps every name. It drops whole descriptions,
starting with the skills you invoke least. Codex shortens descriptions first and omits whole
skills only for very large sets.

Characters in the listing, 31 skills on a 200K-token model

Why does a brand-new skill go quiet first?

Under Claude Code's rule, a skill you installed today has zero invocations. It is first in line
to lose its description. The model then sees only its name, picks it less, and its count stays
at zero. Unless you invoke it by hand, it never climbs out.

What This Means for You

When this matters. You have more than about twenty skills, counting the ones that plugins
bring along. Or you switch between a 1M-token model and a smaller one. The budget is a share of
the window, so a smaller window shrinks it. A skill that worked yesterday can lose its
description when you change models.

How it affects you. The failure is quiet. The skill still shows up in the / menu, and it
still works when you type its name. What stops is the model choosing it on its own. You notice
weeks later, when a review skips the checklist you wrote for it. In Claude Code the newest skills
are hit first. In Codex every description gets shorter, so a description that saves its trigger
words for the last sentence loses exactly those words.

What to do about it. Start with one minute and no new tooling. In Claude Code, run
/context and read the Skills row. It shows the listing's size after the budget is applied. If
it sits near 1% of your window, you are at the edge. Then open your three newest skills and read
the first sentence of each description. If it does not say when to use the skill, rewrite it so
it does.

Then make it a habit. Turn off skills you never use, set manual-only skills so they leave the
listing, and add a size check to the repo that holds your team's skills. ## Implementing It
shows all three.

Implementing It

The change.

Three people touch this, and each change is small.

Role 1, whoever writes the skill. Put the use case first, and make the name carry it too. A
name survives every cut that a description does not. Keep the whole description short enough
that a cut at about 250 characters still leaves the trigger.

# before: the trigger is in the last sentence, and the name says nothing
name: notes
description: Collects merged pull requests, groups them by area, and drafts a
  summary for customers in the house style. ... Use when the user asks for
  release notes.

# after: the trigger leads, and the name alone still says what it is for
name: release-notes
description: Use when the user asks for release notes or a changelog for
  customers. Groups merged pull requests by area in the house style.
Enter fullscreen mode Exit fullscreen mode

In the demo, the Codex cut keeps 244 characters per description once a plugin doubles the
skill count. The "before" description loses the words "release notes". The "after" keeps them.

Role 2, whoever owns the agent setup. Remove what the model never needs to choose. A skill you
only run by hand should leave the listing entirely. In its frontmatter, Claude Code reads
disable-model-invocation: true. Codex reads allow_implicit_invocation: false under policy
in agents/openai.yaml. For skills you cannot edit, use .claude/settings.json in Claude Code and
~/.codex/config.toml in Codex:

{ "skillOverrides": { "legacy-context": "name-only", "old-deploy": "off" } }
Enter fullscreen mode Exit fullscreen mode
# ~/.codex/config.toml
[[skills.config]]
path = "/Users/you/.agents/skills/old-deploy"
enabled = false
Enter fullscreen mode Exit fullscreen mode

You can also raise the budget. In Claude Code, set skillListingBudgetFraction (for example
0.02). In Codex, set skills.max_context_tokens, up to 10,000 tokens. Every character you add
is paid on every turn, so prune first.

Role 3, whoever owns the repo that ships the team's skills. Fail the build when the listing
would overflow on the smallest model your team uses. read_skills and claude_code_listing
in code_example.py do the parsing and the arithmetic:

skills = read_skills([".claude/skills", ".agents/skills"])
shown, budget = claude_code_listing(skills, context_tokens=200_000)
dropped = [name for name, desc in shown.items() if not desc]
assert not dropped, f"over the {budget}-char listing budget: {dropped}"
Enter fullscreen mode Exit fullscreen mode

How you know it worked.

In Claude Code, the Skills row in /context should drop below the budget, and --debug should
stop logging the overflow warning. /skill-doctor lists skills that were never invoked, with
what each costs. In Codex, the warning about omitted skills should go away.

Then check the behavior, not just the size. Pick five requests that should trigger the new skill.
Run each in a fresh session with claude -p "<request>" --output-format json, and look for a
Skill tool call naming it. Most of the five should now load the skill.

When Trimming the Listing Is the Wrong Tool

When you have a handful of skills. Ten skills with 400-character descriptions fit with room to
spare. Rewriting them buys nothing.

When the rule must hold every time. A skill is advice the model can skip, even when it was
loaded. If every edit must pass a check, put the check in a hook. Claude Code's own docs say
the same.

When the listing is not the problem. A skill can be listed in full and still not be chosen. The
model tends to skip skills for tasks it can do alone, like reading one file. That is a
description problem, and no budget change will fix it.

And raising the budget is not free. The listing is read on every turn. Doubling it on a big team
costs context that every session pays for.

Three questions before you change anything:

  • Does /context show the Skills row near its budget on the smallest model you use?
  • Do your newest skills say when to use them in the first sentence, and in the name?
  • Which of your skills are only ever run by hand, and still listed for the model?

Glossary

  • skill — a folder with a SKILL.md file: a name, a description, and instructions for one kind of task.
  • skill listing — the names and descriptions the model sees at the start of a session.
  • context window — the model's working memory for a session, measured in tokens.
  • progressive disclosure — loading the listing first, a skill's instructions on a match, and its files only when needed.
  • invoke — run a skill, either because the model chose it or because you typed its name.

Further reading


Originally published at theaicommit.com, a daily AI engineering lab for software engineers. The original has an interactive version you can play with, and the full runnable code is on GitHub.

Top comments (0)