← All posts
·11 min read

Claude Code Skills Guide: How They Load and Work

Claude CodeSkillsConfigurationProductivity
Claude Code Skills Guide: how skills load and work

TL;DR

  • A Claude Code skill is a directory under .claude/skills/ containing a SKILL.md file, whose markdown body Claude reads in full when the skill loads to perform a task-specific procedure.
  • Skills load through semantic description matching, not keyword matching: Claude scores every skill's description against your message and loads the ones above a similarity threshold, so a description that is too broad loads constantly and one too narrow never loads.
  • Effective descriptions cover three things (what the skill does, when to load it, and related phrasings) plus a "NOT for" exclusion, and run roughly 80 to 200 words; the optional triggers field adds exact phrases that load the skill unconditionally.
  • When a skill never loads, work through the checklist: confirm the YAML frontmatter parses, lengthen a thin description, test an explicit trigger phrase, verify the .claude/skills/ discovery path, and restart the session since skills only load at session start.
  • Put permanent rules that apply to every interaction in CLAUDE.md, and reserve skills for procedures that should only run when a specific task is triggered.

How skill loading actually works

Claude Code skills load through description matching. When you send a message, Claude evaluates all available skill descriptions against your message and loads the ones that score above a similarity threshold. The matching is semantic, not keyword-based. A skill whose description says "deploy application" can load when you type "push this to production" even if neither word appears in the other.

This is powerful and fragile in roughly equal measure. It is powerful because you do not need exact phrasing to trigger a skill. It is fragile because a description that is too broad loads the skill constantly (even when it is not appropriate), and a description that is too narrow never loads it.

Understanding the loading mechanics is the prerequisite for writing descriptions that work. The three documents worth reading first are the Claude Code skills explained guide for the conceptual model and the 20-minute skills tutorial for a hands-on build. This guide covers what happens between "skill file exists" and "skill content appears in context."

The skill file anatomy

Every skill is a directory under .claude/skills/ with a SKILL.md file at minimum. The directory name is the skill's identifier. Additional files (templates, examples, reference data) live in the same directory and the SKILL.md can reference them.

.claude/skills/
  deploy/
    SKILL.md               required
    checklist.md           optional reference content
  database-migration/
    SKILL.md               required
    templates/
      rollback.sql         optional template referenced by SKILL.md

The SKILL.md file has two sections: YAML frontmatter and markdown body.

---
name: deploy
description: >
  Deploy the application to production or staging. Use when the user wants
  to push changes live, release a new version, trigger a deployment, or
  ship code to a server. Also use for pre-deploy checks, rollback procedures,
  and post-deploy verification.
tools:
  - Bash
  - Read
---

## Deploy procedure

1. Run pre-deploy checks
2. Commit and push to the deployment branch
3. Verify the deployment completed
4. Run post-deploy health checks

The frontmatter fields:

Field Purpose Required
name Human-readable identifier (shown in /skills output) Yes
description The text Claude compares against your message for loading Yes
tools List of Claude Code tools this skill uses No
triggers Additional explicit trigger phrases No

The body is standard markdown. Claude reads it in full when the skill loads, so depth and specificity are valuable. Vague bodies produce vague outputs.

Writing descriptions that actually load

The description field is the single most important part of a skill. It determines when the skill loads. Most skills that "do not work" have descriptions that are either too broad or too narrow.

The structure of an effective description

Effective descriptions have three components, though not all three need to be explicit sentences:

  1. What the skill does (the task it automates)
  2. When to load it (the conditions or user intents that trigger it)
  3. Related phrasings (synonyms and adjacent tasks the user might type)

A weak description:

description: Deploy the app

This is too short. It matches "deploy the app" literally and may miss adjacent triggers like "push to prod", "ship this", "release a build", or "go live." It also does not distinguish this skill from a general code-pushing workflow.

A strong description:

description: >
  Deploy the application to production or staging. Use when the user wants
  to push code live, release a new version, trigger a CI/CD pipeline, ship
  to Heroku, Railway, Fly.io, Vercel, or any other hosting platform. Also
  use for pre-deploy checklists, rollback procedures, deploy verification,
  and post-deploy health checks. NOT for local development server starts
  (use the run skill for that).

