Writing skills

Writing skills

How the skills published here are written. The format is the Agent Skills specification, which Claude Code, Codex, Cursor, Copilot and Gemini CLI all read, and what follows is convention (this page adds no rules to the spec). These are the conventions that made the difference between a skill that gets used and one that sits in a marketplace untouched.

The description does the work

It is the only part the agent reads before deciding

A skill is loaded on the strength of its description alone. However good the body is, the description has to match the way someone actually phrases the request. It is the one field every agent reads at startup, whichever one the reader has.

So the description is written as two things joined together. The first half says what the skill does, and the second names the concrete situations that should trigger it.

plugins/isolated-testing-style/skills/isolated-testing-style/SKILL.md
---
name: isolated-testing-style
description: Write tests that use real collaborators through simulation instead of stubs and mocks, take their isolation from randomised data rather than setup and teardown, and assert behaviour rather than call counts. Use when writing or reviewing tests, when a test needs a collaborator faked, when reaching for a mock, spy, `toHaveBeenCalledWith`, `beforeEach`/`afterEach` fixtures or a hardcoded expected hash, and when asked "how should I test this?".
license: Apache-2.0
metadata:
version: "1.11.0"
---

The trigger half names specific function names, specific file shapes, and a question asked in the words a person would use. Abstract descriptions of a problem domain rarely trigger. The artefacts someone is looking at when they need the skill do.

One skill, one job

Scope is what makes triggering possible at all

The temptation with a skill that works is to grow it. Resist it. A skill covering testing, deployment and code review has a description that matches everything. It gets loaded for everything, and its presence stops telling the agent anything about the task at hand.

When a skill starts needing "and also", that is a second skill. The three testing skills published here could have been one. They are three because each answers a different question.

Write rules with their reasons

A rule without a reason gets applied literally or not at all

Every rule in these skills is followed by the failure it exists to prevent. That pairing does real work. An agent that knows why a rule holds can recognise a genuine exception when it meets one. An agent given a bare instruction either applies it everywhere or abandons it at the first friction.

A useful test

If you cannot name the specific bug a rule would have caught, it is probably a preference. Preferences land better as an example than as an instruction.

The layout of a skill

One directory, and it travels on its own
The skill directory
my-skill/
SKILL.md # frontmatter + the instructions themselves
references/ # optional, loaded only when linked to
scripts/ # optional, anything the skill runs

That directory is the artefact. An agent reads it from .agents/skills/, .claude/skills/, .github/skills/ or a plugin, and the contents are the same in each. references/, scripts/ and assets/ are the names the specification gives the optional parts.

Every path a skill mentions is relative to that directory. It gets copied out on its own and installed under a name the source repository never sees, so a command written as node skills/my-skill/scripts/check.mjs works in the repository and nowhere else. Write node scripts/check.mjs.

Publishing it to the Claude Code marketplace means wrapping that directory, and changing nothing inside it:

The plugin around it
plugins/my-skill/
package.json # @kensio/my-skill, versioned in lockstep
README.md # for humans arriving from npm or GitHub
.claude-plugin/
plugin.json
skills/
my-skill/ # the skill directory above, unchanged

The plugin name, the directory under skills/ and the name in the frontmatter all match. That is a convention held by hand, and the sync that builds this website relies on it (as does every human reading the repository).

package.json carries the version, and metadata.version in the frontmatter repeats it for the copies that travel without a package.json beside them. Claude Code notices an update only when that number changes. A released fix that forgets to bump it is a fix nobody receives.

Start from the template

The skill-template skill is a copy-and-edit starting point that carries all of the above. Install it, or read it inthe public repository.