Your skill description is cut at 1,536 characters, and the cap is a setting you can raise
Anthropic documents a per-skill cap of 1,536 characters on the skill listing, and it is a setting you can change. Measured against it, text ending at 1,530 characters still reaches context in every round and text ending at 1,536 never does. Nothing errors either way: past the cut the skill simply stops matching on words you wrote.
CORRECTED 2026-08-21, and the correction is the interesting part. This post originally quoted a documented “Maximum 1024 characters” for a skill description and framed the cut as something the documentation did not cover. The framing was wrong: the cut is documented, it is a named setting, and you can change it. On the quote, I can no longer find that sentence in the skills, settings, plugins or slash-commands references, so I am withdrawing it rather than defending it; I am not claiming it never appeared anywhere. What follows is the measurement, re-run against the number the documentation actually gives.
A skill’s description is the only part of it that loads at startup, and it is what Claude matches your request against when deciding whether to fire the skill. Anthropic documents a cap on it:
skillListingMaxDescCharsDefault:1536. Per-skill character cap on the combineddescriptionandwhen_to_usetext in the skill listing Claude sees each turn. Text longer than this is truncated.
The skills reference states it three more times, on the description row, on the when_to_use row and again under the listing budget, and adds the part that makes it matter: the truncation happens in the listing, silently, “to reduce context usage”.
Nothing rejects a longer description. Claude Code reads skills off the filesystem, and a 2,000-character description loads without complaint. So the question this post set out to answer, where the text actually stops arriving, is still worth measuring. It just has a documented answer to be measured against.
The test
Plant a rare marker at a known character offset inside one skill’s description, then ask for it:
Look at the skills available to you. One skill’s description contains a code that starts with ZQX and ends with FLM. Reply with only that code, exactly as written.
The description is 2,400 characters of ordinary prose in every run. Only the marker’s offset moves.
The answer you get is not the measurement
Every single round reported the marker. All four offsets, out to 2,000 characters, four rounds each. Scored on the reply, the finding is “descriptions are never truncated” and it is wrong.
The session transcripts show what actually happened:
| Marker starts at | and ends at | Answered from context | Went and opened the file |
|---|---|---|---|
| 1,400 | 1,410 | 4 of 4 | 0 |
| 1,550 | 1,560 | 0 | 4 of 4 |
| 1,700 | 1,710 | 0 | 3 (and 1 not found) |
| 1,850 | 1,860 | 0 | 4 of 4 |
| 2,000 | 2,010 | 0 | 4 of 4 |
The marker is ten characters wide, so both columns matter and the second is the one that bounds the cut. The original run of this trial reported only the first, which is fine for a 150-character bracket and not fine for a six-character one.
At 1,400 characters the model answers immediately, with zero tool calls. At 1,550 and beyond it never does: every round it runs bash three to seven times, finds SKILL.md on disk and reads the marker out of the file.
A marker the model had to go and read is evidence the description was not in its context. The right answer arrived by the wrong route. Scoring the reply alone would have published the exact opposite conclusion, with sixteen clean rounds behind it.
So: a skill description stops reaching the model somewhere between 1,400 and 1,550 characters. The documented 1,536 sits inside that bracket, which is a reason to narrow it rather than to stop.
Narrowing it onto the documented number
Five more offsets, four rounds each. The marker is ten characters wide, so what matters is where it ends, not where it starts.
| Marker ends at | Answered from context | Went and opened the file |
|---|---|---|
| 1,510 | 4 of 4 | 0 |
| 1,530 | 4 of 4 | 0 |
| 1,536 | 0 | 4 of 4 |
| 1,540 | 0 | 4 of 4 |
| 1,550 | 0 | 3 (and 1 searched and gave up) |
Text ending at 1,530 characters is delivered; text ending at 1,536 is not. So the cut sits somewhere in 1,530 to 1,535, and the documented 1,536 is right to within six characters. What the remaining gap is made of, presumably whatever a listing entry carries alongside the description text, this does not measure.
What I can state without an interval is the safe side of it: 1,530 characters is delivered, in 4 of 4 rounds. Budget that and you never need to care where inside those six the line actually falls.
Your skill’s name does not eat into it
The doc caps the combined description and when_to_use of the listing entry, which raises an obvious worry: does a long skill name spend your description budget?
No. Re-running the boundary cell with the skill renamed from probe to a 56-character name, a 51-character increase, a marker ending at 1,530 is still answered from context in 4 of 4 rounds, and so is one ending at 1,410. Nothing moved. The figure above is not name-dependent.
Is it your description, or a budget your colleagues can spend?
That distinction decides whether this is something you control, and the answer turned out to be “both, and the one that bit here is yours”.
If each description is cut independently, the fix is yours: keep it short. If instead the whole skill listing shares a budget, then a description that works today silently stops working the moment somebody installs another pack, and nothing you do to your own skill helps.
My first attempt at this was worthless, and the way it failed is worth more than the result.
I held the marker at 300 characters and swept the skill count: 1, 5, 20, 40. Every round came back in context. I wrote down that the cut does not move.
But that test could not have failed. A marker at 300 characters arrives under both hypotheses. A listing-wide budget generous enough to carry a few hundred characters per description still delivers it. Sixteen clean rounds, and the observation was equally consistent with the thing I was claiming to rule out.
So I moved the probe to where the two answers differ. Cost data on the same fixture hints that far less than 1,400 characters is being charged once forty skills are installed, so a marker at 900 or 1,400 characters should vanish at forty skills if the budget is shared, and survive if it is not:
| Marker at | 1 skill | 10 skills | 40 skills |
|---|---|---|---|
| 900 chars | 4 of 4 | 4 of 4 | 4 of 4 |
| 1,400 chars | 4 of 4 | 4 of 4 | 4 of 4 |
It survives. The cut is a property of one description, and at forty skills it is yours to control.
The 300-character sweep is published with the rest, marked as evidence for nothing.
A correction to how strongly that was originally put. This post first said the cut is your description “rather than a budget your colleagues can spend”. A shared budget does exist and is documented: skillListingBudgetFraction reserves 1% of the model’s context window for the listing, and when the listing overflows Claude Code “drops descriptions starting with the skills you invoke least”, listing those skills by name only. What the sweep above shows is that the shared budget did not bite at forty skills, not that there is no shared budget. If you run a very large pack, that second mechanism is the one to read about.
What this costs you in practice
Nothing crashes. There is no error, no warning, and the skill still installs and still appears. What you lose is the matching: the words past the cut are not there when Claude decides whether your skill is relevant to a request.
That is the worst shape a limit can have. A description that says what the skill does in its first 1,200 characters and lists when to use it in the last 400 will look completely fine and quietly fail to trigger on exactly the cases you spelled out.
Practical version: keep the description under 1,530 characters. Put the trigger conditions early, not last. The budget is in characters, so this is the same number whether your description is plain English or full of flags and field types, and it does not change with the length of your skill’s name.
And if you genuinely need more, raise it. skillListingMaxDescChars is a setting, so a longer description is a decision rather than a wall. It costs context on every turn, for every skill, which is why the default is where it is. I have not measured what raising it costs, and it would be a good thing to measure.
What this does not settle
The cut is still an interval, just a narrow one. The last position delivered is 1,530 and the first position not delivered is 1,536. The five positions between were not tested individually.
No when_to_use anywhere. The doc caps description and when_to_use combined. Every fixture here has no when_to_use field, so how the two share the budget is untested.
The cap was never changed. skillListingMaxDescChars sat at its default throughout. Nothing here shows that raising it moves the cut, only that the doc says it should.
Characters, not tokens. Settled later the same day. This post originally listed that as unknown. Measured since: a description built from API-shaped text — punctuation, identifiers, numbers, flags — costs 2.06 times as much per character as the prose used above, verified by a paired cost arm in the same runs. A token budget set where prose is cut would have severed it near 702 characters. It is still answered from context at 1,400, four rounds of four, exactly like prose. The limit counts characters.
That makes the advice universal rather than a prose-writer’s number: an author whose description is full of code or field types gets the same character budget, and simply pays more tokens inside it.
One description shape. Ordinary English prose repeated to length. This site has already measured that a description built from symbols tokenises very differently.
The scale sweeps bound the cut, they do not locate it. They show it stays above 1,400 characters at forty skills. They do not show it sits at exactly the same character count at every skill count.
Cost and context diverge, and I cannot explain it. A separate sweep found description cost going flat above roughly 900 characters at forty skills, while the marker probe shows description text still reaching context at 1,400 characters at the same skill count. Text that arrives but stops being charged is not something I have a mechanism for, and I am not inventing one.
An inference that looked like a refutation, and was not. Back-solving that cost data against this site’s published model of 13.7 tokens plus 0.276 per character suggests only about 580 characters are carried at forty skills, which would mean the cut does move. That back-solve is invalid: the post publishing 0.276 also states it is “linear only over that range”, meaning to 300 characters, and every cell it gets applied to is 512 or more. A rate used outside its stated range gives a carried-character figure that means nothing. The direct measurement overrides it.
One machine, one release. Opus on Claude Code 2.1.235, macOS.
Controls
Tool use is the primary signal, for the reason above. Three outcomes are scored per run and all three are published: answered from context, read from disk, not found.
Positive control. The low-offset and one-skill cells must answer from context; they are the conditions already known to hold. If they had failed, the harness would be at fault and the run void.
The marker’s offset is verified off disk. The generated SKILL.md is read back and the marker’s character position asserted before the call is made, so “offset 1,400” is a fact about the file rather than about the argument passed in.
A rare marker, so a hit cannot be the model producing plausible text.
Isolation. --setting-sources project asserted onto the command line, so this machine’s own skills cannot enter any run.
Every reply and every tool count is published per run, so the scoring can be re-checked rather than taken on trust.
All rounds, with their verbatim replies and tool counts, are in desc-truncation-2-1-235.json. The narrowing sweep and the skill-name control are in desc-cut-1536.json, 28 further runs.