The "NOT for" clause at the end is particularly valuable. It teaches Claude when NOT to load this skill, which prevents it from loading in unrelated situations and reduces noise.

The optimal description length

Descriptions between 80 and 200 words score best in practice. Under 40 words is usually too sparse for reliable semantic matching. Over 300 words introduces ambiguity because the description starts matching too many situations.

The sweet spot is a one-paragraph description that covers the core task, the trigger conditions, the synonyms, and one "NOT for" exclusion.

Using triggers for reliable fallback loading

The optional triggers field accepts a list of exact phrases. When any of these phrases appear in your message, the skill loads unconditionally, bypassing semantic matching:

---
name: deploy
description: >
  Deploy the application to production or staging...
triggers:
  - /deploy
  - deploy to production
  - ship it
  - go live
---

The /deploy trigger makes the skill load whenever you type /deploy regardless of what follows. This is useful for skills you have named explicitly as slash commands in your workflow. Triggers are a fallback, not a replacement for a good description. A skill relying entirely on triggers will never load from natural language.

Directory structure and naming conventions

Skills are discovered from .claude/skills/ recursively. Nesting is supported:

.claude/skills/
  database/
    SKILL.md               loads as 'database'
    migrations/
      SKILL.md             loads as 'database/migrations'
  deploy/
    SKILL.md               loads as 'deploy'

Naming conventions that work well:

  • Use lowercase kebab-case for directory names
  • Use the action or domain as the name, not a description (deploy not deployment-procedure)
  • Group related skills in subdirectories (database/migrations, database/seed, database/backup)
  • Keep names short: the directory name becomes the skill identifier in /skills output

Avoid these naming patterns:

  • Spaces in directory names (breaks some shell tools)
  • Very generic names like helpers or utilities (leads to loading ambiguity)
  • Duplicating the directory name in the skill name field (redundant, does not help)

The tools field

The tools field is a list of Claude Code tool names the skill is expected to use. It does not restrict which tools Claude can use when the skill is loaded. It serves as documentation and influences which skills surface in context-aware tool lists.

tools:
  - Bash
  - Read
  - Edit
  - Write

The tool names must match Claude Code's internal tool names exactly. The standard set:

Tool name What it does
Bash Execute shell commands
Read Read file contents
Edit Edit existing files
Write Create or overwrite files
mcp__<server>__<tool> MCP server tools (e.g., mcp__airtable__create_record)

Listing MCP tools in the tools field is particularly useful for skills that depend on specific MCP servers being available. If the server is not connected, the skill still loads but Claude knows the dependency up front.

Debugging skills that never load

Skills silently fail to load more often than they error visibly. The debugging workflow:

Step 1: Verify the file exists and parses.

cat .claude/skills/your-skill-name/SKILL.md

Check that the YAML frontmatter is valid. Missing --- delimiters or incorrect indentation causes the frontmatter to not parse, which means the description field is never read.

Step 2: Check the description length and specificity.

If the description is under 50 words, extend it. Cover the core task, the trigger conditions, and at least two synonymous phrasings. Add a "NOT for" clause to reduce false positives.

Step 3: Add an explicit trigger phrase.

Add a /your-skill trigger to the triggers field and test with that exact phrase. If the skill loads with the explicit trigger but not from natural language, the issue is the description specificity. If it does not load even with the trigger, the file is not being discovered.

Step 4: Check the discovery path.

Skills must be in .claude/skills/ relative to the project root (the directory containing your CLAUDE.md). If you are working in a subdirectory, Claude may be looking for .claude/skills/ at a different root.

# Confirm the skills directory is at the project root
ls -la .claude/skills/

Step 5: Restart the session.

Skills are loaded at session start. Changes to skill files during a session do not take effect until you start a new Claude Code session. This is a common source of confusion: you edit the description, try again in the same session, and the old description is still loaded.

Step 6: Use /skills to see what is loaded.

The /skills slash command lists all discovered and loaded skills in the current session. If your skill is not in the list, it was not discovered (directory structure problem). If it is in the list but not loading, the description needs work.

