Blog

Claude Code Skills Tutorial: How to Create Custom Slash Commands and Automations

2 Apr 2026

Claude Code Skills Tutorial

Claude Code ships with a powerful extension system called Skills. A skill is a markdown file with instructions that Claude loads into its context — either when you invoke it directly with /skill-name or automatically when it detects the skill is relevant to your task.

If you've been copy-pasting the same prompts across sessions, maintaining long CLAUDE.md files with instructions that only matter sometimes, or wishing Claude would just follow your deploy process without being told every time — skills are the answer.

This guide covers everything from creating your first skill to advanced patterns like forked subagents, dynamic context injection, and team-wide distribution.

What Are Claude Code Skills?

Skills are prompt-based extensions. Each skill lives in a directory with a SKILL.md file that contains two parts: YAML frontmatter that configures how the skill behaves, and markdown content with the instructions Claude follows when the skill is active.

Unlike CLAUDE.md (which loads into every session), skills load on demand. This keeps your context window clean and lets you build a library of specialized capabilities without paying the token cost for all of them in every conversation.

Skills follow the Agent Skills open standard, which means they're portable across AI tools that support the spec. Claude Code extends the standard with features like invocation control, subagent execution, and dynamic context injection.

Skills vs. CLAUDE.md vs. Subagents

Understanding when to use each extension point saves time:

ExtensionWhen to UseContext Impact
CLAUDE.mdRules that apply to nearly every task — build commands, code style, architecture decisionsAlways loaded, always costs tokens
SkillsWorkflows that matter sometimes — deploy steps, review checklists, code generation patternsLoaded on demand when invoked or relevant
SubagentsIsolated tasks that shouldn't pollute your conversation — research, large-scale explorationSeparate context window entirely

The rule of thumb: if a rule applies to every session, put it in CLAUDE.md. If it's a specific workflow that only matters sometimes, make it a skill. If the task involves heavy reading or exploration, consider a subagent. And as you'll see later, skills and subagents can work together.

Creating Your First Skill

Let's build a skill that generates a changelog entry from your recent git commits. This is a practical workflow that many teams repeat manually.

Step 1 — Create the Skill Directory

Every skill needs its own directory with a SKILL.md file inside. Where you put the directory determines who can use the skill:

# Personal skill (available in all your projects)
mkdir -p ~/.claude/skills/changelog

# Project skill (available to everyone on this project)
mkdir -p .claude/skills/changelog

Step 2 — Write SKILL.md

Create SKILL.md inside the directory:

---
name: changelog
description: Generate a changelog entry from recent git commits. Use when the user asks to update the changelog, write release notes, or summarize recent changes.
---

Generate a changelog entry based on recent git activity:

