Skill File Validator
Validate skill files for correct format against the official Claude Code spec.
Validation Target
- With argument: validate specific file
- Without: validate all
.claude/skills/*/SKILL.md
Frontmatter Reference (official fields)
Skills support these fields. Only description is meaningfully required (a
skill with none of these still loads — name defaults to the directory name).
yaml--- name: skill-name # Optional: defaults to directory name; lowercase, hyphenated description: What it does # Recommended: shown in / menu and used for triggering when_to_use: When to reach for it # Optional: appended to description for triggering # (description + when_to_use truncated at 1,536 chars in listings) user-invocable: true # Optional: default true; false hides from / menu (Skill tool still works) model: sonnet # Optional: any /model value (sonnet, opus, haiku, fable, best, # default, opusplan, sonnet[1m], opus[1m], a full model ID) or inherit effort: medium # Optional: low, medium, high, xhigh, max allowed-tools: # Optional: pre-approved tools. Accepts a comma-separated string - Read # OR a YAML list — BOTH are official (list shown here as house style) - Grep - Glob disallowed-tools: # Optional: explicitly blocked tools (string or YAML list) - WebFetch context: fork # Optional: run the skill in a subagent agent: agent-name # Optional: subagent type when context: fork (default: general-purpose) background: false # Optional (2.1.218+): with context: fork, false waits for the result; # forked skills run in the background by default argument-hint: "[issue-number]" # Optional: autocomplete hint shown after the skill name arguments: target flags # Optional: space-separated argument NAMES for $name substitution # (e.g. arguments "target flags" -> use $target and $flags in the body). # NOT a structured array of name/description/required objects. disable-model-invocation: false # Optional: bool; true also blocks scheduled-task invocation paths: # Optional: glob patterns that limit where the skill activates - "src/**/*.ts" shell: bash # Optional: bash or powershell for inline !`command` blocks hooks: # Optional: skill-scoped lifecycle hooks (same schema as settings.json) PreToolUse: - matcher: Write hooks: - type: command command: ./scripts/validate.sh Stop: - hooks: - type: command command: ./scripts/verify.sh once: true ---
Valid Tools (for allowed-tools / disallowed-tools)
Read, Write, Edit, Bash, Grep, Glob, Agent (Task = legacy alias), Skill, WebFetch, WebSearch, TodoWrite, NotebookEdit, AskUserQuestion
Non-official fields (flag as warnings, not errors)
metadata, license, version # Not part of the skill spec; harmless but should be removed once # Valid ONLY inside a hooks[] entry, never at skill top level
Validation Checklist
Required / Recommended Fields
-
descriptionpresent (recommended; used for the / menu and triggering) -
name, if present, is lowercase and hyphenated (defaults to directory name if omitted)
Optional Field Validation
-
allowed-tools/disallowed-toolsare valid tool names -
allowed-tools/disallowed-toolsare a comma-separated string OR a YAML list (both valid) -
allowed-toolsdoes not broadly preapprove bareBash,Edit,Write,Agent,Task, orSkill; omit it when normal runtime approval is required -
modelis a /model value (fable, opus, sonnet, haiku, best, default, opusplan, sonnet[1m], opus[1m], a full model ID) or inherit -
effortis one of: low, medium, high, xhigh, max -
contextisfork(if specified) -
agentonly set alongsidecontext: fork(defaults to general-purpose) -
backgroundis boolean and only set alongsidecontext: fork(default true since 2.1.218) -
argument-hintis a string -
argumentsis a space-separated string of argument names (NOT a structured array) -
when_to_useis a descriptive string (appended to description for triggering) -
description+when_to_usestay within 1,536 characters (the listing truncates beyond it) -
disable-model-invocationis boolean -
pathsis a list of glob patterns -
shellisbashorpowershell -
user-invocableis boolean -
hookshas valid structure (matcher + hooks[] with type/command)
Unknown / Non-official Fields
- Accept
metadata(map),license, andcompatibility(<=500 chars): official but not acted on - Warn on
versionand any other field outside the official list; Claude Code ignores them silently - Warn on
onceused at the top level (only valid inside a hooks[] entry)
Content Structure
- Clear instructions
- Uses
$ARGUMENTS(or$nameperarguments) if expecting input - Step-by-step process if complex
Output Format
markdown## Skill Validation Report ### Files Checked | File | Status | Issues | |------|--------|--------| | workflow/SKILL.md | OK | None | | my-skill/SKILL.md | WARN | Missing description | ### Summary - Total: [N] - Valid: [N] - Needs fixes: [N]
Auto-Fix
- Add missing
namefrom directory name - Add missing
description - Normalize a comma-separated
allowed-toolsstring to a YAML list (house style only — the string form is valid; do NOT flag it as an error) - Remove non-official fields (
metadata,license,version) - Convert a structured
argumentsarray to a space-separated name string - Replace
opusplanmodel with a supported value - Add
$ARGUMENTShandling


