Research Study · March 2026

Claude Code
Skills System

A comprehensive study of how Claude Code discovers, loads, injects, and manages skills at runtime — from SKILL.md frontmatter to context window budget enforcement.

60+ Skills Installed
3 Loading Stages
2 Injection Paths
18KB Max Injection Budget

What Are Skills?

Skills are reusable prompt templates that extend Claude's capabilities by injecting domain-specific instructions into conversations on-demand. Unlike CLAUDE.md (always loaded), skills use progressive disclosure.

★

Skills

  • Prompt-based instruction templates
  • User or Claude invoked
  • Lazy-loaded (on-demand)
  • Supports frontmatter controls
  • Can have supporting files
Recommended
⚙

Hooks

  • Event handlers for system events
  • Automatic (event-driven)
  • Run on matching events
  • Can inject additionalContext
  • PreToolUse / PostToolUse / etc.
Automation
→

Commands

  • Legacy prompt templates
  • User-only (/name)
  • Now merged with skills
  • Simpler frontmatter
  • No auto-invocation
Legacy
⚙

Agents

  • Specialized autonomous workers
  • Claude or user invoked
  • Isolated context
  • Custom system prompts
  • Full preload at startup
Isolated

Anatomy of a SKILL.md

skills/my-skill/SKILL.md
---
name: my-skill
description: "When to use this skill (max 250 chars)"
disable-model-invocation: false
user-invocable: true
allowed-tools: Read, Grep, Glob
model: claude-opus-4-6
effort: high
context: fork
metadata:
  priority: 8
  pathPatterns: ["app/api/chat/**"]
  bashPatterns: ["\\bnpm\\s+install"]
  promptSignals:
    phrases: ["ai sdk"]
    minScore: 6
---

# Markdown instructions here...
Full skill content loaded only on invoke.
←
Identity Name + description (always in context)
←
Invocation Control Who can trigger this skill
←
Execution Config Model, tools, effort, context
←
Plugin Triggers File/bash/prompt patterns for auto-injection
←
Skill Body Full instructions (lazy-loaded, 500-5K tokens)

Progressive Disclosure

Skills use a three-stage loading model to minimize context consumption. Only what's needed is loaded when it's needed.

1

Session Start

Names + descriptions of all enabled skills

~100 tokens/skill
SLASH_COMMAND_TOOL_CHAR_BUDGET Controls total budget (default: 1% of context, min 8K chars)
Always
On invoke
2

On Invocation

Full SKILL.md body loaded into conversation

~500-5,000 tokens/skill
PreToolUse: 18KB / 3-5 skills UserPromptSubmit: 8KB / 2 skills
User /name or Claude auto-detects
On access
3

On-Demand Files

Supporting files: reference.md, examples.md, scripts/

Variable (per file read)
Only loaded when Claude reads them via filesystem
Claude reads supporting files

Context Savings vs. CLAUDE.md

CLAUDE.md (50 skills)
~50K tokens (always)
Skills (50 loaded)
~5K tokens (startup)
Skills (3 invoked)
~11K tokens (active)

Injection Pipeline

Two independent paths inject skills at runtime. Each has its own budget, matching logic, and caps.

Path 1: PreToolUse

Trigger: Read / Edit / Write / Bash Budget: 18 KB Max: 3-5 skills
1
Parse Input Extract file path or bash command
2
Load Manifest Read compiled skill-manifest.json
3
Pattern Match Path globs, bash regex, import patterns
4
Rank + Boost Priority + profiler/TSX/dev-server boosts
5
Dedup Check Skip already-injected skills
6
Budget Enforce Inject top matches within 18KB cap

Path 2: UserPromptSubmit

Trigger: User types a message Budget: 8 KB Max: 2 skills
1
Score Prompt Match against promptSignals config
2
Phrase Match +6 per phrase, +4 allOf, +1 anyOf
3
Lexical Fallback Stemmer-based token matching
4
Rank Results Sort by relevance score
5
Dedup Check Skip already-injected skills
6
Budget Enforce Inject top 2 within 8KB cap

Priority Boost System

Boost Amount Condition
Base priority 1-9 From SKILL.md frontmatter metadata.priority
Profiler +5 Skills predicted at session start via project scanning
vercel.json routing ±10 Key-specific routing when editing vercel.json
TSX review +40 After 3+ .tsx file edits
Dev server +45 When dev server detected running

