>_devkit
catalogue
Stablev1.0.1

devkit-skill-authoring

by @chempa

Showing v1.0.1. The latest is v1.1.0. The install command below is pinned to the version you are looking at.

Use when writing, validating, publishing, or versioning a skill for a devkit registry - the SKILL.md format, the frontmatter rules, and the init/validate/publish loop.

devkit-skill-authoring

How to write a skill that a devkit registry will accept and that Claude will actually load. Everything here is the behaviour of @devkit/core, which is the one validator the CLI, the server, CI, and the in-browser editor all share - so what passes locally passes on publish, for the same reasons.

When to use this

  • Writing a new skill, or fixing one the registry rejected
  • Deciding what belongs in SKILL.md versus a references/ file
  • Publishing, versioning, yanking, or forking
  • Working against more than one registry and needing the right one

The whole loop

devkit init my-skill        # scaffold a folder that already validates
$EDITOR my-skill/SKILL.md
devkit validate my-skill    # the registry's own checks, locally
devkit publish my-skill     # upload it

If you do not have the CLI yet, it comes from the registry itself and needs no token - it is a client and holds no skills:

curl -sSL https://your-registry.example.com/install/cli | sh
devkit login https://your-registry.example.com   # prompts for a token

Mint the token at /manage/settings. Publishing needs the publish scope.

A skill is one folder

my-skill/
  SKILL.md          ← required, at the root
  references/       ← optional, ships with the skill
    checklist.md

There is no manifest. The YAML frontmatter at the top of SKILL.md is the metadata, and the body below it is what Claude loads.

The folder name is the slug, and it must equal the frontmatter name. Slugs are lowercase, hyphen-separated, 3-64 characters, starting and ending alphanumeric. all and cli are refused - the registry already serves those install URLs.

Frontmatter

---
name: code-reviewer
description: Use when reviewing a diff for correctness, dead code, and missing tests.
version: 1.0.0
author: your-handle
license: MIT
tags: [ai, claude, code-review]
status: beta
created: 2026-08-02
updated: 2026-08-02
---
KeyRequiredRule
nameyesMust equal the folder name
descriptionyes10-200 characters, one line
versionyesSemVer; must not already exist in the registry
authoryesLetters, digits, _ . -; max 40
licenseyesAn SPDX identifier (MIT, Apache-2.0, …)
tagsyesInline list, 1-8 entries
statusyesstable, beta, or deprecated
created / updatednoYYYY-MM-DD
featurednoSet by the registry, not by you

The frontmatter parser is deliberately not YAML. It handles key: scalar, inline lists ([a, b, c]), quoted scalars, and # comments - and it throws on indentation, nested maps, block sequences (- item), and multi-line scalars (|, >) rather than mis-parsing them quietly. Keep every value on one line.

For the exact rules, every error message, and what each one means, read references/frontmatter.md.

The description is the field that matters

It is the only part of the skill Claude sees before deciding whether to load it. It has to carry the trigger conditions by itself. Write when to use this, not what this is:

# good - names the situations that should match
description: Use when reviewing a diff, preparing a PR, or asked to check code for bugs.

# bad - accurate, and gives nothing to match against
description: A code review helper.

A skill with a vague description is not a broken skill; it is a skill that never gets loaded, which is worse, because nothing reports it.

The body

Everything below the closing --- is the skill. It is what Claude loads and what the catalogue renders, so it has two readers and must work for both. It must be non-empty.

Keep SKILL.md focused. Anything long - checklists, tables, worked examples - goes in a sibling file that the body points at on demand:

For the full colour formula, read `references/palette.md`.

Every file in the folder is published and lands in the installer's ~/.claude/skills/<slug>/, so those siblings are on their disk afterwards.

For how to write a body Claude actually follows, read references/writing-well.md.

What gets published

Everything in the folder, except housekeeping: .DS_Store, Thumbs.db, .git, .gitignore, .gitkeep, .keep, node_modules, .devkit.json, and editor leftovers matching ~, .#, or .tmp.. Those are your repository's business and nobody downstream's.

There are no secrets in a skill folder. Everything in it is published, and on a public registry, world-readable.

Limits, all enforced at publish:

LimitValueWhy
Files per skill64A skill is documentation, not a package
One file512 KBSame
Whole skill2 MBBounds the upload and the unpacked size
Path length100 bytes incl. <slug>/ustar's name field

Paths may not be absolute, contain .. or . segments, use backslashes, or contain NUL. The install writes straight into ~/.claude/skills/<slug>/, so this is a security boundary rather than tidiness.

Versions are immutable

Publishing a version that already exists is a 409. To change a published skill, bump version: and publish again.

An install pins a content digest, verified on download, so "the skill I installed" and "the skill in the registry" can be compared - and a bad version is rolled back by installing the previous one rather than by hoping somebody reconstructs it.

latest is the highest release. A pre-release (2.0.0-rc.1) is installable by exact version but never becomes the default.

Publishing, registries, tokens, yanking, forking, and visibility are covered in references/publishing.md.

Before you publish

  • Folder name and frontmatter name are identical
  • description names trigger conditions, 10-200 chars, one line
  • Every frontmatter value is on a single line
  • version is SemVer and has not been published before
  • The body is non-empty and reads on its own
  • No secrets anywhere in the folder
devkit validate my-skill

Then try the real install, somewhere disposable:

export CLAUDE_HOME=$(mktemp -d)
devkit install my-skill
find "$CLAUDE_HOME"

CLAUDE_HOME redirects the install target, so you can inspect exactly what an installer gets without touching your real ~/.claude.

When something is rejected

references/troubleshooting.md maps each error the validator, the CLI, and the server produce to its cause and its fix.