Skip to main content

Custom Skills

13 min read

What You Will Learn

This chapter walks you through the SKILL.md system: how to create reusable, shareable instruction sets that extend what Claude Code can do. We’ll cover the anatomy of a SKILL.md file, all twelve frontmatter configuration fields, the three invocation modes (slash command, auto-invocation, and both), the four storage locations where skills can live, how skills are distributed through the Plugins system, string substitutions for dynamic content, dynamic injection syntax for shell command preprocessing, how skill content survives context compaction, and the bundled skills that ship with Claude Code.

By the end, you’ll be able to create custom skills tailored to your workflow and share them across your team.

What Are Skills?

Skills are reusable instruction sets packaged as SKILL.md files that encode team conventions, specialized workflows, and automated capabilities into shareable artifacts.

Skills are reusable instruction sets that extend what Claude Code can do. Each skill lives in a SKILL.md file containing YAML frontmatter for configuration and a markdown body with instructions Claude reads and follows when the skill runs. They follow the Agent Skills open standard.

There are three ways to invoke a skill: as a slash command you type in chat, automatically when Claude decides it’s relevant to your request, or both. Skills can also restrict which tools Claude uses, override the model, run in isolated subagents, conditionally activate based on which files you’re working with, and even embed their own hook configurations.

If you’ve used the older .claude/commands/ directory, skills are the replacement. Command files still work for backward compatibility, but skills are the recommended approach because they support richer configuration through frontmatter, automatic discovery in nested directories, and supporting files alongside the skill definition.

SKILL.MD Anatomy

Every skill is a single SKILL.md file with two parts: YAML frontmatter between --- delimiters, and a markdown body below.

SKILL.md
---
name: fix-issue
description: Fetch a GitHub issue and implement the fix
argument-hint: "[issue-number]"
allowed-tools: Read, Grep, Glob, Bash, Write, Edit
model: sonnet
---
You are a senior developer fixing a GitHub issue.
1. Fetch the issue details using: gh issue view $ARGUMENTS
2. Read the relevant source files identified in the issue
3. Implement the fix with minimal changes
4. Write or update tests to cover the fix
5. Run the test suite to verify nothing is broken
6. Summarize what you changed and why

A complete skill with frontmatter configuration and markdown instructions.

The frontmatter (everything between the --- markers) configures how the skill behaves: its name, description, which tools it can use, and how it gets invoked. All frontmatter fields are optional; a SKILL.md with just a markdown body is perfectly valid.

The markdown body (everything after the closing ---) contains the instructions Claude reads and follows when the skill runs. Write it as clear, step by step directions. Claude treats the body as a system level prompt scoped to that skill’s execution.

Frontmatter Reference

SKILL.md supports twelve optional frontmatter fields. None are required, and sensible defaults kick in when you omit them.

name: A human readable name for the skill. If you leave it out, the filename or directory name is used instead. This name shows up in /help output and the slash command menu.

Setting a skill name
---
name: deploy-staging
---

description: A brief explanation of what the skill does. It’s shown in /help and the slash command completion menu. Write something clear so both users and Claude know when to reach for this skill.

argument-hint: Placeholder text that appears after the slash command name in the completion menu. It tells the user what arguments the skill expects, for example [issue-number] or [file-path] [output-format].

disable-model-invocation: Set this to true if you want only the user to invoke the skill via its slash command. Claude won’t be able to auto-invoke it. This is handy for skills that should only run when explicitly requested, like deployment scripts or destructive operations. Defaults to false.

user-invocable: Set to false to hide the skill from the slash command menu. Only Claude can invoke it based on context. This is useful for internal utility skills that Claude should use automatically but users shouldn’t call directly. Defaults to true.

allowed-tools: A comma separated list of tools the skill is allowed to use. This restricts the skill’s capabilities to just the tools you specify. For instance, Read, Grep, Glob creates a read only skill that can’t write files or run commands.

model: Overrides the model used when this skill runs. Accepts shortnames like sonnet, haiku, or opus. Handy for running cheaper models on simple tasks or making sure the most capable model handles complex operations.

