verify-skill
string (required, when to use this agent)
Installation
Follow the repository instructions for this skill and your agent. Review the files and dependencies before adding it to your workflow.
View source ↗GuidesSkill instructions
Verify Skill
This skill provides exact schemas and validation rules for Claude Code plugin components.
Exact Schemas
plugin.json Schema
Location: <plugin-root>/plugin.json
{
"name": "string (required, kebab-case)",
"version": "string (required, semver)",
"description": "string (required)",
"author": {
"name": "string (required if author present)"
},
"license": "string (optional)",
"repository": "string (optional, URL)",
"keywords": ["array of strings (optional)"]
}
✅ CORRECT plugin.json:
{
"name": "my-plugin",
"version": "1.0.0",
"description": "A plugin description",
"author": {
"name": "Developer Name"
}
}
❌ WRONG plugin.json examples:
// WRONG: author as string instead of object
{
"name": "my-plugin",
"version": "1.0.0",
"description": "A plugin",
"author": "Developer Name" // ❌ Must be object: { "name": "..." }
}
// WRONG: missing required fields
{
"name": "my-plugin" // ❌ Missing version and description
}
// WRONG: invalid name format
{
"name": "My Plugin", // ❌ Must be kebab-case: "my-plugin"
"version": "1.0.0",
"description": "A plugin"
}
marketplace.json Schema
Location: <repo>/.claude-plugin/marketplace.json (in .claude-plugin/ directory)
IMPORTANT: This is for Model B (Marketplace distribution) only. See Directory Structure section.
{
"$schema": "string (optional, https://claude.ai/schemas/marketplace.json)",
"name": "string (required, kebab-case)",
"owner": {
"name": "string (required)"
},
"metadata": {
"description": "string (optional)",
"version": "string (optional, semver)"
},
"plugins": [
{
"name": "string (required)",
"source": "string (required, path to plugin directory, e.g. ./plugins/name)",
"description": "string (optional)",
"version": "string (optional)"
}
]
}
✅ CORRECT marketplace.json:
{
"$schema": "https://claude.ai/schemas/marketplace.json",
"name": "my-marketplace",
"owner": {
"name": "Team Name"
},
"metadata": {
"description": "Marketplace description",
"version": "1.0.0"
},
"plugins": [
{
"name": "my-plugin",
"source": "./plugins/my-plugin",
"description": "Plugin description",
"version": "1.0.0"
}
]
}
❌ WRONG marketplace.json examples:
// WRONG #1: marketplace.json at repo root (wrong location)
// ❌ my-marketplace/marketplace.json (WRONG - at root)
// ✅ my-marketplace/.claude-plugin/marketplace.json (CORRECT)
// WRONG #2: source pointing to "./" instead of plugin directory
{
"plugins": [{
"name": "my-plugin",
"source": "./" // ❌ WRONG: Use "./plugins/my-plugin"
}]
}
// WRONG #3: source including .claude-plugin path
{
"plugins": [{
"name": "my-plugin",
"source": "./plugins/my-plugin/.claude-plugin" // ❌ WRONG - don't include .claude-plugin
}]
}
// WRONG #4: "author" instead of "owner"
{
"name": "my-marketplace",
"author": "Team Name", // ❌ WRONG: Use "owner": { "name": "..." }
"plugins": []
}
// WRONG #5: "owner" as string instead of object
{
"name": "my-marketplace",
"owner": "Team Name", // ❌ WRONG: Must be object with "name" field
"plugins": []
}
// WRONG #6: "path" instead of "source" in plugins
{
"name": "my-marketplace",
"owner": { "name": "Team" },
"plugins": [
{
"name": "plugin",
"path": "." // ❌ WRONG: Use "source": "./plugins/name"
}
]
}
// WRONG #7: "config" object in plugins (not allowed)
{
"name": "my-marketplace",
"owner": { "name": "Team" },
"plugins": [
{
"path": ".",
"config": { // ❌ WRONG: "config" is not allowed
"name": "plugin",
"version": "1.0.0"
}
}
]
}
// WRONG #8: Extra fields not in schema
{
"name": "my-marketplace",
"owner": { "name": "Team" },
"displayName": "My Marketplace", // ❌ WRONG: Not in schema
"license": "MIT", // ❌ WRONG: Not in schema
"repository": "https://...", // ❌ WRONG: Not in schema
"keywords": [], // ❌ WRONG: Not in schema
"categories": [], // ❌ WRONG: Not in schema
"requirements": {}, // ❌ WRONG: Not in schema
"installation": {}, // ❌ WRONG: Not in schema
"plugins": []
}
Agent Schema
Location: <plugin-root>/agents/<agent-name>.md
---
name: string (required, kebab-case)
description: string (required, when to use this agent)
tools:
- ToolName (required, array)
model: string (optional: haiku, sonnet, opus)
color: string (optional: blue, cyan, green, yellow, magenta, red)
---
# System Prompt Content
✅ CORRECT agent:
---
name: my-agent
description: Use this agent when analyzing code quality
tools:
- Read
- Grep
- Glob
model: haiku
color: blue
---
# My Agent
You are a code analysis agent...
❌ WRONG agent examples:
# WRONG: File at wrong location
# Location: agents/my-agent/agent.md ❌
# Correct: agents/my-agent.md ✅
# WRONG: Missing required fields
---
name: my-agent
# ❌ Missing description and tools
---
# WRONG: tools as string instead of array
---
name: my-agent
description: An agent
tools: Read, Grep # ❌ Must be array: ["Read", "Grep"]
---
# WRONG: allowed_tools instead of tools
---
name: my-agent
description: An agent
allowed_tools: # ❌ WRONG: Use "tools" not "allowed_tools"
- Read
---
Command Schema
Location: <plugin-root>/commands/<command-name>.md
---
name: string (required, kebab-case)
description: string (required)
allowed-tools:
- ToolName (optional, array, kebab-case field name!)
argument-hint: string (optional)
---
# Command Content
✅ CORRECT command:
---
name: my-command
description: Runs my command
allowed-tools:
- Read
- Write
argument-hint: "<file-path>"
---
# /my-command
Instructions for the command...
❌ WRONG command examples:
# WRONG: allowed_tools (underscore) instead of allowed-tools (hyphen)
---
name: my-command
description: A command
allowed_tools: # ❌ WRONG: Use "allowed-tools" (kebab-case)
- Read
---
# WRONG: File at wrong location
# Location: commands/my-command/command.md ❌
# Correct: commands/my-command.md ✅
Skill Schema
Location: <plugin-root>/skills/<skill-name>/SKILL.md
---
name: string (required, kebab-case)
triggers:
- string (required, array of trigger phrases)
---
# Skill Content
✅ CORRECT skill:
---
name: my-skill
triggers:
- "use my skill"
- "activate skill"
---
# My Skill
Skill content...
❌ WRONG skill examples:
# WRONG: File at wrong location
# Location: skills/my-skill.md ❌
# Correct: skills/my-skill/SKILL.md ✅
# WRONG: triggers as string
---
name: my-skill
triggers: "use my skill" # ❌ Must be array
---
# WRONG: Missing SKILL.md filename
# Location: skills/my-skill/index.md ❌
# Correct: skills/my-skill/SKILL.md ✅
hooks.json Schema
Location: <plugin-root>/hooks/hooks.json
{
"$schema": "https://claude.ai/schemas/hooks.json",
"description": "string (optional)",
"hooks": {
"EventName": [
{
"matcher": "string (optional, regex pattern)",
"hooks": [
{
"type": "command",
"command": "string (required, with ${CLAUDE_PLUGIN_ROOT})",
"timeout": "number (optional, seconds)"
}
]
}
]
}
}
Event names: PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification
✅ CORRECT hooks.json:
{
"$schema": "https://claude.ai/schemas/hooks.json",
"hooks": {
"PreToolUse": [
{
"matcher": "^Bash$",
"hooks": [
{
"type": "command",
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/validate.py",
"timeout": 10
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "python3 ${CLAUDE_PLUGIN_ROOT}/hooks/stop.py",
"timeout": 10
}
]
}
]
}
}
❌ WRONG hooks.json examples:
// WRONG #1: hooks as array instead of object
{
"hooks": [ // ❌ Must be object keyed by event name
{
"event": "PreToolUse",
"matcher": "^Bash$",
"command": "..."
}
]
}
// WRONG #2: Using "event" field instead of object key
{
"hooks": {
"PreToolUse": [
{
"event": "PreToolUse", // ❌ Don't use event field, it's the object key
"hooks": [...]
}
]
}
}
// WRONG #3: Missing nested "hooks" array
{
"hooks": {
"PreToolUse": [
{
"matcher": "^Bash$",
"command": "..." // ❌ Must be inside hooks array with type
}
]
}
}
// WRONG #4: Missing "type": "command"
{
"hooks": {
"PreToolUse": [
{
"hooks": [
{
"command": "python3 script.py" // ❌ Missing "type": "command"
}
]
}
]
}
}
// WRONG #5: Hardcoded path
{
"hooks": {
"PreToolUse": [
{
"hooks": [
{
"type": "command",
"command": "python3 /home/user/hooks/script.py" // ❌ Use ${CLAUDE_PLUGIN_ROOT}
}
]
}
]
}
}
Directory Structure
Model A: Standalone Plugin (Local Development)
✅ CORRECT structure:
my-plugin/
├── plugin.json # Required at root
├── agents/
│ └── my-agent.md # Direct file, not subdirectory
├── commands/
│ └── my-command.md # Direct file, not subdirectory
├── skills/
│ └── my-skill/
│ └── SKILL.md # Must be SKILL.md in subdirectory
└── hooks/
├── hooks.json # Hook configuration
└── my-hook.py # Hook scripts
Model B: Marketplace (GitHub Distribution)
✅ CORRECT structure:
my-marketplace/ # Repository root
├── .claude-plugin/
│ └── marketplace.json # In .claude-plugin/ directory
├── README.md
├── LICENSE
└── plugins/
└── my-plugin/
└── .claude-plugin/ # Plugin content HERE
├── plugin.json # Required
├── agents/
│ └── my-agent.md
├── commands/
│ └── my-cmd.md
├── skills/
│ └── my-skill/
│ └── SKILL.md
└── hooks/
├── hooks.json
└── my-hook.py
❌ WRONG marketplace structures:
# WRONG: marketplace.json at repo root (should be in .claude-plugin/)
my-marketplace/
├── marketplace.json # ❌ Should be in .claude-plugin/
└── plugins/
# WRONG: Plugin content at repo root (not in plugins/ directory)
my-marketplace/
├── .claude-plugin/
│ └── marketplace.json
├── plugin.json # ❌ Should be in plugins/<name>/.claude-plugin/
├── agents/ # ❌ Should be in plugins/<name>/.claude-plugin/
└── skills/ # ❌ Should be in plugins/<name>/.claude-plugin/
# WRONG: Missing .claude-plugin directory for plugin
my-marketplace/
├── .claude-plugin/
│ └── marketplace.json
└── plugins/
└── my-plugin/
├── plugin.json # ❌ Missing .claude-plugin/ wrapper
└── agents/
❌ General WRONG structures:
# WRONG: Agent in subdirectory
agents/my-agent/agent.md ❌
agents/my-agent.md ✅
# WRONG: Command in subdirectory
commands/my-command/command.md ❌
commands/my-command.md ✅
# WRONG: Skill as direct file
skills/my-skill.md ❌
skills/my-skill/SKILL.md ✅
# WRONG: Skill with wrong filename
skills/my-skill/index.md ❌
skills/my-skill/skill.md ❌
skills/my-skill/SKILL.md ✅
Verification Commands
# Validate JSON syntax
python3 -c "import json; json.load(open('file.json'))"
# Validate YAML frontmatter
python3 -c "import yaml; yaml.safe_load(open('file.md').read().split('---')[1])"
# Validate Python syntax
python3 -m py_compile file.py
# Check file exists
test -f path/to/file && echo "EXISTS" || echo "MISSING"
Quick Reference: Common Mistakes
| Wrong | Correct |
|---|---|
marketplace.json at repo root |
.claude-plugin/marketplace.json |
"source": "./" (for marketplace) |
"source": "./plugins/name" |
"source": "plugins/name/.claude-plugin" |
"source": "./plugins/name" |
| Plugin content at repo root | Inside plugins/<name>/.claude-plugin/ |
"author": "Name" |
"owner": { "name": "Name" } |
"path": "." |
"source": "./plugins/name" |
"config": { ... } |
Not allowed in plugins array |
allowed_tools: |
allowed-tools: |
agents/x/agent.md |
agents/x.md |
skills/x.md |
skills/x/SKILL.md |
tools: Read, Grep |
tools: [Read, Grep] |
"hooks": [...] (array) |
"hooks": { "EventName": [...] } (object) |
Missing "type": "command" |
Always include in hook command |
Marketplace Cross-Validation
When validating a marketplace.json, perform these additional cross-checks:
1. Marketplace Location Check
-
marketplace.jsonMUST be in.claude-plugin/directory - NOT at repository root
2. Plugin Source Path Validation
For each plugin in the plugins array:
- The
sourcepath must follow the pattern:./plugins/<name>(NOT including .claude-plugin) - The source directory must contain a
.claude-plugin/plugin.json - Resolve paths relative to
.claude-plugin/marketplace.jsonlocation
3. Name Consistency Check
- Plugin
namein marketplace.json must match thenamefield in the corresponding plugin.json - Report mismatches as validation errors
4. Invalid Fields Detection
The following fields are NOT allowed in marketplace.json:
-
authorat root level (useownerinstead) -
pathin plugins (usesourceinstead) -
configobject in plugins -
source: "./"pointing to root (should point to./plugins/<name>) -
sourceincluding.claude-plugin(should be./plugins/namenot./plugins/name/.claude-plugin)
Validation should fail if any of these invalid fields are present.
Cross-Validation Commands
# Check marketplace.json is in .claude-plugin/ (not at repo root)
test -f ".claude-plugin/marketplace.json" && echo "CORRECT: In .claude-plugin/" || echo "WRONG: Not in .claude-plugin/"
test -f "marketplace.json" && echo "WRONG: At repo root" || echo "OK"
# Check plugin.json exists at source path (source points to plugin dir, .claude-plugin/plugin.json inside)
SOURCE_PATH="./plugins/my-plugin"
test -f "${SOURCE_PATH}/.claude-plugin/plugin.json" && echo "EXISTS" || echo "MISSING"
# Extract and compare names
MARKETPLACE_NAME=$(python3 -c "import json; print(json.load(open('.claude-plugin/marketplace.json'))['plugins'][0]['name'])")
PLUGIN_NAME=$(python3 -c "import json; print(json.load(open('${SOURCE_PATH}/.claude-plugin/plugin.json'))['name'])")
[ "$MARKETPLACE_NAME" = "$PLUGIN_NAME" ] && echo "MATCH" || echo "MISMATCH: $MARKETPLACE_NAME vs $PLUGIN_NAME"
Examples
Read the usage examples in the source repository.
View source ↗Source history
- Indexed on
- 2026-01-20
- Index updated
- 2026-01-26
- Branch
- main
Index and sync dates describe this directory. View the source repository for code history.
GitHub ↗chat Comments (0)
Sign in to join the discussion and leave a comment.
No comments yet. Be the first to share your thoughts!