Skip to content

Skill Structure Explained

What You'll Learn

  • Precisely understand all SKILL.md field requirements and format specifications
  • Master the design principles and use cases for references/, scripts/, assets/
  • Optimize skill token usage and loading performance
  • Avoid common format errors and path resolution issues
  • Use progressive loading to improve AI context efficiency

Current Challenges

You've learned to create basic skills, but your understanding of the complete SKILL.md specification is limited. Your skills may encounter these problems:

  • SKILL.md is too long, causing excessive token consumption
  • Uncertain about what content belongs in references/ versus SKILL.md
  • AI agents cannot correctly load resources from scripts/ or assets/
  • YAML frontmatter format errors causing installation failures

When to Use This

  • Skill review: Check if existing skills meet Anthropic specifications
  • Performance optimization: Resolve slow skill loading or token limit issues
  • Resource refactoring: Split large skills into SKILL.md + bundled resources
  • Complex skill development: Write complete skills with API docs and executable scripts

🎒 Prerequisites

Prerequisites Check

Before starting, ensure:

  • ✅ Read Create Custom Skills
  • ✅ Installed at least one skill (understand the basic workflow)
  • ✅ Familiar with YAML and Markdown basic syntax

Core Concepts

SKILL.md Design Philosophy

SKILL.md is the core of the Anthropic skill system, designed with progressive loading:

Three-layer loading advantages:

  1. Metadata layer: All skills' name and description are always in context, enabling AI to quickly understand available skills
  2. SKILL.md layer: Loaded only when relevant, containing core instructions (< 5000 words)
  3. Resources layer: Detailed documentation and executable files loaded on-demand, avoiding token waste

Bundled Resources Classification

DirectoryLoaded to ContextUse CasesExample Types
references/✅ On-demandDetailed docs, API specsAPI docs, database schemas
scripts/❌ Not loadedExecutable codePython/Bash scripts
assets/❌ Not loadedTemplates, output files, imagesJSON templates, boilerplate code

Follow Along

Step 1: Understand Complete YAML Frontmatter Specification

Why: YAML frontmatter is skill metadata and must meet strict specifications

SKILL.md must start and end with ---:

yaml
---
name: my-skill
description: Use this skill when you need to demonstrate proper format.
---

Required fields:

FieldTypeFormat RequirementsExample
namestringkebab-case, no spacespdf-editor, api-client
descriptionstring1-2 sentences, third personUse this skill to edit PDF files

Common Errors

Error ExampleProblemFix Method
name: My SkillContains spacesChange to name: my-skill
name: my_skillUnderscore formatChange to name: my-skill
description: You should use this when...Second personChange to description: Use this skill when...
description: Too longOver 100 wordsSimplify to 1-2 sentence overview
Missing ending ---YAML not properly closedAdd ending delimiter

Source verification: OpenSkills uses non-greedy regex to validate format

typescript
// src/utils/yaml.ts
export function hasValidFrontmatter(content: string): boolean {
  return content.trim().startsWith('---');
}

export function extractYamlField(content: string, field: string): string {
  const match = content.match(new RegExp(`^${field}:\\s*(.+?)$`, 'm'));
  return match ? match[1].trim() : '';
}

Step 2: Write SKILL.md Body (Imperative Form)

Why: AI agents expect imperative instructions, not conversational descriptions

Correct approach:

markdown
## Instructions

To execute this task:

1. Read the input file
2. Process data using the algorithm
3. Generate output in specified format

Incorrect approach (avoid):

markdown
## Instructions

You should execute this task by:

1. Reading the input file
2. Processing data using the algorithm
3. Generating output in specified format

Comparison table:

✅ Correct (Imperative/Infinitive)❌ Incorrect (Second Person)
"Load this skill when X""If you need Y"
"To accomplish Z, execute A""You should do Z"
"See references/guide.md""When you want to Z"

Writing guidelines:

  1. Start with verbs: CreateUseReturn
  2. Omit "You": Don't say "You should"
  3. Clear paths: Use references/, scripts/, assets/ prefixes when referencing resources

Step 3: Use references/ for Detailed Documentation

Why: Keep SKILL.md concise, load detailed documentation on-demand