context: Set to fork to run the skill in an isolated subagent. The subagent gets its own context window, so the skill doesn’t eat into the parent session’s context. See the Running Skills in Subagents section below.

agent: Specifies which subagent to use when context is set to fork. For example, Explore runs the skill with the built in read only Explore subagent. Only meaningful when context: fork is also set.

hooks: Skill scoped hook configuration, using the same format as settings.json hooks. Hooks defined here only apply while this skill is running. See Hooks & Lifecycle Automation for the full hook configuration format.

paths: An array of glob patterns that control when this skill is conditionally activated. When paths is set, the skill is only auto-loaded when Claude reads or modifies files matching at least one of the patterns. This keeps the skill out of context for unrelated work, reducing noise and saving tokens.

.claude/skills/api-conventions/SKILL.md
---
name: api-conventions
description: Enforce REST API naming and error handling conventions
paths:
- "src/api/**/*.ts"
- "src/middleware/**"
- "src/routes/**/*.ts"
---
You are an API standards enforcer. When the developer is working
on API routes or middleware, ensure that:
1. Route names use kebab-case
2. All endpoints return standard error envelope format
3. Authentication middleware is applied to protected routes
4. Response status codes follow REST conventions

This skill only activates when Claude is working with files under src/api/, src/middleware/, or src/routes/.

Without paths, this skill would load into every session regardless of what you’re working on. With paths, it stays dormant until you start editing API files, then activates automatically. Glob patterns follow standard matching rules: ** matches any number of directories, * matches any filename characters.

shell: Overrides the shell used for inline !command“ execution within the skill body. By default, skills execute dynamic injection commands using the system’s default shell. Set shell to use a different shell, such as powershell on Windows.

.claude/skills/windows-deploy/SKILL.md
---
name: windows-deploy
description: Deploy using PowerShell scripts
shell: powershell
---
Deploy the application using the project's PowerShell scripts.
Current deployment status: !`Get-Content .\deploy-status.txt`
Active environment: !`$env:DEPLOY_ENV`

The shell field routes dynamic injection commands through PowerShell instead of the default shell.

Here’s a skill that brings several frontmatter fields together.

.claude/skills/security-review/SKILL.md
---
name: security-review
description: Audit source code for common security vulnerabilities
argument-hint: "[directory-or-file]"
disable-model-invocation: true
allowed-tools: Read, Grep, Glob
model: opus
context: fork
agent: Explore
paths:
- "src/**/*.ts"
- "src/**/*.js"
---
You are a senior security engineer performing a code audit.
Analyze the code at $ARGUMENTS for:
- SQL injection vulnerabilities
- Cross-site scripting (XSS) vectors
- Authentication and authorization flaws
- Hardcoded secrets or credentials
- Insecure deserialization
- Path traversal vulnerabilities
For each finding, report:
1. The file and line number
2. The vulnerability type and severity
3. A recommended fix with code example

A security review skill: user only invocation, read only tools, runs in an isolated Explore subagent, activates only for TypeScript and JavaScript source files.

Where Skills Live

Skills can live in four locations, each with a different scope and audience.

Enterprise managed skills get deployed through managed settings by organization administrators. Individual developers can’t modify or remove them. This is the place for organization-wide standards like coding conventions, compliance checks, or approved deployment procedures.

Personal skills live in ~/.claude/skills/ and are available in every project you work on. Put skills here that match your personal workflow: your preferred code review checklist, your debugging methodology, or your documentation template.

Project skills live in .claude/skills/ at the root of your repository. They’re committed to Git and shared with your entire team. This is the recommended spot for team specific skills, since everyone who clones the repo gets the same skill set.

Plugin skills come from plugin marketplaces. They extend Claude Code through community contributed or organization published skill packages.

Project skill directory structure
my-project/
.claude/
skills/
deploy/
SKILL.md # Team deployment skill
templates/
k8s-manifest.yaml
code-review/
SKILL.md # Team code review skill
packages/
auth/
.claude/
skills/
auth-debug/
SKILL.md # Package-specific skill (auto-discovered)
src/
...

