From skill-best-practices
Use when creating a new skill, building a plugin, writing SKILL.md files, setting up hooks, creating commands, or learning skill development best practices. Triggers on: create skill, new skill, build plugin, skill best practices, skill development, write SKILL.md, plugin structure, skill guide, scaffold skill, new plugin, plugin development, skill template, how to write a skill.
How this skill is triggered — by the user, by Claude, or both
Slash command
/skill-best-practices:skill-best-practicesThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Comprehensive guide for building great Claude Code skills and plugins.
Comprehensive guide for building great Claude Code skills and plugins.
Use this as a reference when building any skill — from a simple convention guide to a full
multi-phase production workflow. For an interactive creation wizard, run /create-skill.
Every new skill needs these 10 things. Check them off before shipping:
skills/<skill-name>/SKILL.md (required entry point)name + description (description starts with "Use when...")references/ filesdisable-model-invocation: true if skill has side effectschmod +x), assets accessible./Knowledge Claude applies to current work — conventions, patterns, style guides.
Runs inline with conversation context. No disable-model-invocation.
---
name: api-conventions
description: Use when writing API endpoints or designing REST interfaces for this codebase
---
When writing API endpoints:
- Use RESTful naming conventions
- Return consistent error formats
Step-by-step instructions for specific actions — deployments, commits, code generation.
Often invoked manually. Use disable-model-invocation: true for side effects.
---
name: deploy
description: Use when deploying the application to production or staging environments
context: fork
disable-model-invocation: true
---
Deploy the application:
1. Run the test suite
2. Build the application
3. Push to the deployment target
| Frontmatter | User invokes | Claude invokes | When loaded |
|---|---|---|---|
| (default) | Yes | Yes | Description always in context |
disable-model-invocation: true | Yes | No | Description NOT in context |
user-invocable: false | No | Yes | Description always in context |
Two fields supported: name and description (max 1024 chars total).
---
name: my-skill-name
description: >
Use when [specific triggering conditions]. Triggers on: keyword1, keyword2, keyword3.
---
Name: Lowercase letters, numbers, hyphens only. Max 64 chars.
Description: The single most important field. Claude uses this to decide when to auto-load your skill. Write it poorly and your skill never activates. Rules:
See skill-anatomy.md for the full frontmatter reference including
argument-hint, allowed-tools, model, context, agent, and hooks fields.
# Skill Name
## Overview
Core principle in 1-2 sentences.
## [Core Content]
The main instructions, patterns, or workflow.
Scale sections to their complexity.
## Phase/Step Details (if task skill)
Phase-by-phase breakdown with clear gates.
Reference external docs for each phase.
## Error Recovery (if applicable)
Fallback chains, common failure modes.
## Common Mistakes
What goes wrong + fixes.
Key patterns from well-built skills:
Read references/topic.md before starting..claude/skills/
my-skill/
SKILL.md # Main instructions (required)
references/ # Detailed docs per topic
scripts/ # Utility scripts
assets/ # Templates, images
my-plugin/
├── .claude-plugin/
│ └── plugin.json # Only plugin.json goes here
├── skills/
│ └── my-skill/
│ ├── SKILL.md
│ └── references/
├── commands/ # At plugin root, NOT inside .claude-plugin/
│ └── my-command.md
├── hooks/ # At plugin root
│ ├── hooks.json
│ └── my-hook.sh
└── agents/ # At plugin root (optional)
└── my-agent.md
See plugin-packaging.md for the full plugin structure, manifest schema, caching behavior, and distribution guide.
Claude decides whether to load your skill based on the description field. A vague or missing
description means your skill never activates. A description that summarizes the workflow causes
Claude to shortcut — following the summary instead of reading the full skill.
# BAD: Summarizes workflow — Claude follows this instead of reading skill body
description: Dispatches subagent per task with code review between tasks
# BAD: Too vague — won't match user prompts
description: For async testing
# GOOD: Triggering conditions only, no workflow
description: Use when executing implementation plans with independent tasks in the current session
Move detailed content to references/ files. Reference them from SKILL.md so Claude
knows they exist and when to load them:
## Phase 5 — Workspace Setup
Read `references/tool-setup.md` before starting.
Each reference document covers one topic. Don't combine "hooks configuration" with "plugin packaging" in the same file. This keeps documents focused and lets Claude load only what's relevant.
Use disable-model-invocation: true for any skill that:
This prevents Claude from auto-triggering expensive or destructive workflows.
Verify Claude loads your skill for expected prompts. Check:
/context for warningsSee evaluation-testing.md for testing methodology.
One markdown file per major topic. Structure each as:
Executable shell/python scripts in scripts/. Always:
#!/bin/bash or #!/usr/bin/env python3 shebangchmod +x scripts/my-script.sh${CLAUDE_PLUGIN_ROOT} for paths in plugin context"$VAR"Templates, images, config files in assets/. Include a README.md
explaining what each file is for.
Test cases in evals/evals.json. Format:
[
{
"name": "descriptive-test-name",
"prompt": "Natural language that should trigger the skill",
"expected_trigger": "skill-name",
"expected_behaviors": [
"Specific behavior the skill should produce",
"Another expected behavior"
]
}
]
Commands are .md files with YAML frontmatter. They create /command-name slash commands.
---
command: my-command
description: One-line description of what this command does
disable-model-invocation: true
---
[Markdown instructions for the command workflow]
Commands and skills with the same name conflict — the skill takes precedence.
Use commands for action-oriented workflows (e.g., /deploy, /record-demo, /create-skill).
Hooks run shell commands, prompts, or agents in response to events. Define them in:
hooks/hooks.json — global to the pluginhooks: field — scoped to skill lifecycle{
"hooks": {
"SessionStart": [
{
"matcher": "startup",
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/hooks/load-env.sh",
"timeout": 5,
"statusMessage": "Loading environment..."
}
]
}
]
}
}
See hooks-and-events.md for all event types, matchers, hook types, and exit code semantics.
Convert standalone skills to plugins when you want to:
plugin-name:skill-name)Critical caching gotcha: Plugins are copied to ~/.claude/plugins/cache. Files outside
the plugin directory are NOT copied. Use ${CLAUDE_PLUGIN_ROOT} for all paths.
Version management: Bump the version in marketplace.json before distributing changes. Cached copies only update when the version changes.
See plugin-packaging.md for full details.
Before shipping any skill, verify:
Structure:
Content:
Testing:
claude --plugin-dir ./my-plugin worksPackaging (if plugin):
.claude-plugin/ only.claude-plugin/See common-mistakes.md for the full list. Top 5:
.claude-plugin/ → Only plugin.json goes therenpx claudepluginhub prakhar625/my-plugins --plugin skill-best-practicesGuides developers in creating, improving, and organizing SKILL.md files for Claude Code plugins, covering frontmatter, triggers, structure, progressive disclosure, hooks, budgets, and best practices.
Creates new Claude Code skills from scratch following best practices for structure, naming, frontmatter, progressive disclosure, reference organization, and tool scoping. Use for building skills or converting slash commands.
Guides creation of new Claude Code skills from scratch, listing existing user/project skills, samples, current directory, and providing metadata templates for descriptions/tags.