Applicable scenarios:

  • API documentation (endpoint descriptions over 500 words)
  • Database schemas (table structures, field definitions)
  • Detailed guides (configuration options, FAQ)
  • Code examples (large code snippets)

Directory structure:

my-skill/
├── SKILL.md              (~2,000 words, core instructions)
└── references/
    ├── api-docs.md       (Detailed API documentation)
    ├── database-schema.md (Database structure)
    └── troubleshooting.md (Troubleshooting guide)

Reference method in SKILL.md:

markdown
## Instructions

To interact with the API:

1. Read the request parameters
2. Call the API endpoint
3. For detailed response format, see `references/api-docs.md`
4. Parse the response
5. Handle errors (see `references/troubleshooting.md`)

references/api-docs.md example:

markdown
# API Documentation

## Overview

This API provides endpoints for data processing.

## Endpoints

### POST /api/process

**Request:**
```json
{
  "input": "data to process",
  "options": {
    "format": "json"
  }
}

Response:

json
{
  "status": "success",
  "result": {
    "output": "processed data"
  }
}

Error Codes:

  • 400: Invalid input format
  • 500: Server error

::: tip Best Practice

**references/ file size recommendations**:
- Single file: Recommend < 10,000 words
- Total size: Recommend < 50,000 words (split across multiple files)
- Naming: Use kebab-case (`api-docs.md` not `API_Docs.md`)

:::

---

### Step 4: Use scripts/ for Deterministic Tasks

**Why**: Executable scripts don't need to be loaded into context, suitable for repetitive tasks

**Applicable scenarios**:

- Data transformation (JSON → CSV, format conversion)
- File processing (compression, decompression, renaming)
- Code generation (generate code from templates)
- Test execution (unit tests, integration tests)

**Directory structure**:

my-skill/ ├── SKILL.md └── scripts/ ├── process.py (Python script) ├── transform.sh (Bash script) └── validate.js (Node.js script)


**Reference method in SKILL.md**:

```markdown
## Instructions

To process the input data:

1. Validate the input file format
2. Execute the processing script:
   ```bash
   python scripts/process.py --input data.json --output result.json
  1. Verify the output file
  2. If validation fails, see scripts/validate.py for error messages

**scripts/process.py example**:

```python
#!/usr/bin/env python3
import json
import sys

def main():
    input_file = sys.argv[1]
    output_file = sys.argv[2]

    with open(input_file, 'r') as f:
        data = json.load(f)

    # Processing logic
    result = transform_data(data)

    with open(output_file, 'w') as f:
        json.dump(result, f, indent=2)

    print(f"✅ Processed {input_file} → {output_file}")

if __name__ == "__main__":
    main()

Advantages of scripts/

Compared to inlining code in SKILL.md:

FeatureInline Codescripts/
Token usage✅ High❌ Low
Reusability❌ Poor✅ Good
Testability❌ Difficult✅ Easy
Complexity❌ Token limit✅ No limit

Step 5: Use assets/ for Templates and Output Files

Why: Templates and output files don't need to be loaded into context, saving tokens

Applicable scenarios:

  • Output templates (JSON, XML, Markdown templates)
  • Boilerplate code ( project scaffolding, config files)
  • Images and diagrams (flowcharts, architecture diagrams)
  • Test data (sample inputs, expected outputs)

Directory structure:

my-skill/
├── SKILL.md
└── assets/
    ├── template.json    (JSON template)
    ├── boilerplate.js   (Boilerplate code)
    └── diagram.png     (Flowchart)

Reference method in SKILL.md:

markdown
## Instructions

To generate the output file:

1. Load the template: `assets/template.json`
2. Replace placeholders with actual data
3. Write to output file
4. For boilerplate code, see `assets/boilerplate.js`

assets/template.json example:

json
{
  "title": "{{ title }}",
  "description": "{{ description }}",
  "version": "{{ version }}",
  "author": "{{ author }}",
  "created_at": "{{ timestamp }}"
}

Using templates in scripts:

python
import json
from string import Template

def generate_output(data, template_path):
    with open(template_path, 'r') as f:
        template_str = f.read()

    template = Template(template_str)
    output = template.safe_substitute(data)

    return output

assets/ Considerations

  • Not loaded to context: AI agents cannot directly read content, must load via scripts
  • Path resolution: Use relative paths, like assets/template.json
  • File size: Recommend single file < 10MB (avoid transfer delays)

