| name | skill-authoring |
| description | Expert guidance for creating Claude Code skills and slash commands. Use when authoring new skills, improving existing skills, creating commands, or understanding skill structure and best practices. |
| user-invocable | false |
Creating Skills & Commands
This skill teaches how to create effective Claude Code skills following the official specification from code.claude.com/docs/en/skills.
Commands and Skills Are Now The Same Thing
Custom slash commands have been merged into skills. A file at .claude/commands/review.md and a skill at .claude/skills/review/SKILL.md both create /review and work the same way. Existing .claude/commands/ files keep working. Skills add optional features: a directory for supporting files, frontmatter to control invocation, and automatic context loading.
If a skill and a command share the same name, the skill takes precedence.
When To Create What
Use a command file (commands/name.md) when:
- Simple, single-file workflow
- No supporting files needed
- Task-oriented action (deploy, commit, triage)
Use a skill directory (skills/name/SKILL.md) when:
- Need supporting reference files, scripts, or templates
- Background knowledge Claude should auto-load
- Complex enough to benefit from progressive disclosure
Both use identical YAML frontmatter and markdown content format.
Standard Markdown Format
Use YAML frontmatter + markdown body with standard markdown headings. Keep it clean and direct.
---
name: my-skill-name
description: What it does and when to use it
---
# My Skill Name
## Quick Start
Immediate actionable guidance...
## Instructions
Step-by-step procedures...
## Examples
Concrete usage examples...
Frontmatter Reference
All fields are optional. Only description is recommended.
| Field | Required | Description |
|---|
name | No | Display name. Lowercase letters, numbers, hyphens (max 64 chars). Defaults to directory name. |
description | Recommended | What it does AND when to use it. Claude uses this for auto-discovery. Max 1024 chars. |
argument-hint | No | Hint shown during autocomplete. Example: [issue-number] |
disable-model-invocation | No | Set true to make a pure slash command (zero context cost, invisible to Claude). Default: false. |
user-invocable | No | Set false to hide from / menu. Only use for knowledge bank skills. Default: true. |
allowed-tools | No | Tools Claude can use without permission prompts. Example: Read, Bash(git *) |
model | No | Model to use. Options: haiku, sonnet, opus. |
context | No | Set fork to run in isolated subagent context. |
agent | No | Subagent type when context: fork. Options: Explore, Plan, general-purpose, or custom agent name. |
Invocation Control
| Frontmatter | User can invoke | Claude can invoke | When loaded |
|---|
| (default) | Yes | Yes | Description always in context, full content loads when invoked |
disable-model-invocation: true | Yes | No | Description not in context, loads only when user invokes |
user-invocable: false | No | Yes | Description always in context, loads when relevant |
The key insight: disable-model-invocation: true is the only way to keep a skill out of the 2% context budget. It removes the description from context entirely, making the skill a pure slash command -- zero context cost, invisible to Claude, only fires when you type /name.
Decision framework -- what belongs in the 2% budget?
Only skills you want Claude to auto-discover should consume context budget. Everything else should be a slash command (disable-model-invocation: true) with zero context cost.
- Default (both flags false): Use for skills Claude should discover AND users might invoke. Description counts toward 2% budget.
user-invocable: false: Use for knowledge bank skills -- background reference Claude should auto-detect but users never type. Description counts toward 2% budget.
disable-model-invocation: true: Use for everything else -- workflows, commands, actions you'll invoke by typing /name. Zero context cost. This is the old-school slash command pattern.
Dynamic Features
Arguments
Use $ARGUMENTS placeholder for user input. If not present in content, arguments are appended automatically.
---
name: fix-issue
description: Fix a GitHub issue
disable-model-invocation: true
---
Fix GitHub issue $ARGUMENTS following our coding standards.
Access individual args: $ARGUMENTS[0] or shorthand $0, $1, $2.
Dynamic Context Injection
The ! + backtick-wrapped command syntax runs shell commands before content is sent to Claude. For example, writing ! followed by a command in backticks (like gh pr diff) will execute that command and inject the output.
Example skill using dynamic context:
The PR diff and changed files lines below would use the bang-backtick syntax to call gh pr diff and gh pr diff --name-only respectively, injecting the output before Claude sees the content.
---
name: pr-summary
description: Summarize changes in a pull request
context: fork
agent: Explore
---
- PR diff: (use bang-backtick with: gh pr diff)
- Changed files: (use bang-backtick with: gh pr diff --name-only)
Summarize this pull request...
Running in a Subagent
Add context: fork to run in isolation. The skill content becomes the subagent's prompt. It won't have conversation history.
---
name: deep-research
description: Research a topic thoroughly
context: fork
agent: Explore
---
Research $ARGUMENTS thoroughly:
1. Find relevant files
2. Analyze the code
3. Summarize findings
Progressive Disclosure
Keep SKILL.md under 500 lines. Split detailed content into reference files:
my-skill/
โโโ SKILL.md # Entry point (required, overview + navigation)
โโโ reference.md # Detailed docs (loaded when needed)
โโโ examples.md # Usage examples (loaded when needed)
โโโ scripts/
โโโ helper.py # Utility script (executed, not loaded)
Link from SKILL.md: For API details, see [reference.md](reference.md).
Keep references one level deep from SKILL.md. Avoid nested chains.
Naming & Descriptions
Choosing a Name
Each component type has a natural part of speech. Consistency within a type creates a predictable mental model.
| Component | Case | Part of Speech | Examples |
|---|
| Plugin | kebab-case | Noun/noun-compound | cortex-engineering, git-workflow |
| Skill (action) | kebab-case | Verb or verb-phrase | research, deploy-staging |
| Skill (knowledge) | kebab-case | Noun or noun-compound | api-conventions, frontmatter |
| Command | kebab-case | Verb (imperative) | deploy, fix-issue |
| Agent | kebab-case | Role-noun | debugger, code-reviewer |
The Five Rules of Naming
- Never repeat the plugin name in component names -- the namespace handles scope
- Match skill names to command counterparts -- if
/research delegates to a skill, name the skill research
- Use the description for AI routing, not the name -- name is for humans, description is for Claude
- Maintain part-of-speech consistency within a type -- commands are verbs, agents are role-nouns, knowledge skills are nouns
- Treat published names as API contracts -- renaming is a semver-major change
Invocation control changes strategy:
- User-invoked skills/commands: optimize for human recall (verb-noun, memorable, typable)
- Auto-triggered skills: description matters more than name
- Keep
name matching directory name for predictability
Name Anti-Patterns
| Anti-Pattern | Why It Fails | Fix |
|---|
Overly generic: check, process | Too broad, fails recall and discovery | Add domain context: spam-check |
Plugin name repeated: cortex:cortex-research | Namespace stuttering | Drop prefix: cortex:research |
Too long: code-review-and-security-analysis-agent | Untypable | 1-3 words max |
Ambiguous siblings: update vs upgrade | Users can't remember which is which | Use distinct verbs |
For advanced naming topics (agent naming, namespace strategy, budget constraints), invoke the naming-conventions skill.
Writing Effective Descriptions
The description enables skill discovery. Follow the WHAT + WHEN + WHEN NOT pattern. Always write in third person -- descriptions are injected into the system prompt.
Good:
description: Extract text and tables from PDF files, fill forms, merge documents. Use when working with PDF files or when the user mentions PDFs, forms, or document extraction.
Bad:
description: Helps with documents
Tips:
- Front-load capabilities, include file extensions (
.pdf, .xlsx), user synonyms ("deck" for presentations), and action verbs
- Max 1024 characters, but match length to competition -- unique skills need less, contested domains need more
- Use "pushy" language: "Make sure to use this skill whenever..." outperforms passive phrasing
For the full description-writing guide (activation rates, length strategy, pushy pattern, WHEN NOT clauses), see description-writing.md.
Argument Hints
Use POSIX bracket conventions: <required>, [optional], {a|b} for choices. Keep under 30 characters.
argument-hint: <topic>
argument-hint: <issue-number>
argument-hint: <file> [format]
For detailed conventions, see argument-hints.md.
What Would You Like To Do?
- Create new skill - Build a skill or command from scratch
- Audit existing skill - Check against best practices with scored report
- Add component - Add to an existing skill:
- Get guidance - Understand whether/how to build something
Routing keywords: create -> 1, audit -> 2, add reference -> 3a, add workflow -> 3b, add template -> 3c, add script -> 3d, guidance -> 4
If arguments match a keyword or menu item, read the corresponding workflow and begin.
Otherwise, reply with a number or describe what you need.
$ARGUMENTS
Anti-Patterns to Avoid
- XML tags in body - Use standard markdown headings
- Vague descriptions - Be specific with trigger keywords
- Deep nesting - Keep references one level from SKILL.md
- Wasting context budget - Only skills Claude should auto-discover belong in the 2% budget; use
disable-model-invocation: true for everything else
- Too many options - Provide a default with escape hatch
- Punting to Claude - Scripts should handle errors explicitly
Reference Files
For detailed guidance, see:
Sources