Skill template
A copy-and-edit starting point for a new agent skill.
When it loads
Scaffold a new agent skill, writing the SKILL.md and its frontmatter to the Agent Skills specification, then wrapping it as a plugin in this repo with package.json, plugin.json and a marketplace entry. Use when the user asks to "add a new skill", "create a skill", "write a SKILL.md" or "start a new plugin", and when checking whether an existing skill is portable between agents.
The description from SKILL.md. A request is matched against this wording.
Install it
Into any agent
Installing a skill means putting its directory where your agent looks. The default is .agents/skills, which Codex, Cursor, VS Code and Gemini CLI all read.
npx @kensio/skills add skill-templatecurl -L https://github.com/KensioSoftware/kensio.ai/releases/download/v1.18.1/skill-template-1.18.1.zip -o skill-template.zipunzip skill-template.zip -d .agents/skills/mkdir -p .agents/skills/skill-templatecurl -L https://kensio.ai/skills/skill-template/SKILL.md \ -o .agents/skills/skill-template/SKILL.mdAs a Claude Code plugin
/plugin marketplace add KensioSoftware/kensio.ai/plugin install skill-template@kensioclaude plugin marketplace add KensioSoftware/kensio.aiclaude plugin install skill-template@kensioAs an npm package
npm install @kensio/skill-templatePer-agent directories and the rest of the options are on Installing skills. The file itself is served at /skills/skill-template/SKILL.md.
What it does
Skill template
A skill is a directory with a SKILL.md in it. That directory is the artefact, and every agent reads it. The plugin folder around it in this repository is packaging for one of them.
Write the skill first, following the specification. Then wrap it.
The skill directory
<skill-name>/├── SKILL.md├── references/ # optional, loaded only when linked to├── scripts/ # optional, anything the skill runs└── assets/ # optional, templates and data filesThose three subdirectory names come from the specification. An agent that supports skills at all knows this shape, whether it reads the directory from .agents/skills/, .claude/skills/, .github/skills/ or a plugin.
Every path a skill mentions is relative to its own directory. The directory gets copied out on its own, unzipped somewhere unrelated, and installed under a name this repository never sees. A command written as node skills/<skill-name>/scripts/check.mjs works here and nowhere else. Write node scripts/check.mjs. pnpm validate:skills fails the build on any path that reaches outside the skill, which is the check that caught this after it had already shipped once.
Frontmatter
---name: <skill-name>description: <what it does, then when to use it. Include the words and phrases a user would actually type>license: Apache-2.0metadata: version: "0.0.0"---nameis lowercase, hyphenated, at most 64 characters, and matches the containing directory.descriptionis the only thing an agent sees when deciding whether to load the skill. It carries the whole triggering burden. State what the skill does, then when to use it, in third person. Concrete trigger phrases beat abstract summaries. 1024 characters is the ceiling.licenseandmetadatatravel with the directory. A copy in someone’s.agents/skills/has no package.json beside it, and these are then the only record of what it is and where it came from. The release setsmetadata.version. Never edit that number by hand.- The specification allows two more keys.
compatibilitystates an environment requirement, such as a binary the scripts need.allowed-toolsrestricts the tools the skill may use, and support for it varies between agents. Any other key fails validation.
Keep SKILL.md under 500 lines. It is instructions for an agent, and documentation for a human belongs in the README. Push detail into references/ and link to it. The body stays cheap to load and the details are read only when needed.
Wrapping it as a plugin
Claude Code installs skills as plugins, so each one here has a plugin folder around it:
plugins/<skill-name>/├── package.json # npm package: @kensio/<skill-name>├── README.md # for humans arriving from npm or GitHub├── .claude-plugin/│ └── plugin.json # name, version, description, author└── skills/ └── <skill-name>/ # the skill directory above- Create
plugins/<skill-name>/following that layout. - Copy
package.jsonfrom an existing plugin, then setnameto@kensio/<skill-name>andrepository.directorytoplugins/<skill-name>. - Copy
.claude-plugin/plugin.json, then setnameanddescription. - Set the
versionin both files, and in theSKILL.mdfrontmatter, to whatever the other plugins currently carry. Versions move in lockstep across the whole repo and the release workflow is what changes them. Never pick a new number by hand. - Write
skills/<skill-name>/SKILL.md. - Add an entry to
.claude-plugin/marketplace.jsonwith a matchingname, asourceof"./plugins/<skill-name>", and a description. - Run
pnpm check.
Anything under skills/ ships, because that is what package.json lists in files. A script the skill runs belongs there too, and never at the plugin root.
A plugin folder must be self-contained. Never reference files outside it with ../. Plugins are copied, zipped and installed standalone, and those paths will not resolve.
Nothing else needs telling about the new folder. scripts/set-version.mjs, scripts/publish-npm.mjs and scripts/build-zips.mjs all read the plugins/ directory, so a new skill is versioned, bundled into @kensio/skills, zipped onto the release and published without being listed anywhere else.
A brand new package still needs one manual first publish. npm trusted publishing cannot create a package that does not exist, because the trusted publisher is configured against a package already on the registry. The release reports the commands and carries on. See “npm publishing” in the repository README.
Prose
pnpm check runs pnpm prose, which fails the build on em dashes, semicolons, and five sentence shapes measured against Django, Effective Go, the Rust Book and the Python docs. A new SKILL.md and README.md have to pass it.
Load the technical-prose-style skill before writing either one. It carries the rules, the before-and-after examples, and the evidence for each. Checking a single file while drafting:
node plugins/technical-prose-style/skills/technical-prose-style/scripts/prose-check.mjs plugins/<skill-name>Releasing
Releasing is automatic. Merging to main releases, and the version comes from the pull request title. fix: for a patch, feat: for a minor, feat!: or a BREAKING CHANGE footer for a major. A docs: or chore: title releases nothing.
Every plugin is set to the new version together. A released version means the same commit wherever it was installed from.