Prompt Signal Scoring

phrases
+6
+6
+6
Per exact phrase match (case-insensitive)
allOf
+4
+4
Per group where ALL terms present
anyOf
+1
+1
cap +2
Per optional term, capped at +2 total
noneOf
×
Hard suppress — skill excluded entirely
minScore threshold
6
Default: 6 points required to inject

Session Lifecycle

Skills are tied to the session lifecycle. Once loaded, they persist until the session ends or conversation is compacted.

▶ Session Start
Read settings.json → enabledPlugins
Load all skill names + descriptions
Profile project → set LIKELY_SKILLS
Initialize dedup tracking
Inject base context (vercel.md, etc.)
● Session Active
User Prompt UserPromptSubmit hook fires Max 2 skills, 8KB
Tool Use PreToolUse hook fires Max 3-5 skills, 18KB
File Write PostToolUse validates Regex checks on output
⚠
No mid-session unloading. Injected skills persist in context. Settings changes take no effect until restart.
↺ Mid-Session Events
/compact Summarizes conversation. Dedup resets. Skills can re-inject.
/clear Clears history. Dedup resets. Descriptions remain loaded.
resume Full reload same as fresh session. History restored.
◼ Session End
Cleanup temp dedup files
Next session reads fresh settings.json

Context Budget System

Multiple budget mechanisms work together to prevent skills from overwhelming the context window.

Layer 1: Description Budget

SLASH_COMMAND_TOOL_CHAR_BUDGET
~42 skills
8,000 chars
Default 1% of context window (min 8,000 chars)
Per skill 250 chars max per description (hard cap)
Override export SLASH_COMMAND_TOOL_CHAR_BUDGET=20000

Layer 2: PreToolUse Injection

VERCEL_PLUGIN_INJECTION_BUDGET
3-5 skills/invocation
18,000 bytes
Trigger Read / Edit / Write / Bash tool use
Selection Highest priority first until budget exhausted

Layer 3: Prompt Injection

VERCEL_PLUGIN_PROMPT_INJECTION_BUDGET
2 skills/prompt
8,000 bytes
Trigger Every user message submission
Selection Prompt signal scoring + lexical fallback

Deduplication

Skill matched
→
Check seen? VERCEL_PLUGIN_SEEN_SKILLS
↓
Skip Already injected
↓
Inject Add to seen list
Reset triggers: /clear /compact session end

Local Installation Audit

Inventory of all skill-bearing plugins installed on this machine.

V

Vercel Plugin

claude-plugins-official · v0.22.1
47 skills
Core
vercel-deploy vercel-cli vercel-api vercel-agent deployments-cicd vercel-flags
Next.js
nextjs next-upgrade next-cache-components routing-middleware
AI
ai-sdk ai-gateway chat-sdk ai-elements v0-dev
Infra
vercel-functions vercel-storage vercel-queues workflow turborepo turbopack
DX
bootstrap marketplace env-vars observability shadcn verification agent-browser
P

Plugin-Dev

claude-plugins-official
7 skills
skill-development plugin-structure command-development hook-development agent-development mcp-integration plugin-settings
F

Frontend Design

claude-code-plugins
1 skill
frontend-design
H

Hookify

claude-code-plugins (marketplace)
1 skill
writing-rules
D

Feature-Dev

claude-plugins-official
Multiple
code-explorer code-architect code-reviewer
R

Code-Review

claude-plugins-official
Multiple
code-review

Key Findings

✓

Lazy Loading Works

Only ~100 tokens/skill at startup. Full content on-demand saves massive context vs. CLAUDE.md approach.

✗

No Mid-Session Unloading

Once injected, skills persist. /compact is the closest workaround (resets dedup, compresses context).

✗

No Hot-Reload

Plugin enable/disable requires session restart. settings.json is read once at startup.

!

Cloud Skill Injection

69 unwanted skills injected from claude.ai with no opt-out mechanism (GitHub #39686).

✓

Smart Dedup

Per-session tracking prevents skill spam. Resets on /clear and /compact.

✓

Configurable Budgets

Three env vars control description budget, PreToolUse injection, and prompt injection independently.