Skills System
Skills are prompt-based extensions that add slash-command capabilities to Claude Code. They can be bundled into the binary, loaded from disk, provided by plugins, or exposed through MCP servers.
Skill Sources
Claude Code loads skills from multiple sources, merged at startup:
Compiled into the CLI binary via registerBundledSkill(). Available to all users unconditionally.
Markdown files in .claude/skills/ relative to the project root. Scoped to a single repository.
Markdown files in ~/.claude/skills/. Available across all projects for a given user.
Skills provided by installed plugins. Loaded from the plugin's commands path.
Skills from managed/policy settings paths. Used for enterprise policy-controlled skills.
Skills built dynamically from MCP server tool discovery via registerMCPSkillBuilders().
The LoadedFrom type captures these origins:
type LoadedFrom =
| 'commands_DEPRECATED'
| 'skills'
| 'plugin'
| 'managed'
| 'bundled'
| 'mcp'BundledSkillDefinition
Bundled skills are registered programmatically at startup. The BundledSkillDefinition type defines their shape:
type BundledSkillDefinition = {
name: string
description: string
aliases?: string[]
whenToUse?: string
argumentHint?: string
allowedTools?: string[]
model?: string
disableModelInvocation?: boolean
userInvocable?: boolean
isEnabled?: () => boolean
hooks?: HooksSettings
context?: 'inline' | 'fork'
agent?: string
files?: Record<string, string>
getPromptForCommand: (
args: string,
context: ToolUseContext,
) => Promise<ContentBlockParam[]>
}"batch" becomes /batch).registerBundledSkill()
The registerBundledSkill() function converts a BundledSkillDefinition into a Command and adds it to an internal registry:
function registerBundledSkill(definition: BundledSkillDefinition): voidWhen a skill has files, the function wraps getPromptForCommand to lazily extract those files to ~/.claude/bundled-skills/<name>/ on first invocation. Extraction is memoized at the promise level so concurrent callers share a single write.
Bundled Skills
The following skills ship with the CLI (registered in src/skills/bundled/):
| Skill | Description |
|---|---|
batch | Run operations across multiple files or inputs |
claude-api | Build apps with the Claude API or Anthropic SDK |
claude-in-chrome | Chrome extension integration |
debug | Debug failing tests or runtime errors |
keybindings | Customize keyboard shortcuts |
loop | Run a prompt or slash command on a recurring interval |
lorem-ipsum | Generate placeholder text |
remember | Save information to memory files |
schedule | Create and manage scheduled remote agents |
simplify | Review changed code for reuse, quality, and efficiency |
skillify | Convert a workflow into a reusable skill |
stuck | Help when Claude is stuck in a loop |
update-config | Configure the Claude Code harness via settings.json |
verify | Verify that a task was completed correctly |
Disk-Based Skills
Skills loaded from .claude/skills/ and ~/.claude/skills/ are Markdown files with YAML frontmatter:
---
description: "Generate unit tests for a module"
whenToUse: "When the user asks for tests"
allowedTools:
- Read
- Write
- Bash
hooks:
PostToolUse:
- matcher: "Write"
hooks:
- type: command
command: "npm test"
---
Write comprehensive unit tests for the specified module.
Use the project's existing test framework and conventions.Frontmatter Fields
"<file-path>").Shell Command Execution in Prompts
Skill prompts can embed shell commands using backtick-fenced blocks with a sh or bash language tag. These commands are executed before the prompt is sent to the model, and their output is substituted inline via executeShellCommandsInPrompt().
Argument Substitution
Skill prompts support $ARGUMENTS placeholders. When a user invokes /my-skill some args, the argument string is parsed via parseArgumentNames() and substituted into the prompt via substituteArguments().
MCP Skill Builders
The registerMCPSkillBuilders() function bridges the MCP server layer with the skills system. It provides two functions to the MCP subsystem:
createSkillCommand: converts MCP tool metadata into aCommandobjectparseSkillFrontmatterFields: parses frontmatter from MCP-provided skill content
This avoids a circular dependency: MCP servers need to create skill commands, but the skill loader transitively imports most of the codebase. The builders are registered at module init time (via static import from commands.ts) before any MCP server connects.
type MCPSkillBuilders = {
createSkillCommand: typeof createSkillCommand
parseSkillFrontmatterFields: typeof parseSkillFrontmatterFields
}Skill Deduplication
When loading from multiple sources, skills are deduplicated by resolving symlinks to canonical file paths via realpath(). This prevents the same skill from appearing twice when accessed through different paths (e.g., symlinks or overlapping parent directories).
Token Estimation
Skill metadata tokens are estimated via estimateSkillFrontmatterTokens(), which counts tokens across the skill's name, description, and whenToUse fields. Full content is only loaded on invocation, keeping the idle system prompt lightweight.