Skip to main content

Mental Model

Skills follow a three-stage progressive disclosure model that controls when and how instructions enter Claude's context window. Understanding this model is the difference between skills that activate reliably and skills that sit dormant.

What a Skill Actually Is

A skill is a directory containing a SKILL.md file. The file has two parts: YAML frontmatter (metadata Claude uses to decide relevance) and a markdown body (instructions Claude follows when invoked). That's it. No runtime, no compilation, no API.

.claude/skills/deploy/
├── SKILL.md              # Required. Frontmatter + instructions.
├── references/           # Optional. Large reference docs, API specs.
│   └── api-spec.md
├── scripts/              # Optional. Executable code Claude can run.
│   └── validate.sh
└── assets/               # Optional. Templates, config samples.
    └── config.template

The path must be <root>/skills/<name>/SKILL.md. Nesting deeper (e.g., skills/a/b/SKILL.md) does not work.

Skill Scopes

ScopePathUse Case
Project.claude/skills/<name>/SKILL.mdTeam standards, repo-specific workflows
Personal~/.claude/skills/<name>/SKILL.mdYour global workflows across all repos
EnterpriseDeployed via managed-settings.jsonOrg-wide enforcement
Pluginskills/ directory inside a published pluginDistributed skill packages
Legacy.claude/commands/<name>.mdStill works, but prefer .claude/skills/

The Three-Stage Lifecycle

Stage 1: Metadata Loading

At session start, Claude Code reads the name and description fields from every discoverable skill's frontmatter. These are injected into the system prompt as a skill registry. The full SKILL.md content is NOT loaded yet.

What the system prompt registry looks like internally:

Available skills:
- deploying-to-staging: Deployment expert for staging environments. ALWAYS invoke when...
- reviewing-code: Structured code review process. Invoke when reviewing PRs...
- fixing-issues: Fix a GitHub issue by number. ALWAYS invoke when the user says...

Cost: ~100 tokens per skill. Twenty skills = ~2,000 tokens always present in every turn. This is the overhead you pay just for having skills available.

Stage 2: Invocation Decision

Claude decides whether to invoke a skill. Two paths exist:

Manual invocation: User types /skill-name [args]. Always works. Bypasses description matching entirely. This is the guaranteed path.

Auto-invocation: Claude reads the skill descriptions in its system prompt, reasons about relevance to the current task, and calls the Skill tool. This is a language model decision, not algorithmic matching. The description is the only input Claude uses to decide.

Stage 3: Content Injection

Once invoked, the rendered SKILL.md content enters the conversation as a single message. It stays there for the rest of the session. Claude does NOT re-read the skill file on later turns.

Supporting files in the skill directory are NOT auto-loaded. Claude must explicitly read them using Read or Bash tools. A skill that references its own assets:

# API Scaffolding
 
## Step 1: Load the route template
Read the template file:
`cat ${CLAUDE_SKILL_DIR}/assets/route.template.ts`
 
## Step 2: Check the API spec
Read the OpenAPI spec for endpoint definitions:
`cat ${CLAUDE_SKILL_DIR}/references/openapi.yaml`
 
## Step 3: Generate the endpoint
Use the template and spec to create the new route handler.

This is intentional — it keeps the initial injection lean.

Skill Resolution Order

When naming conflicts occur, precedence from highest to lowest:

  1. Enterprise skills (managed-settings.json) — override everything
  2. Personal skills (~/.claude/skills/) — your global preferences
  3. Project skills (.claude/skills/) — team/repo standards
  4. Plugin skills (plugin skills/ directory) — lowest priority

If a skill and a legacy command share the same name, the skill takes precedence.

Known issue (April 2026): When a project has .claude/skills/, skills from ~/.claude/skills/ may not load. This contradicts documented behavior where both should be discovered.

Context Window Implications

Understanding the token budget is non-negotiable for skill design:

ContentWhen LoadedToken Budget
CLAUDE.mdEvery turn~2,000 tokens recommended max
Skill descriptions (name + description)Session start, every turn~100 tokens each
Invoked skill bodyOn invocation, stays until compactionNo hard limit, but 500 lines recommended max
Re-attached skill (after compaction)After auto-compaction5,000 tokens per skill, 25,000 combined max
MCP tool schemasSession start, every turn5,000-10,000 tokens per server

