---
name: claude-code-skill-spec
source: https://app.decimal.ai/s/claude-code-skill-spec@1/SKILL.md
source_sha256: a944318accc8
---

# Claude Code Skill Spec

## Contract

Enforces the exact on-disk shape of a Claude Code Agent Skill. Apply whenever you are asked to
create, scaffold, generate, or author a Claude Code / Agent Skill — the output must match this fixed
format, not an invented manifest shape.

## Rules

The format is arbitrary and fixed. Reproduce every part of it.

1. **Location.** Put the skill at `.claude/skills/<kebab-name>/SKILL.md`. The `<kebab-name>`
   directory sits DIRECTLY under `.claude/skills/`.
   - `<kebab-name>` is lower-case kebab-case: `changelog-generator`, not `ChangelogGenerator` or
     `changelog_generator`.
   - There is exactly one directory level between `.claude/skills/` and `SKILL.md`. No nested
     namespaces, no `category/skill/` grouping, no `skill/v1/` versioning under the name.
   - Personal (user-wide) skills live at `~/.claude/skills/<name>/`; project skills at
     `<repo-root>/.claude/skills/<name>/`. Same `<name>/SKILL.md` shape in both.
2. **Filename.** The main file is named EXACTLY `SKILL.md` — upper-case `SKILL`, lower-case `.md`.
   Not `skill.md`, `Skill.md`, `skill.yaml`, `manifest.json`, `manifest.yaml`, `index.md`, or
   `README.md`. (A `README.md` may exist alongside as human docs, but it is never the skill file.)
3. **Frontmatter block.** `SKILL.md` MUST begin with a YAML frontmatter block: the very first line
   is `---` alone, then the fields, then a closing line of `---` alone. Nothing precedes the opening
   `---` (no blank line, no comment, no H1).
4. **Frontmatter keys — exactly two.** The frontmatter contains EXACTLY the keys `name` and
   `description`, and no others.
   - Forbidden keys (Claude ignores them; including any is wrong): `version`, `author`, `tags`,
     `tools`, `license`, `category`, `model`, `created`, `updated`, `maintainer`, `difficulty`,
     `allowed-directories`, or anything else. Only `name` and `description`.
5. **`name`.** A short, human-friendly title string, at most 64 characters. Title Case is
   conventional (`Changelog Generator`). This is the display name and differs from the kebab-case
   directory: dir `changelog-generator`, `name: Changelog Generator`.
6. **`description`.** At most 1024 characters, and it MUST state BOTH what the skill does AND when to
   use it. Include an explicit trigger clause, conventionally phrased starting with `Use when …`.
   Front-load concrete trigger keywords so Claude matches it. A description with no "when" clause is
   invalid even if grammatical.
7. **Body opening.** Immediately after the closing `---`, the body's first heading is a single H1:
   `# <Name>`. Not `##`, not prose before the heading.
8. **Lean body / progressive disclosure.** Keep `SKILL.md` lean. Long reference material, templates,
   and scripts go in separate files the body links to (`scripts/`, `resources/`, `references/` under
   the skill dir) — not inlined as walls of text. The frontmatter + body are what Claude reads first;
   linked files load on demand.

## Worked examples

One BEFORE (a plausible-looking wrong default) → AFTER (conforming) per rule.

### Rule 1 — location & nesting

BEFORE — nested namespace folders and a grouping directory:
```
.claude/skills/git/changelog/generator/SKILL.md
```
AFTER — one kebab-case directory directly under `.claude/skills/`:
```
.claude/skills/changelog-generator/SKILL.md
```

### Rule 2 — filename

BEFORE — lower-case / wrong extension:
```
.claude/skills/changelog-generator/skill.md
.claude/skills/changelog-generator/manifest.yaml
```
AFTER — exact casing:
```
.claude/skills/changelog-generator/SKILL.md
```

### Rule 3 — frontmatter is YAML fenced by `---`, not JSON

BEFORE — a `package.json`-style manifest:
```json
{ "name": "Changelog Generator", "description": "Generates changelogs." }
```
AFTER — YAML frontmatter at the top of `SKILL.md`:
```markdown
---
name: Changelog Generator
description: "Generate a changelog from git history. Use when cutting a release."
---
```

### Rule 4 — exactly two keys

BEFORE — extra keys borrowed from npm/semver habits:
```yaml
---
name: Changelog Generator
version: 1.0.0
author: platform-team
tags: [git, docs]
description: Generates changelogs.
---
```
AFTER — only `name` and `description`:
```yaml
---
name: Changelog Generator
description: "Generate a changelog from git history grouped by type. Use when cutting a release or updating CHANGELOG.md."
---
```