Step 6: Optimize File Size and Performance

Why: File size directly affects AI context token consumption and loading speed

File size guidelines (official recommendations):

DirectorySize LimitLoading Behavior
SKILL.md< 5,000 wordsAlways loaded (when needed)
references/No strict limitLoaded on-demand
scripts/Not countedNot loaded, only executed
assets/Not loadedNot loaded, only copied

Performance optimization tips:

  1. Split references/:

    bash
    # ❌ Single large file (20,000 words)
    references/all-docs.md
    
    # ✅ Split into multiple small files (each < 5,000 words)
    references/
    ├── api-docs.md
    ├── database-schema.md
    └── troubleshooting.md
  2. Use scripts/ for data processing:

    markdown
    # ❌ Inline large code blocks in SKILL.md (consumes tokens)
    ## Instructions
    Execute this code:
    ```python
    # 500 lines of code...

    ✅ Reference scripts/ (no token consumption)

    Instructions

    Execute: python scripts/processor.py

  3. Streamline SKILL.md:

    • Keep only core instructions and steps
    • Move detailed explanations to references/
    • Use concise imperative language

Verify file size:

bash
# Count SKILL.md words
wc -w my-skill/SKILL.md

# Count references/ total words
find my-skill/references -name "*.md" -exec wc -w {} + | tail -1

# Check scripts/ file size
du -sh my-skill/scripts/

Step 7: Understand Resource Resolution Mechanism

Why: Understand path resolution rules to avoid reference errors

Base directory concept:

When AI agents load a skill, openskills read outputs the base directory:

Reading: my-skill
Base directory: /path/to/project/.claude/skills/my-skill

Relative path resolution rules:

Reference PathResolved Result
references/api.md/base/directory/references/api.md
scripts/process.py/base/directory/scripts/process.py
assets/template.json/base/directory/assets/template.json

Source verification:

typescript
// src/commands/read.ts
export function readSkill(skillNames: string[] | string): void {
  const skill = findSkill(name);
  const content = readFileSync(skill.path, 'utf-8');

  // Output base directory for AI to resolve relative paths
  console.log(`Base directory: ${skill.baseDir}`);
  console.log(content);
}

Path Error Examples

❌ Incorrect MethodProblem✅ Correct Method
/absolute/path/to/api.mdUses absolute pathreferences/api.md
../other-skill/references/api.mdCross-skill referencereferences/api.md
~/references/api.mdUses tilde expansionreferences/api.md

Step 8: Validate Skill Format

Why: Validate format before installation to avoid runtime errors

Use openskills to validate:

bash
npx openskills install ./my-skill

You should see:

✔ Found skill: my-skill
  Description: Use this skill when you need to demonstrate proper format.
  Size: 2.1 KB

? Select skills to install: (Use arrow keys)
❯ ☑ my-skill

Validation checklist:

  • [ ] SKILL.md starts with ---
  • [ ] Contains name field (kebab-case)
  • [ ] Contains description field (1-2 sentences)
  • [ ] YAML ends with ---
  • [ ] Body uses imperative/infinitive form
  • [ ] All references/, scripts/, assets/ references use relative paths
  • [ ] SKILL.md word count < 5,000 words
  • [ ] references/ file naming uses kebab-case

Manual YAML frontmatter validation:

bash
# Check if starts with ---
head -1 my-skill/SKILL.md

# Verify YAML fields (using yq or other tools)
yq eval '.name' my-skill/SKILL.md

Step 9: Test Skill Loading

Why: Ensure skills can be correctly loaded into AI context

Use openskills read to test:

bash
npx openskills read my-skill

You should see:

Reading: my-skill
Base directory: /path/to/project/.claude/skills/my-skill

---
name: my-skill
description: Use this skill when you need to demonstrate proper format.
---

# My Skill

## Instructions

To execute this task...

## Bundled Resources

For detailed information: see `references/skill-format.md`

Skill read: my-skill

Checkpoints:

  • ✅ Output includes Base directory (for path resolution)
  • ✅ SKILL.md content is complete (including YAML and body)
  • ✅ No "Invalid SKILL.md" error
  • ✅ All reference paths display correctly

Checkpoint ✅

After completing the above steps, you should:

  • ✅ Understand the complete SKILL.md field specifications
  • ✅ Master the use cases for references/, scripts/, assets/
  • ✅ Be able to optimize skill file size and loading performance
  • ✅ Know how to validate skill format and test loading
  • ✅ Understand resource resolution mechanism and base directory

Common Pitfalls

Issue 1: SKILL.md Exceeds 5000 Words Causing Token Limit

Cause: SKILL.md contains too much detailed documentation

Solution:

  1. Move detailed content to references/ directory
  2. Reference in SKILL.md: See references/guide.md for details
  3. Use wc -w SKILL.md to check word count

Issue 2: scripts/ Scripts Cannot Execute

Cause:

  • Scripts lack execute permissions
  • Using absolute paths instead of relative paths

Solution:

bash
# Add execute permissions
chmod +x my-skill/scripts/*.sh

# Use relative paths in SKILL.md
## Instructions
Execute: `python scripts/process.py`  # ✅ Correct
Execute: `/path/to/my-skill/scripts/process.py`  # ❌ Incorrect

Issue 3: references/ Files Loaded On-Demand But AI Cannot Read

Cause: AI agents did not correctly parse references/ paths

Solution:

  1. Confirm openskills read outputs Base directory
  2. Clearly state when referencing: See references/api-docs.md in base directory
  3. Avoid using absolute paths or cross-skill references

Issue 4: assets/ Files Too Large Causing Transfer Delays

Cause: assets/ stores large binary files (> 10MB)

Solution:

  • Compress images: Use PNG instead of BMP, optimize JPEG quality
  • Split data: Split large datasets into multiple small files
  • Use external storage: For extra-large files, provide download links instead of including directly

Issue 5: YAML Frontmatter Format Errors

Cause:

  • Missing ending ---
  • Field values contain special characters (colons, hashes) without quotes

Solution:

yaml
# ❌ Incorrect: Missing ending ---
---
name: my-skill
description: Use this skill: for testing
# Missing ---

# ✅ Correct: Complete closure
---
name: my-skill
description: "Use this skill: for testing"
---

Issue 6: Instructions Use Second Person

Cause: Habitual use of "You should", "When you want"

Solution:

  • Use imperative language starting with verbs
  • Use "To do X, execute Y" instead of "You should do Y"
  • Use "Load this skill when Z" instead of "If you need Z"

Comparison table:

Second Person (❌ Avoid)Imperative (✅ Recommend)
"You should execute...""To execute X, run..."
"When you want to...""Load this skill when..."
"If you need...""Use X to accomplish Y"

Summary

Key points of skill structure:

  1. YAML frontmatter: Required fields name (kebab-case) and description (1-2 sentences)
  2. Body format: Use imperative/infinitive form, avoid second person
  3. references/: Store detailed documentation, loaded on-demand to context (< 10,000 words/file)
  4. scripts/: Store executable scripts, not loaded to context, suitable for deterministic tasks
  5. assets/: Store templates and output files, not loaded to context
  6. File size: SKILL.md < 5,000 words, references/ can be split, scripts/ no limit
  7. Path resolution: Use relative paths (references/, scripts/, assets/), resolved based on base directory
  8. Validation methods: Use openskills install to validate format, openskills read to test loading

Next Lesson Preview

In the next lesson, we'll learn CI/CD Integration.

You'll learn:

  • How to use the -y/--yes flag in CI/CD environments
  • Automate skill installation and sync workflows
  • Integrate OpenSkills in GitHub Actions, GitLab CI

Appendix: Source Reference

Click to expand source code locations

Last updated: 2026-01-24

FeatureFile PathLine
YAML frontmatter validationsrc/utils/yaml.ts12-14
YAML field extractionsrc/utils/yaml.ts4-7
Skill read commandsrc/commands/read.ts1-49
Base directory outputsrc/commands/read.ts42
Format validation on installsrc/commands/install.ts242, 291, 340

Example skill files:

Key functions:

  • hasValidFrontmatter(content: string): boolean - Validate if SKILL.md starts with ---
  • extractYamlField(content: string, field: string): string - Extract YAML field value (non-greedy matching)
  • readSkill(skillNames: string[] | string): void - Read skill to standard output (for AI use)