The Compaction Cycle

When the context window fills up, Claude Code triggers auto-compaction. During compaction:

  1. Conversation history is summarized
  2. The most recent invocation of each skill is re-attached
  3. Each re-attached skill gets up to 5,000 tokens (first 5,000 of the original)
  4. Re-attached skills share a combined budget of 25,000 tokens
  5. The budget fills starting from the most recently invoked skill

This means long skills lose their tail content after compaction. Front-load the critical instructions in the first 5,000 tokens of your SKILL.md.

SKILL.md Frontmatter Reference

All fields are optional, but description is strongly recommended.

---
# Identity
name: deploying-to-staging      # Max 64 chars. Lowercase, numbers, hyphens.
                                 # No reserved words ("anthropic", "claude").
                                 # If omitted, uses directory name.
                                 # Gerund form recommended (verb + -ing).
 
# Trigger
description: |                   # Max 1,024 chars. What + when.
  Deployment expert for staging environments.
  ALWAYS invoke this skill when the user asks about deploying,
  releasing, or pushing to staging.
 
# Execution control
context: fork                    # Runs in isolated subagent. No conversation history.
agent: Explore                   # Which agent type executes.
model: claude-sonnet-4-6         # Override model for this skill.
 
# Security
allowed-tools: Read,Grep,Glob   # Only listed tools permitted.
                                 # Supports Bash scoping: Bash(git:*), Bash(npm:*)
disable-model-invocation: true   # Only manual /slash-command. Hidden from auto-invocation.
 
# Metadata (Agent Skills Standard)
license: MIT
compatibility: "node>=18"       # Max 500 chars.
metadata:
  version: "1.2.0"
  author: "dakota"
---

How Skills Differ from Everything Else

MechanismLoadedPurposeNature
CLAUDE.mdEvery turnGlobal project instructionsAdvisory, always in context
SkillsOn-demand (description always; body when invoked)Task-specific workflowsAdvisory, loaded when relevant
HooksAutomatically at lifecycle eventsEnforce constraints deterministicallyDeterministic, runs regardless of Claude's judgment
Legacy commandsOn explicit /command invocationSaved promptsSame as skills but single-file, no auto-invocation
MCP serversTool schemas at startupExternal tool connectivityInfrastructure, provides tools not instructions

The most common mistake: treating skills as "CLAUDE.md sections that load on demand." Skills are interactive workflows with parameterization, forking, tool restrictions, and model overrides. If your skill is just a paragraph of instructions, it probably belongs in CLAUDE.md.

Argument Interpolation

Skills support parameter passing through shell-style variables:

VariableExpands To
$ARGUMENTSEverything typed after the slash command
$0, $1, $2Positional args (shell-style quoting)
${CLAUDE_SKILL_DIR}Absolute path to the skill's directory

A SKILL.md using all three interpolation types:

---
name: migrate-database
description: |
  Database migration runner. ALWAYS invoke when the user asks
  to create or run a migration. Do not run migration commands directly.
---
 
# Database Migration
 
## Target
Run migration: $ARGUMENTS
 
## Steps
1. Identify migration type from first arg: `$0` (create | run | rollback)
2. Target environment from second arg: `$1` (dev | staging | production)
3. Load the environment config template:
   `cat ${CLAUDE_SKILL_DIR}/assets/env-config.template`
4. Execute the migration using the reference script:
   `bash ${CLAUDE_SKILL_DIR}/scripts/migrate.sh $0 $1`
5. Verify the result against the expected schema in:
   `${CLAUDE_SKILL_DIR}/references/schema-spec.md`

Invocation: /migrate-database create staging makes $0 = "create", $1 = "staging", and $ARGUMENTS = "create staging".

If a skill does not reference $ARGUMENTS, Claude Code automatically appends ARGUMENTS: <input> so Claude still sees the input.

Multi-word arguments use shell-style quoting: /my-skill "hello world" second makes $0 = "hello world", $1 = "second".

Watch out: Multi-line input passed to $ARGUMENTS can break across 16+ commands. Keep arguments to single-line values when possible.