### Rule 5 — name length & form

BEFORE — a kebab id reused as the display name, or an overlong sentence:
```yaml
name: changelog-generator-that-reads-git-history-and-groups-by-commit-type
```
AFTER — short, human-friendly title ≤ 64 chars:
```yaml
name: Changelog Generator
```

### Rule 6 — description must say WHAT and WHEN

BEFORE — what only, no trigger:
```yaml
description: "A tool that generates changelogs from git history."
```
AFTER — what + explicit `Use when` trigger:
```yaml
description: "Generate a changelog from git history grouped by commit type. Use when cutting a release, summarizing merged PRs, or updating CHANGELOG.md."
```

### Rule 7 — body opens with H1 `# <Name>`

BEFORE — body starts with prose or a sub-heading:
```markdown
---
name: Changelog Generator
description: "... Use when cutting a release."
---
This skill generates changelogs.
```
AFTER:
```markdown
---
name: Changelog Generator
description: "... Use when cutting a release."
---

# Changelog Generator

This skill generates changelogs from git history.
```

### Rule 8 — lean body, link the rest

BEFORE — a 600-line `SKILL.md` with every template pasted inline.
AFTER — a short `SKILL.md` that links out:
```markdown
See `resources/templates/changelog.hbs` for the template.
Run `scripts/build.sh` to generate.
```

## Edge cases & exceptions

- **`name` with special characters** (`:`, `#`, leading `@`): quote the YAML string —
  `name: "JSON:API Builder"`. Unquoted `name: JSON:API Builder` is a YAML parse error.
- **Description near the 1024-char limit:** trim prose, keep the `Use when` trigger — the trigger is
  load-bearing, not the prose.
- **Multiple related skills:** each gets its OWN `.claude/skills/<name>/` directory. Do not put two
  skills in one folder or namespace them under a parent.
- **The skill needs scripts or templates:** allowed — put them in `scripts/`, `resources/`, or
  `references/` UNDER the skill dir. These are content subdirs, not the forbidden "nested namespace
  under the skill name"; `SKILL.md` still sits at the top of the skill dir.
- **A `README.md` for humans:** fine to include alongside `SKILL.md`, but Claude reads `SKILL.md`. The
  `README.md` is never a substitute for it.
- **Kebab dir vs Title-Case name:** they intentionally differ — directory `pr-summarizer`,
  `name: PR Summarizer`. Don't force them to match.

## Do / Don't

- DON'T name the file `skill.md`, `Skill.md`, `skill.yaml`, or `manifest.json`. ALWAYS name it
  `SKILL.md`.
- DON'T emit the skill as a JSON / TOML / `package.json` object. ALWAYS use a Markdown file with a
  YAML frontmatter block.
- DON'T add `version`, `author`, `tags`, `tools`, `license`, or `category` to the frontmatter. ALWAYS
  stop at `name` and `description`.
- DON'T write a `description` that only says what it does. ALWAYS include an explicit `Use when …`
  trigger.
- DON'T nest the skill under grouping/namespace folders. ALWAYS place `<name>/` directly under
  `.claude/skills/`.
- DON'T start the body with prose or `##`. ALWAYS open with the H1 `# <Name>`.

## Common mistakes (the base's wrong defaults)

- Emitting a `package.json`-shaped JSON manifest instead of a Markdown + YAML-frontmatter file.
- Reflexively adding `version: 1.0.0`, `author`, and `tags` from package-manifest habit.
- Lower-casing the filename to `skill.md`, or using `manifest.yaml` / `README.md` as the skill file.
- Writing a `description` that states only the function and omits the `Use when` trigger.
- Nesting the skill under a category/namespace path like `.claude/skills/git/changelog/`.
- Forgetting the opening `# <Name>` H1, or putting text before the frontmatter's first `---`.

## Quick checklist

- [ ] Path `.claude/skills/<kebab-name>/SKILL.md`, one dir level, no nesting.
- [ ] File named exactly `SKILL.md`.
- [ ] Frontmatter fenced by `---` lines, at the very top.
- [ ] Exactly two keys: `name` and `description` — nothing else.
- [ ] `name` ≤ 64 chars; `description` ≤ 1024 chars with an explicit `Use when` trigger.
- [ ] Body opens with `# <Name>`.
- [ ] Long material linked from `scripts/` / `resources/`, not inlined.