Skills that are too broad (and how to fix them)

A skill whose description matches too many situations loads when it should not, injecting instructions that confuse unrelated tasks. The symptom is Claude behaving strangely on tasks you did not intend to trigger the skill for.

Overly broad description example:

description: Help with code and database tasks

This matches almost everything. Any message mentioning code or databases loads this skill, even if the skill contains a specific migration procedure.

Fix: narrow the description to the specific task the skill automates.

description: >
  Run database schema migrations using Alembic or Flask-Migrate. Use when
  the user wants to apply schema changes, generate a new migration file,
  roll back a migration, or check migration status. NOT for seeding data,
  querying the database, or creating new models.

The "NOT for" clauses are doing real work here. They actively suppress loading on adjacent tasks that the broad description would have matched.

Including reference content in skills

A skill can reference additional files in its directory. This is useful for skills that need templates, checklists, or reference data that is too long to inline in SKILL.md.

---
name: deploy
description: Deploy the application to production...
---

## Deploy checklist

Follow the checklist at: .claude/skills/deploy/checklist.md

Read that file before proceeding.

The instruction to "Read that file" is explicit. Claude loads the SKILL.md automatically on trigger, but it reads additional files only when instructed to. Include the Read instruction in the skill body for any supporting file the skill needs.

Writing skills for team use

When skills are shared across a team via version control, a few conventions reduce friction:

Pin tool versions in CLAUDE.md, not in the skill. Skills should describe behaviour, not stack versions. Stack versions belong in the project CLAUDE.md where they apply to all interactions.

Document the skill's contract. Add a brief section at the top of the SKILL.md body that describes what the skill produces. This helps teammates understand what to expect and helps you diagnose when the skill output changes after an update.

## What this skill does

Input: a description of the feature to test
Output: a pytest test file at tests/test_{feature_name}.py with unit and integration tests

## Prerequisites
- pytest installed
- src/ package structure exists
- tests/ directory exists with conftest.py

Version your skills. Add a version field to the frontmatter and increment it when the skill behaviour changes significantly. This makes it easier to track which skill version produced a particular output.

---
name: test-generator
version: "1.2"
description: Generate pytest test files for a given feature...
---

The skill vs CLAUDE.md decision

A common question is whether to put an instruction in CLAUDE.md or in a skill. The rule of thumb:

  • CLAUDE.md: permanent rules that apply to every interaction (code style, naming conventions, hard prohibitions, stack versions)
  • Skill: task-specific procedures that apply only when a particular task is triggered

If the instruction should be followed every time Claude generates code, it belongs in CLAUDE.md. If it should only be followed when performing a specific operation (deploy, migrate, test), it belongs in a skill.

A practical example: "NEVER use var in JavaScript" is a CLAUDE.md rule because it applies to every generated code snippet. "Run database migrations before deploying" is a skill instruction because it applies only to the deploy task.

For the CLAUDE.md rules that complement your skills, Claude Code best practices covers the structure and ordering of CLAUDE.md content that produces the most consistent Claude behaviour. For skills that invoke sub-agents or coordinate multiple tools, Claude Code subagents guide covers the patterns for multi-step autonomous tasks.

Building a skill library that actually works

Skills work at the scale of the problems they automate. A skill that covers a five-step procedure saves five steps per invocation. A library of twenty well-written skills turns Claude Code from a capable assistant into a system that handles your entire development workflow autonomously.

The prerequisite for a working skill library is good descriptions. Every skill in this guide uses the three-component description structure (what, when, related phrasings), a "NOT for" exclusion, and explicit trigger phrases for high-priority skills. That structure is the difference between a skill directory that loads reliably and a skill directory that Claude ignores.

Get Claudify. Claudify includes a library of production-tested skills covering deployment, database migrations, testing, code review, and documentation, each with optimised descriptions and explicit trigger phrases configured from day one.

More like this

Ready to upgrade your Claude Code setup?

Get Claudify
Featured on Dofollow.Tools AI Toolz Dir Claudify - Featured on Startup Fame