---
name: skill-validator
description: |-
  Validate SKILL.md files against the Agent Skills spec and Claude Code extensions.
  Run on new or modified skills before committing.
metadata:
  internal: true
  version: "1.0.3"
  tags: "validation, skills, spec-compliance, quality"
title: skill-validator
canonical_url: https://skilld.dev/gh/shipshitdev/library/skill-validator
last_updated: 2026-09-29T12:24:48.000Z
---

> **Skill from skilld.dev.** Follow the instructions below for this session. You do not need to install anything.
>
> If the user asked to install this Skill, run `npx skilld install shipshitdev/library/skill-validator`. Install writes the Skill files into the project, so every session loads them.

# Skill Validator

Validate SKILL.md files against the Agent Skills specification and Claude Code extensions.

## When to Run

- After creating a new skill
- After modifying a skill's SKILL.md frontmatter
- Before committing skill changes
- During periodic repo audits

## Validation Rules

### Required Fields (Agent Skills Spec)

Every SKILL.md must have YAML frontmatter with:

- `name` — kebab-case, matches directory name
- `description` — 1-3 sentences, under 1024 chars, starts with verb or domain noun

### Metadata Block

`version` and `tags` must be inside `metadata:`, never top-level:

```yaml
# CORRECT
metadata:
  version: "1.0.0"
  tags: "react, performance, optimization"

# WRONG — top-level version
version: 1.0.0

# WRONG — tags as YAML list
metadata:
  tags:
    - react
    - performance
```

### Forbidden Fields

These are not part of any spec:

- `auto_activate` / `auto_trigger` — removed in 2026-04 migration
- `risk` — not in Agent Skills or Claude Code specs

### Claude Code Extensions (Optional)

Valid extension fields (must match `allowed_fields` in `scripts/validate-skill-sync.sh`):

| Field | Purpose |
|-------|---------|
| `when_to_use` | Extra trigger phrases appended to `description` |
| `disable-model-invocation` | Prevent auto-triggering (for destructive skills) |
| `user-invocable` | `false` hides from the `/` menu |
| `allowed-tools` | Auto-approve **allowlist** (not a sandbox — unlisted tools stay callable) |
| `disallowed-tools` | Removes tools from the pool while active (the actual block mechanism) |
| `argument-hint` | Autocomplete hint for expected arguments |
| `compatibility` | Environment prerequisites (packages, network, target agent) |
| `context` | `fork` for subagent isolation |
| `agent` | Subagent type when `context: fork` |
| `hooks` | Lifecycle hooks scoped to the skill |
| `paths` | ⚠️ Broken upstream (#49835) — flag if present |
| `shell` | `bash` (default) or `powershell` |

### Forbidden Fields (updated)

- `auto_activate` / `auto_trigger` — removed in 2026-04 migration
- `risk` — not in any spec
- `metadata.triggers` — duplicate activation metadata; put trigger phrases in
  `description` or `when_to_use`
- `model` / `effort` — recognized by Claude Code but owned by app/session
  configuration, not public reusable skills
- Any top-level field not in the tables above → "Unsupported top-level frontmatter field"

### Content Rules

- No hardcoded `/workspace/` paths
- No tool names in instructions (say "search for" not "use Grep")
- Imperative/infinitive style ("Configure X" not "You should configure X")
- Code blocks use real backtick fences, not escaped `\`\`\``
- **No concrete model names** in body, `references/`, or `scripts/` — reject tier+version IDs (`claude-3-7-sonnet-20250219`, `claude-opus-4.5`, `gpt-5.5`), dated snapshots, and bare family names used as routing keys. Exception: orchestrator skills may name **capability tiers** in prose. See [skill-standards.md → Model references](../memory/system/skill-standards.md).
- **No harness-owned execution parameters** in skills, commands, or routine templates.
  Apply [execution-boundary.md](../memory/system/execution-boundary.md).
- **Routine templates** follow
  [routine-standards.md](../memory/system/routine-standards.md). Run
  `python3 scripts/audit-routines.py` to detect duplicate bodies and app-parameter
  leakage without printing prompt or configuration values.
- **Provenance (derived skills only):** when `metadata.source` is set, `metadata.last_synced` and a README `## Upstream` section are required (enforced by `check_provenance()`). In-house skills need no provenance fields.

## Validation Process

1. Read the SKILL.md frontmatter
2. Check `name` matches parent directory name
3. Check `description` exists and is under 1024 chars
4. Check `description` plus `when_to_use` is under 1536 chars
5. Check `plugin.json` description is present and under 100 chars
6. Check `version`/`tags` are NOT top-level (must be inside `metadata:`)
7. Check for forbidden fields (`auto_activate`, `auto_trigger`, `risk`, `model`, `effort`, any field not in the extension tables)
8. Check for escaped backtick fences in content
9. Validate frontmatter value types: `allowed-tools` is a scalar,
   `metadata.version` and `metadata.tags` are quoted scalars, and `metadata` is a map
10. Reject duplicate `metadata.triggers`; keep activation guidance in `description`
    or `when_to_use`
11. Check for hardcoded paths (`/workspace/`, project-specific paths)
12. Grep body + `references/` + `scripts/` for concrete model names (`claude-*`, `gpt-*`, `sonnet`/`opus`/`haiku` used as IDs); allow only capability-tier prose in orchestrator skills
13. Warn when skills, commands, or templates set harness-owned execution parameters
14. Warn when a side-effecting skill lacks both `disable-model-invocation: true`
    and an explicit `Confirmation Required` gate
15. Check prose routing references across the body, excluding frontmatter and code
    fences, and flag missing local skills
16. Check provenance for derived skills: if `metadata.source` is set, require `metadata.last_synced` and a README `## Upstream` section
17. Run `bunx markdownlint-cli` on the file
18. Run `./scripts/validate-skill-sync.sh` for cross-validation

## Quick Validation Command

```bash
# Single skill
bunx markdownlint-cli skills/<name>/SKILL.md skills/<name>/references/*.md

# All skills
bunx markdownlint-cli --ignore bundles --ignore dist "**/*.md"

# Sync validation
./scripts/validate-skill-sync.sh
```