1. Run `git log --oneline -20` to see recent commits
2. Group commits by type (features, fixes, refactoring, docs)
3. Write a concise changelog entry in Keep a Changelog format
4. Add the entry to CHANGELOG.md (create if it doesn't exist)

Use the conventional commit prefix to categorize:
- feat: → Added
- fix: → Fixed
- refactor: → Changed
- docs: → Documentation
- chore: → Maintenance

Skip merge commits and CI-only changes.

Step 3 — Test It

You can invoke the skill two ways:

Directly by typing the slash command:

/changelog

Automatically by asking something that matches the description:

Summarize recent changes for a release

Claude checks skill descriptions against your request and loads matching skills automatically. The description field is what makes auto-discovery work, so write it carefully.

Where Skills Live

The storage location determines scope and priority:

LevelPathApplies To
EnterpriseManaged settings (admin-configured)All users in your organization
Personal~/.claude/skills/<name>/SKILL.mdAll your projects
Project.claude/skills/<name>/SKILL.mdThis project only
Plugin<plugin>/skills/<name>/SKILL.mdWhere the plugin is enabled

When skills share the same name across levels, higher-priority locations win: enterprise > personal > project. Plugin skills use a plugin-name:skill-name namespace so they never conflict.

Monorepo Support

Claude Code automatically discovers skills from nested .claude/skills/ directories. If you're editing a file in packages/frontend/, Claude also checks packages/frontend/.claude/skills/. This means each package in a monorepo can maintain its own skills.

Skill Directory Structure

A skill can be more than just a single file:

my-skill/
├── SKILL.md           # Main instructions (required)
├── template.md        # Template for Claude to fill in
├── examples/
│   └── sample.md      # Example output showing expected format
└── scripts/
    └── validate.sh    # Script Claude can execute

Reference supporting files from your SKILL.md so Claude knows when to load them:

## Additional resources

- For the PR template, see [template.md](template.md)
- For output examples, see [examples/sample.md](examples/sample.md)

Keep SKILL.md under 500 lines. Move detailed reference material, API docs, or large example collections to separate files that Claude reads only when needed.

Frontmatter Reference

The YAML frontmatter block at the top of SKILL.md controls how the skill behaves. All fields are optional, but description is strongly recommended.

---
name: my-skill
description: What this skill does and when to use it
disable-model-invocation: true
allowed-tools: Read, Grep, Glob
context: fork
agent: Explore
model: claude-sonnet-4-6
effort: high
---

Here's what each field does:

FieldDescription
nameDisplay name and slash command. Defaults to the directory name. Lowercase letters, numbers, and hyphens only.
descriptionWhat the skill does. Claude uses this to decide when to load it. Front-load the key use case — descriptions are truncated at 250 characters.
argument-hintHint shown during autocomplete. Example: [issue-number] or [filename] [format].
disable-model-invocationSet to true to prevent Claude from loading this skill automatically. Only you can invoke it with /name.
user-invocableSet to false to hide from the / menu. Use for background knowledge Claude should apply but users shouldn't invoke directly.
allowed-toolsTools Claude can use without asking permission when this skill is active.
modelOverride the model for this skill.
effortOverride the effort level: low, medium, high, or max.
contextSet to fork to run in an isolated subagent context.
agentWhich subagent type to use when context: fork is set. Options: Explore, Plan, general-purpose, or a custom subagent name.
hooksHooks scoped to this skill's lifecycle.
pathsGlob patterns that limit when the skill auto-activates. Only triggers when working with matching files.
shellShell for inline commands: bash (default) or powershell.

Controlling Who Invokes a Skill

By default, both you and Claude can invoke any skill. Two frontmatter fields let you restrict this:

User-Only Skills

Add disable-model-invocation: true for workflows with side effects — deployments, sending messages, publishing releases. You don't want Claude deciding to deploy because your code looks ready:

---
name: deploy
description: Deploy the application to production
disable-model-invocation: true
---

Deploy $ARGUMENTS to production:

1. Run the test suite: `npm test`
2. Build the application: `npm run build`
3. Push to deployment target: `npm run deploy`
4. Verify the deployment succeeded

Claude-Only Skills

Set user-invocable: false for background knowledge that isn't a meaningful action. A skill explaining legacy system architecture should inform Claude's decisions without appearing in the slash command menu:

---
name: legacy-api-context
description: Context about the legacy REST API. Use when modifying API endpoints or debugging API issues.
user-invocable: false
---

The legacy API uses Express with a custom middleware chain...

Invocation Summary

FrontmatterYou Can InvokeClaude Can Invoke
(default)YesYes
disable-model-invocation: trueYesNo
user-invocable: falseNoYes

Passing Arguments to Skills

Arguments are available through the $ARGUMENTS placeholder. When you run /fix-issue 123, the $ARGUMENTS token in your skill content gets replaced with 123.

---
name: fix-issue
description: Fix a GitHub issue
disable-model-invocation: true
---

Fix GitHub issue $ARGUMENTS following our coding standards.

1. Read the issue description
2. Understand the requirements
3. Implement the fix
4. Write tests
5. Create a commit with the message "fix: resolve #$ARGUMENTS"

Positional Arguments

For skills that take multiple inputs, use $ARGUMENTS[N] or the shorthand $N:

---
name: migrate-component
description: Migrate a component from one framework to another
---

Migrate the $0 component from $1 to $2.
Preserve all existing behavior and tests.

Running /migrate-component SearchBar React Vue replaces $0 with SearchBar, $1 with React, and $2 with Vue.

Other Built-in Variables

VariableDescription
$ARGUMENTSAll arguments passed when invoking
$ARGUMENTS[N]Specific argument by 0-based index
$NShorthand for $ARGUMENTS[N]
${CLAUDE_SESSION_ID}Current session ID
${CLAUDE_SKILL_DIR}Directory containing the skill's SKILL.md

Advanced Patterns

Dynamic Context Injection

The !`command` syntax runs shell commands before the skill content reaches Claude. The command output replaces the placeholder, so Claude receives real data rather than a command to execute.

This is powerful for skills that need live system state:

---
name: pr-summary
description: Summarize the current pull request
context: fork
agent: Explore
allowed-tools: Bash(gh *)
---

## Pull request context
- PR diff: !`gh pr diff`
- PR comments: !`gh pr view --comments`
- Changed files: !`gh pr diff --name-only`

## Your task
Summarize this pull request. Highlight breaking changes,
new dependencies, and any files that need careful review.

When this skill runs, each !`command` executes immediately. Claude only sees the final rendered content with actual PR data embedded.

Running Skills in a Subagent

Add context: fork when you want a skill to run in isolation. The skill content becomes the prompt that drives a separate subagent with its own context window. Results are summarized and returned to your main conversation.

This is ideal for research-heavy tasks that would otherwise flood your conversation with intermediate results:

---
name: deep-research
description: Research a topic thoroughly across the codebase
context: fork
agent: Explore
---

Research $ARGUMENTS thoroughly:

1. Find relevant files using Glob and Grep
2. Read and analyze the code
3. Identify patterns, dependencies, and potential issues
4. Summarize findings with specific file references

The agent field determines the execution environment. Built-in options:

  • Explore — Optimized for read-only codebase exploration. Fast model, read-only tools.
  • Plan — For designing implementation strategies. Read-only tools with architectural focus.
  • general-purpose — Full tool access. Default if agent is omitted.

You can also reference custom subagents defined in .claude/agents/.

Restricting Tool Access

Use allowed-tools to limit what Claude can do when a skill is active. This creates guardrails for sensitive workflows:

---
name: audit
description: Audit code for security issues
allowed-tools: Read, Grep, Glob
---

Audit the codebase for security vulnerabilities:
- SQL injection
- XSS vulnerabilities
- Hardcoded secrets
- Insecure dependencies

Report findings only. Do not modify any files.

By listing only read-only tools, you guarantee the audit skill can't accidentally change code.

Practical Skill Examples

Here are real-world skills you can adapt for your own workflow.

Code Review Skill

---
name: review
description: Review code changes against team standards
context: fork
agent: Explore
---

Review the current git diff against these standards:

1. Run `git diff --staged` (or `git diff` if nothing is staged)
2. Check for:
   - Functions longer than 50 lines
   - Missing error handling at system boundaries
   - Inconsistent naming conventions
   - New dependencies that duplicate existing ones
   - Test coverage for new code paths
3. Rate severity: blocker, warning, or nitpick
4. Provide specific file:line references for each finding

Database Migration Skill

---
name: migrate-db
description: Generate a database migration file
disable-model-invocation: true
argument-hint: [description]
---

Generate a database migration for: $ARGUMENTS

1. Check the existing migration files for naming conventions and numbering
2. Create a new migration file following the same pattern
3. Include both `up` and `down` functions
4. Add appropriate indexes for any new columns
5. If modifying existing tables, ensure backward compatibility

Component Generator Skill

---
name: component
description: Generate a React component following project conventions
argument-hint: [ComponentName]
---

Generate a React component named $0:

1. Read existing components in src/components/ to understand patterns
2. Create the component file following the same structure
3. Include TypeScript types
4. Create a test file in the same directory
5. Export from the nearest index file

Release Notes Skill with Dynamic Context

---
name: release-notes
description: Generate release notes from git history
disable-model-invocation: true
argument-hint: [version]
---

## Context
- Latest tag: !`git describe --tags --abbrev=0 2>/dev/null || echo "no tags"`
- Commits since last tag: !`git log $(git describe --tags --abbrev=0 2>/dev/null || echo "HEAD~20")..HEAD --oneline`
- Contributors: !`git log $(git describe --tags --abbrev=0 2>/dev/null || echo "HEAD~20")..HEAD --format='%an' | sort -u`

## Task
Write release notes for version $ARGUMENTS. Group changes by:
- Breaking Changes
- New Features
- Bug Fixes
- Performance Improvements
- Documentation

Use the commit history above. Write for end users, not developers.

Codebase Visualization Skill

Skills can bundle and run scripts. This pattern generates interactive HTML output:

---
name: visualize
description: Generate an interactive visualization of the codebase structure
allowed-tools: Bash(python *)
---

Run the visualization script from the project root:

```bash
python ${CLAUDE_SKILL_DIR}/scripts/visualize.py .

This creates codebase-map.html and opens it in your browser. The visualization shows collapsible directories, file sizes, and color-coded file types.


Bundle a Python script in `scripts/visualize.py` alongside the skill. Claude executes the script, and you get an interactive browser-based view of your codebase.

## Bundled Skills

Claude Code ships with several built-in skills available in every session:

| Skill | What It Does |
|---|---|
| `/batch <instruction>` | Orchestrate large-scale changes across a codebase in parallel. Researches, decomposes work into 5-30 units, and spawns one agent per unit in isolated git worktrees. |
| `/claude-api` | Load Claude API reference material for your project's language. Also activates automatically when your code imports Anthropic SDKs. |
| `/debug [description]` | Enable debug logging and troubleshoot issues by analyzing session logs. |
| `/loop [interval] <prompt>` | Run a prompt repeatedly on an interval. Useful for polling deployments or monitoring PRs. |
| `/simplify [focus]` | Review recently changed files for code quality issues, then fix them. Spawns three review agents in parallel. |

## Sharing Skills with Your Team

### Project Skills (Version Control)

Commit `.claude/skills/` to your repository. Every developer who clones the project gets the same skills:

.claude/ ├── skills/ │ ├── deploy/ │ │ └── SKILL.md │ ├── review/ │ │ └── SKILL.md │ └── test-e2e/ │ └── SKILL.md


This is the simplest distribution method and keeps skills versioned alongside the code they support.

### Plugin Distribution

Package skills as a plugin for cross-project reuse. Plugins have their own `skills/` directory:

my-plugin/ ├── skills/ │ ├── skill-a/ │ │ └── SKILL.md │ └── skill-b/ │ └── SKILL.md


Plugin skills use a `plugin-name:skill-name` namespace, so they never conflict with project or personal skills.

### Enterprise Distribution

For organization-wide skills, deploy through managed settings. Enterprise skills take the highest priority and can enforce standards across all projects and users.

## Permission Control

You can control which skills Claude can invoke through permission rules:

Allow only specific skills

Skill(commit) Skill(review-pr *)

Deny specific skills

Skill(deploy *)


To disable all skills, deny the Skill tool entirely in `/permissions`.

## Troubleshooting

### Skill Not Triggering Automatically

If Claude doesn't pick up your skill when expected:

1. Check that the `description` includes keywords matching how you phrase requests
2. Verify the skill shows up when you ask "What skills are available?"
3. Try invoking it directly with `/skill-name` to confirm it works
4. Front-load the most important use case in the description — it truncates at 250 characters

### Skill Triggers When You Don't Want It

If Claude applies a skill unexpectedly:

1. Narrow the `description` to be more specific
2. Add `paths` to restrict activation to certain files
3. Set `disable-model-invocation: true` to require manual invocation

### Description Budget

All skill descriptions are loaded into context so Claude knows what's available. The total budget is 1% of the context window (fallback: 8,000 characters). If you have many skills, descriptions get shortened. To increase the limit, set the `SLASH_COMMAND_TOOL_CHAR_BUDGET` environment variable.

### Commands Migration

If you have existing files in `.claude/commands/`, they keep working. Skills and commands both create slash commands and use the same frontmatter. The only difference is that skills support additional features like supporting files and directory-based organization. If a skill and command share the same name, the skill takes precedence.

## Key Takeaways

- Skills are on-demand context. CLAUDE.md is always-on context. Use skills for workflows that matter sometimes, not always.
- The `description` field drives auto-discovery. Write it like a search query — include the keywords someone would naturally use.
- Use `disable-model-invocation: true` for anything with side effects. Deploys, messages, releases — keep humans in the loop.
- `context: fork` runs skills in isolation. Use it for research-heavy tasks that would flood your main conversation.
- Dynamic context injection (`` !`command` ``) lets skills pull in live data before Claude sees the prompt.
- Store project skills in `.claude/skills/` and commit them. Your whole team benefits.
- Keep `SKILL.md` under 500 lines. Move detailed reference material to supporting files.

Ship 10x faster with Claude Code

Production-ready CLAUDE.md templates, MCP server configs, custom hooks, and battle-tested workflows. Stop configuring, start building.

  • CLAUDE.md templates for 6+ frameworks with MCP server configs
  • 8+ custom hooks: Pre-commit, lint, test, format & more ready to go
  • Prompt library: 50+ curated prompts and workflow templates