Skip to main content

Custom Skills

10 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 ten frontmatter configuration fields, the three invocation modes (slash command, auto-invocation, and both), the four storage locations where skills can live, string substitutions for dynamic content, dynamic injection syntax for shell command preprocessing, 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, 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
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 ten 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
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.

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

.claude/skills/security-review/SKILL.md
.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
---
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.

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
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.

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
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
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
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
.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
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
.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
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.

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
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.

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.

  • 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