Custom Skills
Creating custom skills to extend agent capabilities.
Overview
Skills are reusable prompt fragments that agents can invoke during their sessions. Each skill is a Markdown file with optional YAML frontmatter that controls how the skill behaves — who can invoke it, what tools it can use, and how arguments are substituted.
Skill File Format
A skill file has two parts: frontmatter (optional) and body (required).
---
name: my-skill
description: A brief description of what this skill does
user-invocable: true
argument-hint: "<required-arg> [optional-arg]"
---
You are now executing the "my-skill" skill.
The user asked: $ARGUMENTS
Perform the requested action and report results.
Step 1: Choose a Location
Skills are discovered from three paths, in priority order:
| Priority | Path | Style |
|---|---|---|
| 1 (highest) | <project>/.claude/skills/<name>/SKILL.md | Directory |
| 2 | <project>/.skills/<name>.md | Flat file |
| 3 (lowest) | ~/.claude/skills/<name>/SKILL.md | Global directory |
Directory style is preferred — each skill gets its own directory, which can contain supporting files:
.claude/skills/
commit/
SKILL.md
review/
SKILL.md
checklist.md
Flat file style is available for backward compatibility:
.skills/
commit.md
review.md
If a skill with the same name exists at multiple paths, the highest-priority path wins. First match is used; duplicates at lower priorities are ignored.
Step 2: Write the Frontmatter
The YAML frontmatter block is delimited by --- lines at the top of the file. All fields are optional:
| Field | Type | Default | Description |
|---|---|---|---|
name | String | Filename/directory name | Skill identifier (overrides the inferred name) |
description | String | None | One-line description shown in skill discovery |
user-invocable | bool | false | If true, appears in the / slash-command menu |
disable-model-invocation | bool | false | If true, only the user can invoke this skill (not the model) |
allowed-tools | String[] | None | Restrict which tools the skill can access |
model | String | None | Override the model for this skill's execution |
context | String | None | Set to "fork" for subagent execution |
agent | String | None | Subagent type when context: fork |
argument-hint | String | None | Usage hint displayed to the user |
hooks | HooksConfig | None | Lifecycle hooks specific to this skill |
unsafe | bool | None | Reserved for future WASM sandbox flag |
Invocation Control
| Setting | Effect |
|---|---|
user-invocable: true | Appears in / menu; user and model can invoke |
user-invocable: false | Hidden from menu; model-only unless model invocation also disabled |
disable-model-invocation: true | Only the user can invoke via /skill-name |
Example Frontmatter
---
name: commit
description: Create a conventional commit
user-invocable: true
disable-model-invocation: false
allowed-tools:
- Bash
- Read
- Grep
argument-hint: "[commit message]"
model: claude-sonnet-4-5-20250929
---
Step 3: Write the Body
The body is everything after the closing ---. It's injected into the agent's prompt when the skill is invoked. Use argument placeholders to make the skill dynamic:
Argument Substitution
| Placeholder | Replaced With |
|---|---|
$ARGUMENTS | The full argument string passed by the invoker |
$ARGUMENTS[0] through $ARGUMENTS[9] | Positional argument (space-split) |
$0 through $9 | Shorthand for $ARGUMENTS[N] |
Substitution is single-pass (left-to-right) — output from one replacement is never re-processed. Missing positional arguments are replaced with an empty string. Only indices 0–9 are supported.
Example Body
---
name: test-file
description: Run tests for a specific file
user-invocable: true
argument-hint: "<file-path>"
---
Run the tests for the file at `$0`.
Steps:
1. Read the file to understand what it does
2. Find the corresponding test file
3. Run the tests with `cargo test`
4. If tests fail, analyze the failures and suggest fixes
5. Report results
Full context from user: $ARGUMENTS
When invoked as /test-file src/main.rs, the placeholders expand to:
$0→src/main.rs$ARGUMENTS→src/main.rs
When invoked as /test-file src/main.rs --verbose, the placeholders expand to:
$0→src/main.rs$1→--verbose$ARGUMENTS→src/main.rs --verbose
Step 4: Add Skill-Level Hooks (Optional)
Skills can define their own hooks that fire during skill execution:
---
name: deploy
description: Deploy to staging
user-invocable: true
hooks:
pre_tool_use:
- matcher: Bash
hooks:
- type: command
command: ./scripts/validate-deploy.sh
timeout: 10
---
Hook configuration follows the same format as project-level hooks. See Hooks for details.
Step 5: Test Your Skill
Verify Discovery
Skills are discovered automatically when agents build their prompts. To verify your skill is found, check that:
- The file exists at one of the three resolution paths
- The filename or
namefield matches what you expect - If
user-invocable: true, it should appear in the agent's available slash commands
Test Resolution
The resolution order is deterministic:
- Swarm checks
<project>/.claude/skills/<name>/SKILL.md - If not found, checks
<project>/.skills/<name>.md - If not found, checks
~/.claude/skills/<name>/SKILL.md - If not found at any path, the skill is not available
Validate the Name
Skill names must contain only [a-zA-Z0-9_:-]. Names with other characters (including /, .., spaces) are rejected to prevent path traversal.
Examples
Simple Commit Skill
---
name: commit
description: Create a git commit with conventional format
user-invocable: true
allowed-tools:
- Bash
- Read
- Grep
argument-hint: "[commit message]"
---
Create a git commit following the conventional commits format.
If no message was provided, analyze the staged changes and generate an appropriate message.
User input: $ARGUMENTS
Steps:
1. Run `git diff --cached` to see staged changes
2. Generate or use the provided commit message
3. Ensure the message follows conventional commits (feat:, fix:, chore:, etc.)
4. Create the commit
Code Review Skill
---
name: review
description: Review code changes in the current branch
user-invocable: true
disable-model-invocation: true
argument-hint: "[focus area]"
---
Review the code changes in the current branch compared to main.
Focus area: $ARGUMENTS
Steps:
1. Run `git diff main...HEAD` to see all changes
2. For each changed file, analyze:
- Correctness: Are there bugs or logic errors?
- Security: Any vulnerabilities introduced?
- Performance: Any obvious performance issues?
- Style: Does the code follow project conventions?
3. Provide a summary of findings
Subagent Skill
---
name: research
description: Research a topic using a subagent
user-invocable: true
context: fork
agent: researcher
argument-hint: "<topic>"
---
Research the following topic thoroughly: $ARGUMENTS
Provide a detailed summary with references.
Related
- Skills Concept — How the skill system works internally
- Hooks — Lifecycle hooks for skills and agents
- Permissions — How
allowed-toolsinteracts with permissions