You have installed a pile of AI tooling. Anything that looked useful, you kept. You have never cleared any of it out, and by now you are not sure which of it you actually use.
That is not an idle question, because installed tooling does not sit quietly. It takes up room in the model's head on every single turn, whether it gets used or not. You are carrying the whole toolbox to every job while reaching for three things.
So we counted our own. One evening we pulled up the numbers on our own skill library. The main plugin (a bundle of skills installed and loaded together as one unit) holds 84 skills that the model can see, and their descriptions together come to 30,922 characters loaded into context on every turn, whether anything calls them or not.
Then we counted how many had actually been used. We searched 1,067 session logs on the laptop, searched the same files a second way by looking at slash commands (typing /skill-name to invoke one directly), and searched a third time across 5,680 files on the server. 60 skills never appeared once. That is 73% of the context rent we were paying.
The conclusion felt obvious at the time. Delete them. Why keep something that is never used and still takes up room on every turn?
We measured before cutting. The result came back the opposite of what we expected.
This post is how Productize measured its own Claude skill library, all 142 skills. Every number here comes from runs we did in a single day, none of them borrowed. The number 84 that shows up often below is the subset inside one main plugin, which is the set we actually fired the model against; the rest of the library was checked with the layers that cost nothing.
Part 1The night we nearly deleted 60 skills
It started as a small job. We only wanted to know which skills in the house actually worked. As soon as we started counting we found that nobody had ever counted before.
The first set of numbers was alarming enough.
| What was counted | Number |
|---|---|
| Skills in the main plugin the model can see | 84 |
| Descriptions loaded on every turn | 30,922 characters |
| With a real trace of being used | 24 |
| With no trace at all across 3 searches | 60 (73% of the context rent) |
The phrase "3 searches" matters more than it looks. The first pass searched one way only, for tool invocations in the session logs, and returned 65 skills as never used. A second pass using a different method, slash commands, found 4 more. A third pass on the server found 1 more.
Trusting a single search would have put "65 never used" in the report, wrong by 5, and that report was going to be the basis for deleting things.
Part 2Measuring a skill library takes four layers, and they do not cost the same
What we did not know at the start is that "is this library any good?" is not one question. It is several questions stacked on top of each other, and the tool that answers each one is different, with costs an order of magnitude apart.
| Layer | Answers | Cost |
|---|---|---|
| Inventory | What exists, how many the model really sees, who owns it | zero |
| Self-consistency | Does the skill obey the rule it wrote for itself? | zero |
| Trigger | Does the model pick it up on its own given a matching task? | 1 model call per skill |
| Effect | Does it change the outcome compared to not having it? | 6 model calls per case |
The top two cost nothing because they only read files. No model call at all. And they catch the most common failure.
Here is one we hit ourselves. Our Thai writing skill declares a clear rule against using a long dash mid-sentence. When we measured it at layer four, the model had read that rule, had even opened the reference file where the rule lives, and still put long dashes into the work in 3 runs out of 3.
The cause was inside the skill itself. Three of the examples it labelled as good used a long dash. Examples teach louder than instructions. We fixed 4 lines of examples, measured again, and the result flipped from 0 out of 3 to 3 out of 3.
That class of fault can be found from the files alone, without firing the model once. So we wrote a zero-cost checker that walks all 142 skills in a few seconds, and wired it into the job that runs automatically on every skill sync.
Work up from the layers that cost nothing. Do not jump straight to firing the model.
Part 3Do the folders on disk equal what the model sees?
No, and the gap is far bigger than you would guess. Two filters sit between the files on your machine and the list the model actually reads. Skip them and your context-rent number inflates while still looking perfectly reasonable.
We measured against the skill library of Matt Pocock, a TypeScript engineer who publishes his own skills for others to install, one we have installed for real, at version 1.2.3.
| Layer | Count | What got filtered |
|---|---|---|
| Folders on disk | 35 | nothing yet |
| Declared in the plugin manifest | 25 | 10 never load at all |
| Visible to the model | 11 | 14 have self-invocation turned off |
The number 11 matched exactly the list a real session could see at that moment, which is the only reason we know our counter was right. We caught it by comparing against the real thing, not because any code complained. The first version of the counter reported 35, and 35 looked entirely plausible.
There is a second trap in the same layer. The file where the system records a plugin's location is not always the path the program actually reads. Our cached copy was five days stale and contained none of that day's edits, while the program was reading the working tree in the repo. Believe that record and you conclude your fix had no effect, when it did.
Part 4Does "never called" mean broken?
Mostly no. We fired all 86 skills one at a time, using tasks built from the trigger phrases each skill advertises about itself, then read the run logs to see whether the model picked it up. 66 triggered normally.
That 86 is two more than the 84 quoted earlier, because they are different denominators. The prober walks every skill folder present in the plugin; the 84 counts only the ones the model sees in its list. Skills with self-invocation turned off get probed but take no seat in the list. Same trap as Part 3, one page later.
Which means they were never used not because they were broken, but because nobody ever asked for that kind of work. The context rent was buying triggers that function. Cutting them wholesale removes capability, it does not remove waste.
The remaining 6 were unjudgeable, because the phrases they advertise are not requests a person would make; they are tokens that appear in an output, like "not found". A task synthesised from a phrase like that means nothing. Those need hand-written tasks and another run. That is 66 firing, 14 not, 6 unjudgeable, which adds up to 86.
The 14 that did not fire need one more split, because "did not fire" hides three completely different meanings in one bucket.
- The trigger really is weak. This one is a bug. You spot it when a sibling skill gets picked up instead. We found 4 pairs competing with each other, fixed it by writing non-overlapping scope into the descriptions, and they flipped to firing on the next run.
- The model can already do it. Not a bug. Opening the run log showed no tool call at all, and an answer that was genuinely good.
- The test bench had nothing to work on. Unmeasurable. You spot it when the model answers that it cannot start yet, and then names the skill itself as the one it would use, which means the trigger is working.
We lost a whole round by not separating those three. Seeing 6 skills come back as not firing at the same time, we concluded the descriptions were written weakly and rewrote all 6. The next run flipped exactly one. The other 5 had to be reverted.
What told us was opening the actual run logs, not guessing a third time.
Part 5The right test, and how to run it on your own library
The test we started with was "has it been used?", and it is wrong. The right one is "should it be picked up on its own?"
And "no" is a real answer. Some skills are reference libraries for other skills to read, not doers. Those should have self-invocation turned off, not because nobody uses them but because they should not be picked up on their own. Turning it off still leaves them callable by direct command; it just stops them taking a seat in the list the model reads every turn.
If you want to start on your own library, here is the order we recommend, learned by walking it wrong.
- Count at the right layer first. Do not count folders. Count what the model actually sees, then compare it against the list a real session shows. If the two numbers disagree, your counter is wrong, not your library.
- Check whether each skill obeys its own rules. Zero cost, and the layer that catches root causes most often.
- Search for usage at least 2 different ways before the word "never" goes into any report.
- Fire triggers only when a skill changes, never on a daily timer. A check tied to the calendar produces reports nobody reads.
- Read the results before fixing anything, especially when several things fail at once. An unusually high failure rate usually means your definition of "correct" is wrong, not that everything broke together.
All four layers we used are ordinary scripts that read files and run one-line commands. Nothing special. The hard part is reading the results correctly, because on that same day we misread them 4 times, and every one of those nearly sent us off to fix something that was not broken.
We now keep the reading guide as a separate document from the tools themselves, because the thing that was missing was never the tools.
The sharpest example of a skill demonstrating what it forbids has its own post: the skill banned a character, and the skill used it 54 times. If you are not sure how a skill differs from a long prompt, we covered that in a skill is not just a longer prompt. And if your library has grown to the point where different agents should carry different sets, try your AI team should not all carry the same skills next. Everything else lives on the blog index.
Sources and references
Every number in this post comes from runs against our own skill library on 13 August 2026. None of them are borrowed from elsewhere.
- The count of model-visible skills and the context rent were measured with a counter we wrote, reading the machine's settings file and the plugin tree the program actually reads.
- The usage search covered 1,067 session logs on the main machine and 5,680 on the server, in two different patterns.
- The trigger results across 86 skills came from one single-line command per skill, read out of the verbose run logs.
- The numbers 35, 25 and 11 were read from the real folders, the plugin manifest, and each skill's file header, then compared against the list a real session could see.