Skills in nested .claude/skills/ directories are discovered automatically (monorepo support).

Claude Code discovers skills automatically by scanning for SKILL.md files in .claude/skills/ directories at any depth in your project. If you’re working in a monorepo with multiple packages, each package can define its own skills and they’ll all be available when Claude Code runs from the project root.

Skills and Plugins

The Plugins system is the distribution mechanism for skills. When you install a plugin, any skills it contains become available in your session alongside your personal and project skills. Plugin skills are namespaced to avoid collisions: a skill named lint from a plugin called code-quality is invoked as /code-quality:lint rather than just /lint.

This namespacing means you can install multiple plugins that each define skills with the same name without conflicts. Your own project and personal skills always take precedence when invoked without a namespace prefix.

The Plugins chapter covers plugin installation, marketplace discovery, and the full plugin manifest format including how to package your own skills for distribution.

Invocation Modes

Skills support three invocation modes that control who can trigger them.

Slash command invocation is the default for user facing skills. You type /skill-name followed by optional arguments in the chat prompt. To make a skill user only and prevent Claude from auto-invoking it, set disable-model-invocation: true in the frontmatter.

User-only slash command
---
name: deploy
description: Deploy the current branch to staging
disable-model-invocation: true
---
Deploy steps here...

Setting disable-model-invocation: true prevents Claude from auto-invoking this skill.

Auto-invocation lets Claude decide to use the skill based on context. When Claude determines a skill is relevant to the current task, it invokes it automatically without any slash command needed. To make a skill Claude only and hide it from the slash command menu, set user-invocable: false.

Claude-only auto-invocation
---
name: test-helper
description: Automatically run relevant tests after code changes
user-invocable: false
---
Test running steps here...

Setting user-invocable: false removes this skill from the slash command menu.

Both (the default) lets either you or Claude invoke the skill. When neither disable-model-invocation nor user-invocable: false is set, the skill appears in the slash command menu and Claude can also invoke it automatically when it’s relevant.

Default: both user and Claude can invoke
---
name: refactor
description: Refactor code for clarity and maintainability
---
Refactoring steps here...

No invocation flags means both slash command and auto-invocation are enabled.

String Substitutions

The markdown body of a skill supports five string substitutions that inject dynamic values at invocation time.

$ARGUMENTS gets replaced with the full argument string you pass after the slash command. If you type /fix-issue 42 --priority high, then $ARGUMENTS becomes 42 --priority high.

$ARGUMENTS[N] or $N gets replaced with the Nth argument (0-indexed). For /fix-issue 42 --priority high, $0 is 42, $1 is --priority, and $2 is high.

${CLAUDE_SESSION_ID} gets replaced with the current session identifier. It’s useful for creating session specific log files or temporary directories.

${CLAUDE_SKILL_DIR} gets replaced with the absolute path to the directory containing the SKILL.md file. Use it to reference supporting files that live alongside the skill, like templates, configuration files, or examples.

.claude/skills/scaffold/SKILL.md
---
name: scaffold
description: Create a new component from the team template
argument-hint: "[component-name]"
---
Create a new React component named $ARGUMENTS using the template
at ${CLAUDE_SKILL_DIR}/templates/component.tsx as a starting point.
The component should be placed in src/components/$0/.
Copy the template, rename it, and update all placeholder names.
Also create a test file using ${CLAUDE_SKILL_DIR}/templates/component.test.tsx.

$ARGUMENTS passes the component name; CLAUDE_SKILL_DIR resolves to the skill's directory for template access.

Supporting Files and Dynamic Injection

Skills can include supporting files in the same directory as the SKILL.md. These files (templates, configuration snippets, example outputs, reference docs) give Claude additional context to work with when executing the skill.

Skill with supporting files
.claude/skills/deploy/
SKILL.md # The skill definition
templates/
k8s-deployment.yaml # Kubernetes manifest template
k8s-service.yaml # Service template
examples/
staging-deploy.md # Example of a successful deploy
scripts/
validate-manifest.sh # Validation script

Supporting files live alongside SKILL.md and are referenced via CLAUDE_SKILL_DIR.

