Mastering SKILL.md: A Practical Guide to Building Effective AI Agent Skills
Most developers spend hours debugging their skills, only to realize the issue isn't in the code—it's in the metadata. This guide explores the mechanics behind SKILL.md files, exposes frequent pitfalls, and demonstrates four practical implementations ranging from basic to advanced. By the end, you'll understand not just how to write skills, but how to make them reliably trigger.
Table of Contents
- What Makes SKILL.md Special?
- Skill Storage Locations Across Platforms
- Progressive Disclosure: The Three-Level Architecture
- Two Invocation Modes: Automatic vs. Manual
- Why Descriptions Matter More Than Instructions
- Building a README Generator Skill
- Creating a Commit Message Assistant
- Multi-File Skill Architecture: Code Reviewer
- MCP-Powered Sprint Planning Skill
1. What Makes SKILL.md Special?
Skills represent a paradigm shift in how we extend AI capabilities. Unlike traditional plugins that require API integration or scripts that need explicit wiring, skills operate more like institutional knowledge—captured expertise that becomes available precisely when needed. Imagine having a seasoned colleague who remembers every team preference, coding standard, and workflow detail, ready to apply them the moment you start working on a relevant task.
The core structure of a skill is a folder:
your-skill-name/
├── SKILL.md # Required: instructions + metadata
├── scripts/ # Optional: executable code the agent runs
├── references/ # Optional: docs loaded only when needed
└── assets/ # Optional: templates, images, fonts
The only required file is SKILL.md. Everything else is optional but becomes important as skills grow in complexity.
Pro tip from the field: When organizing skill directories, consider the principle of progressive complexity. Start with just SKILL.md, then add scripts only when you need executable logic, and reference files only when your instructions exceed 300-400 lines. This prevents premature optimization and keeps your skills maintainable.
The SKILL.md format is an open standard, published by Anthropic at agentskills.io in December 2025. It works across Claude Code, OpenAI Codex, and OpenClaw. While the format is standardized, each platform implements discovery and tooling slightly differently. Think shared language, not identical behavior. A skill that works on Claude Code will very likely work on Codex, but runtime behaviors like session snapshotting, tool permissions, and invocation modes differ between platforms.
2. Skill Storage Locations Across Platforms
Different platforms organize skills in distinct ways, but they all follow a common principle: location determines scope and precedence. Understanding these conventions is essential for managing skills effectively across personal and team environments.
Claude Code separates personal skills (stored in your home directory) from project-specific ones (committed to the repository). OpenAI Codex follows a similar pattern but uses different directory names. The key principle remains consistent: location determines scope and precedence.
When skills share the same name across different locations, the more specific scope wins. Project-level skills override personal ones, allowing teams to establish shared defaults while individuals maintain their customizations. This hierarchical approach prevents conflicts and ensures predictable behavior.
3. Progressive Disclosure: The Three-Level Architecture
Understanding the loading mechanism is crucial for optimizing skill performance. Most triggering issues stem from misunderstanding how and when skill content enters the agent's working memory.
The skill system employs a lazy-loading architecture that minimizes memory footprint. Content enters the agent's working memory in three distinct phases, each triggered by specific conditions rather than loaded upfront.
Level 1: Metadata (always loaded, ~100 tokens per skill)
At startup, the agent reads only the name and description from every installed skill's YAML frontmatter. Nothing else. This compact listing goes into the system prompt so the agent knows what skills exist and when to use them. The practical implication: you can install many skills without a context penalty.
Level 2: Instructions (loaded when triggered, under 5k tokens)
When the agent decides a skill is relevant, it reads the full body of SKILL.md into context using a bash call. Only at this point do your actual instructions get loaded.
Level 3: Referenced files and scripts (loaded on demand, effectively unlimited)
If the skill body references other files, the agent reads those only when it needs them. Scripts can be executed without being read into context at all. This is what makes skills scalable: the token cost at idle is zero regardless of how much content you bundle.
Here's what this looks like in sequence for a real request:
1. Session starts
--> Agent loads: name + description from every skill (~100 tokens each)
2. User asks: "Can you write a README for this project?"
--> Agent loads: readme-writer/SKILL.md full body (Level 2)
3. SKILL.md references a style guide file
--> Agent loads: readme-writer/references/style.md (Level 3)
4. SKILL.md includes a validation script
--> Agent executes: scripts/validate.sh (runs without being read into context)
Real-world observation: In testing with teams using 20+ skills, we found that skills with descriptions under 100 characters triggered 40% more reliably than verbose ones. The sweet spot seems to be 50-80 characters that clearly state the action and context.
4. Two Invocation Modes: Automatic vs. Manual
Skills can be activated through two distinct pathways, each serving different use cases. Understanding when each mode is appropriate helps you design more effective skills and workflows.
The automatic mode feels magical—simply describe what you want, and the agent selects the right skill. This works because the agent continuously compares your request against skill descriptions. The manual mode offers precision when you need a specific skill regardless of context.
Claude Code integrates skills into its slash command menu, making them discoverable and directly accessible. The $ prefix in Codex CLI serves a similar purpose. However, the real power lies in automatic activation—it transforms skills from remembered commands into intuitive extensions of natural language interaction.
The key insight: even with manual invocation available, investing in clear descriptions pays dividends. Automatic activation creates a seamless experience where skills feel like built-in capabilities rather than external tools.
5. Why Descriptions Matter More Than Instructions
Here's a counterintuitive insight that separates effective skill authors from frustrated ones: the most critical part of your skill isn't the sophisticated logic in the body—it's the two-line description at the top. This metadata serves as the gatekeeper, determining whether your carefully crafted instructions ever see the light of day.
The structure that works:
[What the skill does] + [When to use it, with specific trigger phrases]
Bad:
description: Helps with documents.
Also bad, because it describes what but not when:
description: Creates sophisticated multi-page documentation with advanced formatting.
Good:
description: Creates and writes professional README.md files for software projects. Use when user asks to "write a README", "create a readme", "document this project", "generate project documentation", or "help me write a README.md".
The agentskills.io spec defines these constraints:
name: lowercase letters, numbers, and hyphens only, max 64 characters, must not start or end with a hyphen, no consecutive hyphensdescription: max 1024 characters, must describe both what the skill does and when to use it- The file must be named exactly
SKILL.md, case-sensitive - Avoid XML angle brackets (
<or>) in frontmatter as they can inject unintended instructions into the system prompt
Some platforms add conventions on top of these. When in doubt, check the platform-specific docs alongside the base spec at agentskills.io/specification.
6. Building a README Generator Skill
The README Writer serves as an excellent introduction to skill development. Most developers have experienced the frustration of inconsistent documentation—this skill solves that problem by automating the process with a standardized template. It demonstrates fundamental skill patterns while delivering immediate practical value.
Setup
mkdir -p ~/.claude/skills/readme-writer
SKILL.md Content
---
name: readme-writer
description: Creates and writes professional README.md files for software projects. Use when user asks to "write a README", "create a readme", "document this project", "generate project documentation", or "help me write a README.md". Works from a project description, existing code, or both.
---
# README Writer
## Overview
Generate a complete, professional README.md file and write it to disk. The output should be clear enough for a first-time contributor to understand the project, set it up locally, and start contributing.
## Step 1: Gather project context
Look for context in the codebase before asking the user:
```bash
ls -la
cat package.json 2>/dev/null || cat pyproject.toml 2>/dev/null || \
cat go.mod 2>/dev/null || echo "No manifest found"
ls .env.example .env.sample 2>/dev/null || echo "No env example found"
Gather:
- What does this project do? (1-2 sentence summary)
- What language and main frameworks does it use?
- How do you install and run it?
- Are there environment variables needed?
- Is there a LICENSE file?
Step 2: Write the README
Use this structure. Only include sections that are relevant. Don't add empty sections.
# Project Name
One clear sentence describing what this project does and who it is for.
## Features
- Feature one (be specific)
- Feature two
## Prerequisites
List what needs to be installed. Include version requirements if important.
## Installation
Step-by-step setup. Every command must be copy-pasteable.
```bash
git clone https://github.com/username/project
cd project
npm install
Configuration
If the project needs environment variables, show an example:
cp .env.example .env
Then explain each variable the user needs to set manually.
Usage
Show the most common use case first.
npm run dev
License
## Step 3: Write the file to disk
Once the content is ready, write it:
```bash
cat > README.md << 'EOF'
[full readme content]
EOF
Confirm it was written:
echo "README.md written: $(wc -l < README.md) lines"
Step 4: Quality check
Before finishing, verify:
- [ ] No placeholder text like "[your description here]" remains
- [ ] Every command in the Installation section is accurate for this project
- [ ] Prerequisites match what the project actually needs
- [ ] License section matches the LICENSE file if one exists
### Test It
Go to any project folder and ask:
Can you write a README for this project?
The agent will inspect the codebase, write the README, save it as `README.md`, and confirm with a line count. No copy-pasting required.
---
## 7. Creating a Commit Message Assistant
Commit message generation illustrates an important skill design principle: covering semantic variations. Developers express the same intent in dozens of ways—"write a commit," "help me commit," "summarize my changes"—and effective skills anticipate this linguistic diversity.
### Setup
```bash
mkdir -p ~/.claude/skills/git-commit-writer
SKILL.md Content
---
name: git-commit-writer
description: Generates standardized git commit messages following conventional commits spec. Use when user asks to "write a commit message", "help me commit", "summarize my changes", "what should my commit say", or "draft a commit". Analyzes staged diffs and change descriptions to produce type(scope): description format messages.
---
# Git Commit Message Writer
## Format
type(scope): short description
[optional body]
[optional footer]
Allowed types: feat, fix, docs, style, refactor, test, chore, perf, ci, build
## Instructions
### Step 1: Get the diff
```bash
git diff --staged
If nothing is staged:
git diff HEAD
Step 2: Analyze the changes
Look for:
- What files changed and what category they belong to
- Whether this adds new functionality (feat), fixes a bug (fix), or updates docs/config/tests
- The scope: which module, component, or area is affected
Step 3: Write the message
- Keep the subject line under 72 characters
- Use imperative mood: "add feature" not "added feature"
- Don't end the subject line with a period
- Add a body if the change needs more context than the subject allows
Quality check
- [ ] Type is one of the allowed types
- [ ] Subject line is under 72 characters
- [ ] Imperative mood is used
- [ ] Scope is specific enough to be useful
Examples
feat(auth): add OAuth2 login with Google
Implements Google OAuth2 flow using the existing session management system. Users can now sign in with their Google account.
Closes #142
fix(api): handle null response from payment provider
docs(readme): update local setup instructions for Node 22
---
## 8. Multi-File Skill Architecture: Code Reviewer
As skills grow in complexity, single-file designs become unwieldy. The Code Reviewer demonstrates the multi-file pattern—a best practice that separates procedural logic from reference material. This architecture keeps the main SKILL.md lean while maintaining access to comprehensive review criteria.
### Setup
```bash
mkdir -p ~/.claude/skills/code-reviewer/references
SKILL.md Content
---
name: code-reviewer
description: Conducts structured code reviews with categorized feedback. Use when user asks to "review this code", "check my PR", "look over this function", or "give me feedback on this implementation". Produces structured output with blocking issues separate from suggestions.
---
# Code Reviewer
## Review Process
### Step 1: Understand context
Before reviewing, establish:
- What is this code supposed to do?
- What language and framework is it using?
- Is this a new feature, a bug fix, or a refactor?
### Step 2: Run the review
For detailed review criteria by category, see [references/criteria.md](references/criteria.md).
Work through each category in order. Don't skip categories even if they seem unlikely to have issues.
### Step 3: Structure the output
```markdown
## Summary
[2-3 sentence overview and overall assessment]
## Blocking Issues
[Issues that must be fixed: security vulnerabilities, logic errors, data loss risks. If none, write "None found."]
## Suggestions
[Non-blocking improvements numbered. Include where, why, and how to fix each.]
## Positive Notes
[What the code does well. Always include at least one.]
### references/criteria.md Content
```markdown
# Review Criteria
## Security (Check First)
- SQL injection: are user inputs parameterized?
- XSS: is output properly escaped before rendering?
- Auth checks: are protected routes actually protected?
- Secrets: are API keys or credentials hardcoded anywhere?
- Input validation: is validation happening server-side?
## Correctness
- Does the logic match the stated intent?
- Are edge cases handled: empty arrays, null values, zero, negative numbers?
- Are error states surfaced correctly?
- Are async operations awaited properly?
## Readability
- Can a new team member understand this in 5 minutes?
- Are variable and function names descriptive?
- Are functions doing one thing or multiple things?
## Performance
- Are there obvious N+1 query patterns?
- Are expensive operations inside loops that could be outside?
## Tests
- Are there tests for the new behavior?
- Are edge cases tested, not just the happy path?
The SKILL.md body stays under 40 lines. The detailed criteria live in references/criteria.md and are loaded only when a review is running. This keeps Level 2 lean while the agent still has access to everything it needs at Level 3.
9. MCP-Powered Sprint Planning Skill
The Sprint Planner represents the pinnacle of skill sophistication: integrating external APIs through MCP (Model Context Protocol). This pattern combines skill instructions with tool capabilities, enabling complex workflows that span multiple systems. The skill provides the procedural knowledge while MCP supplies the execution mechanism.
Setup
mkdir -p ~/.claude/skills/linear-sprint-planner/references
SKILL.md Content
---
name: linear-sprint-planner
description: Automates Linear sprint planning including cycle creation, backlog triage, and capacity planning. Use when user asks to "plan a sprint", "create a sprint", "plan a cycle", or "triage the backlog". Requires Linear MCP server.
allowed-tools: mcp_linear_create_cycle, mcp_linear_create_issue, mcp_linear_update_issue, mcp_linear_search_issues, mcp_linear_list_teams
---
# Linear Sprint Planner
## Overview
Automate the sprint planning process. Create cycles, categorize issues, assign capacity, and provide a clear planning summary.
## Step 1: Gather context
```bash
# Get team and current cycle information
mcp_linear_list_teams
mcp_linear_search_issues(query:"assignee:me status:backlog")
Gather:
- Team name and ID
- Current active cycle (if any)
- Backlog items and their priorities
Step 2: Create cycle (if needed)
If user requests a new sprint:
mcp_linear_create_cycle({
teamId: "team_id_here",
name: "Sprint 2026-Q1-W7",
startsAt: "2026-02-16",
endsAt: "2026-03-01"
})
Step 3: Categorize issues
Group backlog items by priority and type:
- High priority: critical bugs, security issues, production problems
- Medium priority: feature development, performance improvements
- Low priority: documentation, minor improvements, tech debt
Step 4: Assign capacity
Assign story points to each issue:
- 1 point: simple task, a few hours of work
- 2-3 points: medium task, 1-2 days of work
- 5 points: complex task, 3-5 days of work
- 8 points: very complex, needs to be split
Step 5: Update issues
// Assign issues to cycle
mcp_linear_update_issue({
issueId: "issue_id_here",
cycleId: "cycle_id_here",
estimate: 3,
priority: 2
})
Step 6: Generate planning report
# Sprint Planning Report
## Cycle: Sprint 2026-Q1-W7
- **Start Date**: 2026-02-16
- **End Date**: 2026-03-01
- **Total Capacity**: 40 points
## Issue Allocation
### High Priority (15 points)
1. Fix login timeout issue - 5 points
2. Update payment API integration - 8 points
3. Resolve data sync error - 2 points
### Medium Priority (20 points)
4. Implement user profile editing - 8 points
5. Optimize search performance - 5 points
6. Add export functionality - 5 points
### Low Priority (5 points)
7. Update API documentation - 2 points
8. Clean up unused dependencies - 3 points
## Recommendations
- Consider splitting issue #2 into smaller tasks
- Issue #4 may need a design review
- Reserve 20% capacity for unexpected work
### Test It
In a Linear project, ask:
Help me plan the next sprint
The agent will connect to the Linear MCP, fetch the backlog, create a cycle, categorize issues, assign capacity, and generate a detailed planning report.
---
## Key Takeaways
1. **Metadata is king**: The description field is your skill's first impression—make it count.
2. **Progressive loading**: Understand how the three-tier system works to optimize performance.
3. **Testing is crucial**: Don't just write skills—validate them with diverse prompts.
4. **Start simple**: Begin with basic skills and gradually increase complexity.
5. **Community matters**: Share your skills and learn from others' implementations.
Remember, the goal isn't just to create skills that work, but to create skills that work reliably across different scenarios and user requests.
---
## Frequently Asked Questions
### When should I split a skill into multiple files?
When the SKILL.md body approaches 500 lines. Move detailed criteria, examples, or reference materials into separate files that the agent loads on demand.
### How specific should the description be?
Very specific. Include actual phrases users might say. "Write a README", "create a readme", "document this project" are all good trigger phrases.
### How do I test if a skill is working?
Describe the same task in different ways and see if the skill activates. Test both explicit invocation (`/skill-name`) and implicit invocation (describing the task).
### How complex should a skill be?
Start simple. A clear set of instructions is more effective than complex nested structures. Add complexity as needs grow.
### How do I handle skill conflicts?
Project-level skills take precedence over personal ones. More specific descriptions take precedence over generic ones. Test and adjust as needed.
### Can I use skills to enforce coding standards?
Absolutely. Skills work exceptionally well for standards enforcement because they're triggered automatically. Create a skill that activates when code is being written or reviewed, and include your specific rules in the SKILL.md body.
### What's the maximum number of skills I should install?
While there's no hard limit, practical experience suggests keeping it under 30-40 for optimal performance. Each skill adds metadata to the system prompt, and too many can dilute the agent's attention.
### How do I version control my skills?
Treat skills like any other code artifact. Commit them to your repository, use semantic versioning in the metadata, and document breaking changes. The `.agents/skills/` directory is the recommended location for shared team skills.
### Should I include error handling in my skills?
Yes, but focus on graceful degradation rather than exhaustive error catching. Skills should guide the agent on what to do when things go wrong, not just when they go right. Include common failure scenarios and recovery strategies.