How to build a Claude Skill that actually works
A good prompt is an asset that disappears. A skill is a prompt with a permanent address, a reliable trigger, and a way to measure whether it actually works. Here is how to build one, from the raw idea to the moment you trust it in daily work.
A good prompt is an asset that disappears
You once wrote a 40-line prompt that worked perfectly. You polished it for half an hour, got exactly the output you wanted, and moved on. Two weeks later you needed it again, and it was buried somewhere in a chat history, between "summarize this meeting for me" and a failed attempt at a regex. So you wrote it again, slightly worse, and forgot half the constraints you had discovered the first time.
That’s not a tidiness problem. It’s an architecture problem: a prompt lives inside a conversation, and conversations get thrown away. Everything you learned about making the model do this properly - the output format, the edge cases, the tone - disappears with the conversation. You pay the cost of learning it over and over.
A skill turns the prompt into a file. It has a name, it has a trigger, and it loads automatically in any conversation that’s relevant to it. The real difference isn’t convenience, it’s accumulation. A prompt starts from zero in every conversation. A skill improves: every bug you fixed, every edge case you added, is still there tomorrow. After a month you have a tool that knows things you have already forgotten you taught it.
A prompt is an expense. A skill is an asset.
The anatomy of SKILL.md
A skill is just a folder with a SKILL.md file inside it, and sometimes a few reference files next to it. No compilation, no registration, no API. The file splits in two: frontmatter at the top - the fields Claude reads to decide when to invoke the skill - and the body below it, which is the instructions themselves.
The part that’s easiest to underestimate is the description. It’s the only field Claude sees before deciding whether to load the skill at all. A brilliant body with a bad description is a skill that never runs. Walk through the file below - every part is clickable, and the explanation appears beside it.
This is everything Claude sees at the moment it decides whether to invoke the skill. The formula: what the skill does + when to use it + real phrasings your users actually type. A one-line description is a skill that sleeps through its own job.
A strength tester for descriptions
The fastest way to understand why the description decides everything: take a weak one and a strong one, and check which real requests each of them catches. The weak one below isn’t a caricature. It’s exactly what most people write in the first version.
description: Helps with client documents and pricing.
- Put together a quote for Intel, a one-day workshopdidn’t fire
- What should I charge Wix for the February talk?didn’t fire
- Got an inquiry from a company, build them a proposaldidn’t fire
- can you draft a proposal for Monday?fired
- Summarize the invoice from my accountantfired by mistake
1 of 4 real requests caught - plus one unwanted firing on an invoice. The user is certain the skill "doesn’t work". It works fine. It simply never gets invited.
Building with skill-creator
You can write SKILL.md by hand, but there’s a better way: skill-creator, a skill that builds skills. You give it a raw dump of what you know, it interviews you about what is missing, and it produces a valid file with a description that’s already built properly. Five steps from idea to installed skill:
Don’t phrase it, dump it. How you do the task today, one good example of the output, the mistakes you’re tired of correcting. Ten minutes of an ugly dump is worth more than an hour of careful writing.
I have a process I repeat every week: [free description]. Here is an example of good output: [paste]. Things that always go wrong: [list].
Evals: one green run proves nothing
Models are stochastic. Same skill, same request - one run succeeds and one fails. Testing a skill isn’t "I tried it once and it worked", it’s a table: 5-6 cases, several runs each, and three things you measure - whether the skill fired at all (trigger), whether the output meets the requirements (quality), and how stable the result is across runs (variance).
Hit "run again" a few times below and watch the score jump around. That’s not a bug in the demo. That’s the point.
The problem is in the description. Add the phrasing that failed as a literal quote.
The problem is in the body. The instruction exists but is too soft - turn it into a numbered step with "Never skip this".
The instruction is ambiguous. If Claude reads it differently on every run, a human reader would have hesitated too. Rewrite it.
Rule of thumb: a case that passes 4 out of 4 runs is stable. 3 out of 4 is suspect. 2 out of 4 is a fair coin, and a fair coin isn’t a working tool.
Iteration and shipping
The loop is simple: run the table, fix the most common failure - one at a time, so you know what helped - and run it again. Three or four rounds of that take one evening, and they’re the difference between a skill that impresses in a demo and a skill you rely on at eight on a Tuesday evening.
When do you stop? Not at a hundred percent. A skill is ready for daily use when the triggers pass 4 out of 4 on your real phrasings, the quality cases pass at least 3 out of 4, and the negative trigger doesn’t fire. Perfection isn’t the target. The target is that the skill gets it wrong less often than you would have without it, in a tenth of the time.
And from there it only improves. Every time it misses in real work, the miss becomes a row in the eval table, the fix becomes a line in SKILL.md, and the knowledge stays. That’s the whole story: a prompt disappears, a skill accumulates.
- Triggers: 4/4 on your real phrasings
- Quality: 3/4 or better on every case
- Negative trigger: doesn’t fire on neighboring requests
- Every failure from real use enters the table before you fix it