For dynamic context that changes between invocations, SKILL.md supports the !`command` syntax. When Claude loads the skill, it runs the shell command and injects the output directly into the skill prompt. This lets your skill adapt to the current state of the repo, environment, or system.

.claude/skills/deploy/SKILL.md
---
name: deploy
description: Deploy current branch to the appropriate environment
argument-hint: "[environment]"
---
Deploy the current project to the $ARGUMENTS environment.
Current branch: !`git branch --show-current`
Last commit: !`git log --oneline -1`
Uncommitted changes: !`git status --short`
Read the deployment configuration at ${CLAUDE_SKILL_DIR}/templates/k8s-deployment.yaml
and customize it for the $0 environment.
If there are uncommitted changes, warn the user before proceeding.

The !`command` syntax injects live shell output into the skill prompt at invocation time.

When this skill runs, the three !command“ blocks get replaced with the actual output of git branch --show-current, git log --oneline -1, and git status --short. So Claude sees the current branch name, latest commit, and working tree status right in its instructions.

Running Skills in Subagents

When a skill sets context: fork in its frontmatter, it runs in an isolated subagent with its own context window. This is valuable for two reasons: the skill doesn’t consume context from your main session, and it can run without interfering with your ongoing conversation.

You can combine context: fork with the agent field to pick which subagent runs the skill. The built in Explore subagent uses the Haiku model and has read only tools, making it ideal for analysis tasks that shouldn’t modify files.

Skill running in a forked Explore subagent
---
name: analyze-deps
description: Analyze project dependencies for vulnerabilities and updates
context: fork
agent: Explore
---
Analyze this project's dependency files (package.json, requirements.txt,
go.mod, or similar) and report:
1. Total number of direct and transitive dependencies
2. Any dependencies with known security advisories
3. Dependencies that are more than 2 major versions behind
4. Unused dependencies (declared but not imported)
Read dependency lock files for accurate version information.
Do not modify any files.

context: fork isolates the skill; agent: Explore restricts it to read only analysis.

The subagent runs to completion and returns its results to the parent session. Your main conversation continues uninterrupted, and the skill’s work doesn’t eat into your available context window. This pattern is especially useful for expensive analysis tasks that need to read many files.

The relationship between skills and subagents works in both directions. Skills with context: fork run inside subagents, and subagents defined with a skills field in their AGENT.md frontmatter can preload specific skill content into their context. This lets you build specialized agents that always have certain skills available without waiting for auto-invocation.

Content Lifecycle and Compaction

When a long session triggers context compaction, Claude Code preserves skill content so your active skills continue influencing behavior. Understanding how this works helps you write skills that remain effective throughout extended sessions.

After compaction, the first 5,000 tokens of each invoked skill’s content are re-attached to the context window. This means the most important instructions in your skill should appear near the top of the markdown body. If your skill is under 5,000 tokens, it survives compaction entirely intact.

Across all invoked skills in a session, Claude Code allocates a combined budget of 25,000 tokens for post-compaction skill content. When multiple skills are active, the most recently invoked skills are prioritized for re-attachment. Skills that haven’t been used recently may be dropped from context to stay within the budget.

.claude/skills/coding-standards/SKILL.md
---
name: coding-standards
description: Enforce team coding standards
---
## Critical Rules (keep in first 5,000 tokens)
These rules MUST be followed in every code change:
1. All functions must have TypeScript return types
2. No any types -- use unknown and narrow
3. Error handling must use Result types, not try/catch
4. All public APIs must have JSDoc comments
## Extended Guidelines
These additional guidelines apply when context allows:
- Prefer composition over inheritance
- Use barrel exports for module boundaries
- Keep files under 300 lines
- ...

Structure skills with critical content in the first 5,000 tokens so it survives context compaction.

