Een Claude Code-skill is een procedure: een SKILL.md met de stappen, de controles en eventuele hulpbestanden die een klus nodig heeft, die de agent laadt en volgt zodra die klus zich voordoet. De reden om er zelf een te schrijven is precies het deel dat de meeste mensen overslaan, en daar gaat de rest van dit stuk over.
Je hebt de beslisboom gelezen, je hebt "skill" gekozen uit de zeven manieren om Claude Code te sturen, en nu staat er een lege SKILL.md open. Wat zet je er eigenlijk in?
De meeste mensen zetten er een prompt in. Een alinea of twee "audit deze code en vertel me wat er mis is", opgeslagen in een mapje met een mooie naam. Het laadt, het model leest het, het model doet ongeveer wat er staat. Ongeveer.
Dat is geen skill. Dat is een prompt met een chique bestandsnaam.
Een goede skill is een procedure. En de beste skills doen iets wat een prompt nooit kan: ze bouwen wantrouwen in tegen het model dat ze uitvoert. Ze benoemen precies hoe de agent de mist in gaat, en ze bouwen de vangrail zó in de stappen in dat het niet meer mis kan gaan.
Ik laat het je zien met een echte. Neem een code-audit-skill: wijs hem naar een pad of een git-range, en hij jaagt op bugs en schrijft een rapport. Het is een goed voorbeeld, juist omdat het interessante deel niet zit waar je het zou verwachten.
Wat een Claude Code-skill eigenlijk is
Haal eerst de mystiek eraf, want het maakt uit dat de verpakking saai is.
Een skill is een map met een SKILL.md erin: bovenaan YAML-frontmatter, daaronder instructies in markdown. Waar je de map neerzet, bepaalt wie hem kan gebruiken:
| Plek | Wie hem kan gebruiken |
|---|---|
~/.claude/skills/<naam>/SKILL.md | jij, in elk project |
.claude/skills/<naam>/SKILL.md | iedereen die in de repository werkt |
packages/api/.claude/skills/<naam>/SKILL.md | Claude, zodra het aan bestanden in dat package werkt |
skills/<naam>/SKILL.md in een plugin | iedereen die de plugin installeert |
Twee dingen doen het echte werk. De mapnaam wordt het slash command, dus /code-audit start de skill direct, of /plugin-naam:code-audit voor een skill uit een plugin. Claude leest het veld description om te bepalen of het de skill uit zichzelf laadt, dus daar beschrijf je de situaties waarin je hem nodig hebt. Verder is het handig om twee optionele velden te kennen: met disable-model-invocation: true start de skill alleen nog via het slash command, en allowed-tools beperkt welke tools hij mag gebruiken.
Zwaardere onderdelen, zoals een naslagdocument of een hulpscript, zet je in een apart bestand waar de skill naar verwijst. Claude leest een naslagbestand pas als de taak erom vraagt, en voert een script uit zonder het in de context te laden. De praktische kant van installeren en indelen behandelde ik in de gids over de Superpowers-plugin.
De verpakking is expres dom. Alle waarde zit in wat de body de agent laat doen, en in hoe strak die de manieren beperkt waarop het mis kan gaan.
De echte vraag was dus nooit "wat is het bestandsformaat". Het is "wat maakt van een skill iets dat het laden waard is, in plaats van een opgeslagen prompt". Drie dingen, en code-audit laat ze alle drie zien.
Een skill is een procedure, geen prompt
Dit is de naïeve versie van code-audit, de versie die de meeste mensen zouden schrijven:
Audit deze code op bugs, beveiligingsproblemen en foute logica. Rapporteer wat je vindt.
Zet dat voor een model neer en het leest wat bestanden, matcht op dingen die op bugs lijken, en geeft je vol overtuiging een lijst. Een deel echt. Een deel gehallucineerd. Je kunt niet zien welk deel, dus je moet alles met de hand nacontroleren, en dat is precies het werk dat je wilde besparen.
De echte code-audit skill is een procedure met drie fasen. Hij verdeelt het doelwit in auditeenheden die klein genoeg zijn dat één subagent er elke regel van kan lezen. Hij start per eenheid een finder op vier vaste dimensies, plus één overkoepelende finder voor tegenstrijdigheden die onzichtbaar zijn voor elke losse eenheid. En dan doet hij de zet die een skill onderscheidt van een prompt:
Geen enkele bevinding wordt bevestigd voordat een verse, onafhankelijke sceptische subagent heeft geprobeerd hem onderuit te halen, en daar niet in is geslaagd.
Dit is de hele kern. Elke bevinding die een finder oplevert, gaat naar een nieuwe subagent waarvan de enige taak is om hem af te schieten. Die scepticus krijgt de claim en verder niets. Niet de redenering van de finder, niet zijn zekerheid, niet zijn onderbouwing. Dit is de daadwerkelijke instructie voor de scepticus, ingekort:
You are a skeptical senior engineer. A code audit produced this claim. Your job is to REFUTE it.
Claim: in [file:line], [dimension] defect: [failure scenario]. Offending code: [code].
Read the actual file(s) in full, including surrounding code, callers, and any guards
elsewhere that would prevent the failure. Then decide:
- REFUTED: the failure cannot actually happen. Default to REFUTED if you cannot confirm
it end-to-end.
- CONFIRMED: you traced the failure scenario end-to-end and it happens. Quote the exact
lines that prove it.Let op de standaardwaarde. REFUTED tenzij bewezen. De bevinding moet zichzelf bewijzen om te overleven, het is niet aan de scepticus om hem te slopen. De scepticus leest het echte bestand, volledig, inclusief de guards en aanroepers elders die de fout onmogelijk kunnen maken, en ziet nooit het argument dat de bevinding in eerste instantie overtuigend liet klinken.
Dat ontwerp begint bij een aanname die de meeste prompts nooit maken: het model dat de bevindingen genereert is niet te vertrouwen. Het produceert plausibel ogende bugs die verdampen zodra iemand echt kijkt. Dus bouwt de skill de controle in. Hij zet de output van het model tegenover een verse instantie van datzelfde model, ontdaan van de redenering waardoor de claim waar leek, en alleen de overlevenden komen bij jou.
Dit is het verschil. Een prompt vertelt de agent wat hij moet doen. Een procedure vertelt hem wat hij moet doen en hoe het misgaat terwijl hij ermee bezig is.
Het vak is benoemen hoe de agent de mist in gaat
Zodra je accepteert dat een skill een vangrail is tegen de eigen faalmodi van het model, volgt de rest vanzelf. Hier zie je dat terug.
De description is een trigger, geen samenvatting. Hier doet iedereen het andersom. Het veld description bestaat zodat een toekomstige agent, die een lijst met skills doorloopt, kan beslissen of hij deze moet laden. Het hoort te beschrijven wanneer je de skill gebruikt, niet wat de skill doet. Dit is de echte frontmatter van code-audit:
---
name: code-audit
description: Use when asked to audit code — "audit this module", "logic audit",
"fact-checked review", "/code-audit [path|ref]" — for a path, git ref/range, or the
whole repo. Runs finder subagents across four dimensions, then adversarially verifies
EVERY finding with independent skeptic subagents before asserting it. NOT for reviewing
the current working diff (use /code-review) and NOT a fix-applying tool — it is strictly
read-only.
---Hij begint met de zinnen die iemand echt zou zeggen en besteedt de tweede helft juist aan wanneer je hem niet moet pakken. Perfect is hij niet. Die middenzin, "runs finder subagents, then verifies", is precies de werkwijze-samenvatting waarvan ik net zei dat je die moest schrappen. Die zou je hier ook kunnen weglaten. Maar de twee uiteinden verdienen hun plek: de geciteerde triggers vooraan zodat de skill gevonden wordt, en de luide NOTs achteraan zodat hij niet op de verkeerde klus afgaat.
Waarom maakt dit zoveel uit? Omdat als je de werkwijze in de description samenvat, de agent die samenvatting leest en denkt dat hij de procedure nu kent, dus opent hij de body nooit. Een description die zegt "auditeert code door problemen te vinden en te verifiëren" leert de agent stilletjes om het deel over te slaan waar hij leert hoe. Houd het proces uit de description. Met de description kom je binnen. De body leert je de rest.
Het output-contract is een recept, geen wens. Een finder in code-audit mag niet zomaar zeggen "this looks wrong". De skill dwingt elke bevinding in een vaste vorm: dimensie, ernst, exact bestand en regel, de betreffende code geciteerd, en een failure_scenario dat een concrete input of toestand moet zijn die tot een concrete, verkeerde uitkomst leidt. De skill zegt het met zoveel woorden: "This looks wrong" is not a scenario. Een lege lijst is uitdrukkelijk toegestaan en wordt respectabel genoemd.
Dat is geen versiering. "Rapporteer alles wat verdacht is" is een open uitnodiging om de lijst te vullen met onderbuikgevoel. Met een verplichte, concrete vorm valt er voor het model niets te onderhandelen. Of je kunt de input benoemen die het breekt, of je hebt geen bevinding. Diezelfde regel loopt door de prompt is geen spec: losse instructies leveren losse output, en de oplossing is om de vorm niet-optioneel te maken.
Dicht de mazen voordat de agent ze vindt. code-audit eindigt met een tabel met discipline-regels, elk gemarkeerd "no exceptions", en een lijst met red flags, getiteld "stop and correct yourself". Een stukje van die tabel:
| Rule | No exceptions |
|---|---|
| One skeptic per finding for critical/high severity | Never batch these |
| Never override a skeptic's REFUTED back to confirmed | If you disagree, spawn a second skeptic, majority wins |
| No finding skips verification | Move low-severity items to an Unconfirmed appendix, never assert unverified |
| Finder dies or returns garbage | Mark its unit "not audited", never fabricate coverage |
Elk van die regels bestaat omdat het een shortcut is waar een model onder druk naar grijpt. Sceptici bundelen om tijd te winnen. Een weerlegde bevinding stiekem terugzetten omdat hij goed aanvoelt. Een gecrashte subagent wegmoffelen zodat het rapport compleet lijkt. Deze regels in de skill schrijven is geen paranoia, het is geheugen: het is elke manier waarop deze procedure eerder is misgegaan, opgeschreven zodat het niet twee keer op dezelfde manier misgaat. Een skill zonder red-flags-sectie is een skill die zijn eigen faalmodi nog niet is tegengekomen.
Stem de inzet af op het doelwit. code-audit heeft een schaalregel: als het doelwit vijf bestanden of minder is, sla de finder-fan-out over en doe de zoekfase inline. Maar de verificatie wordt nooit minder, zelfs een piepklein doelwit krijgt nog steeds verse sceptische subagents. Dat is oordeelsvermogen dat rechtstreeks is vastgelegd. Start geen acht subagents op om een hulpbestand te auditeren, maar laat de kerngarantie nooit los alleen omdat de klus klein leek.
Wat je concreet moet doen
De volgende keer dat je naar een lege SKILL.md staart, werk in deze volgorde.
- Schrijf de description als trigger. Begin met "Use when", vul hem met de woorden die iemand echt zou typen of zeggen, en zeg waar de skill niet van toepassing is. Vat de stappen niet samen. Als je description de werkwijze uitlegt, schrap die helft.
- Schrijf de procedure, niet de intentie. Als je body leest als iets wat je in het chatvenster zou typen, is het een prompt. Knip hem op in fasen met elk een duidelijke taak. Benoem wat er gelezen wordt, wat er geproduceerd wordt, en in welke volgorde.
- Vind de stap waar het model tegen je gaat liegen, en bouw de controle in. Dit is het echte vak. Waar hangt de procedure ervan af dat de output van het model zelf klopt? Daar voeg je de onafhankelijke verificatie toe, de scepticus, de tweede blik die de redenering niet kan zien waardoor de eerste blik goed aanvoelde.
- Maak van de output een contract. Vaste velden, concreet bewijs verplicht, "een leeg antwoord is een geldig antwoord" hardop gezegd. Geef het model niets om de lijst mee op te vullen.
- Schrijf elke manier op waarop het is misgegaan. Een tabel zonder uitzonderingen en een lijst met red flags. Niet hypothetisch, maar doordat je het echt hebt zien falen. Als je de skill nooit hebt zien falen, weet je nog niet wat erin moet, en dus ben je niet klaar.
Een prompt vraagt het model om goed te zijn. Een skill gaat ervan uit dat het dat niet is, en houdt de lijn toch vast. Dat is het hele verschil, en daarom lezen de skills die het bewaren waard zijn allemaal minder als instructies en meer als een lijst van alle keren dat hun auteur zijn vingers al heeft gebrand.