Practical implications:

  • Put critical instructions first. The top of your skill body is the most durable part. Move non-negotiable rules, required patterns, and essential context above any nice-to-have guidance.

  • Keep skills concise. A focused 3,000 token skill survives compaction fully intact. A sprawling 20,000 token skill loses 75% of its content after compaction.

  • Watch for skill count. With a 25,000 token combined budget, five 5,000 token skills fit perfectly. If you’re running ten active skills, some will be dropped. Reduce active skill count by using paths to conditionally activate skills only when relevant files are in play.

  • Recently invoked wins. If a skill hasn’t been invoked recently, it may be deprioritized after compaction. For skills that must persist, consider invoking them periodically or structuring them as shorter, higher-priority instructions.

Bundled Skills

Claude Code ships with several built in skills that are available in every session without any setup.

/simplify reduces code complexity. Point it at a function, class, or file and it’ll refactor for clarity by extracting helper functions, simplifying conditionals, reducing nesting depth, and improving naming.

/batch runs an operation across multiple files. Describe a change once and it applies the transformation consistently to every matching file, taking the tedium out of multi-file edits.

/debug gives you systematic debugging. Describe the symptom and it follows a structured approach: reproduce the issue, isolate the cause, propose a fix, verify the fix, and check for regressions.

/loop runs a prompt or slash command on a recurring interval. Describe what you want to happen and how often, and it sets up the automation for you. Great for polling deploy status, running periodic checks, or any task that needs to repeat on a schedule. See Remote Control & Headless Automation for more on scheduled tasks.

/claude-api helps you integrate with the Anthropic API. It assists with writing code that calls Claude’s API, handling authentication, message formatting, streaming responses, and error handling correctly.

Restricting Skill Access

Permission rules let you control which skills are allowed to run. The Skill(name) permission type lets you allow or deny specific skills.

settings.json
{
"permissions": {
"deny": [
"Skill(deploy)"
]
}
}

Denying the deploy skill prevents both user slash command and Claude auto-invocation.

Enterprise administrators can use managed settings to enforce skill restrictions across the organization, ensuring only approved skills run in production sensitive environments.

For environments where inline shell execution in skills poses a security concern, the disableSkillShellExecution managed setting blocks all !command dynamic injection from running in skills, slash commands, and plugin commands. When enabled, the `!`command syntax is treated as literal text rather than being executed. Bundled skills and managed skills are not affected by this setting.

managed-settings.json
{
"disableSkillShellExecution": true
}

Blocks inline shell execution in skills. Only configurable through managed settings -- users cannot override it.

This is a managed-only setting, meaning it can only be configured by enterprise administrators through managed settings. Individual users cannot enable or disable it in their personal or project settings. See Security & Governance for the full managed settings reference and other enterprise security controls.

Best Practices

  • Keep skills focused on one task. A skill that does one thing well is more reusable and easier to debug than one that tries to handle multiple scenarios.

  • Write clear descriptions for discoverability. The description field is what users see in the slash command menu and what Claude uses to decide when to auto-invoke. Make it specific and action oriented.

  • Use allowed-tools to limit scope. A code review skill shouldn’t need write access. A documentation generator shouldn’t need to run shell commands. Restricting tools prevents unintended side effects.

  • Use paths to reduce context noise. Skills without paths load into every session. Set glob patterns so skills only activate when you’re working on relevant files, saving context window space and keeping unrelated skills from interfering.

  • Structure content for compaction survival. Put your most critical instructions in the first 5,000 tokens of the skill body. After context compaction, only this portion is guaranteed to be re-attached.

  • Test skills with simple inputs first. Before rolling out a complex skill to your team, test it with straightforward cases to make sure the instructions produce the expected behavior.

  • Use context:fork for expensive operations. Skills that read many files or perform lengthy analysis should run in subagents so they don’t chew through your main session’s context window.

  • Prefer project skills for team sharing. Store skills in .claude/skills/ and commit them to Git. That way every team member gets the same skill set, and updates propagate through normal version control.

  • Use dynamic injection sparingly. The !command“ syntax is powerful but runs shell commands on every invocation. Keep injected commands fast and side effect free.

Further Reading

  • Custom Skills, the official documentation on SKILL.md anatomy, frontmatter fields, invocation modes, and supporting files
  • Next up: Hooks & Lifecycle Automation covers the hook system that can be embedded in skill frontmatter for lifecycle aware automation