Skills are custom slash commands for Claude Code. You make a markdown file, put it in the right folder, and Claude picks it up automatically. That’s it.

Build one from scratch:

1. Create the folder and file

Every skill lives in its own folder with a SKILL.md inside it. For a personal skill (available across all your projects):

mkdir -p ~/.claude/skills/my-skill
touch ~/.claude/skills/my-skill/SKILL.md

For a project-specific skill, use .claude/skills/my-skill/SKILL.md in your repo instead.

The folder name becomes the command name. So ~/.claude/skills/my-skill/ gives you /my-skill.

2. Write the frontmatter

Open SKILL.md and start with YAML frontmatter. Only description really matters, but there are useful options:

---
name: my-skill
description: Does the thing when you need the thing done
allowed-tools: Read, Grep, Bash
---

The description field is how Claude decides whether to auto-invoke your skill. Make it specific. “Helps with stuff” won’t cut it.

Here’s what the other fields do:

  • allowed-tools - Which tools Claude can use without asking permission. Comma-separated. If you don’t set this, Claude uses whatever your permission mode allows.
  • disable-model-invocation: true - Prevents Claude from running this skill on its own. You can still type /my-skill manually.
  • user-invocable: false - Hides it from the / menu. Claude can still invoke it behind the scenes. Good for background knowledge skills.
  • argument-hint - Shows up in autocomplete. Like [filename] or [topic].
  • context: fork - Runs the skill in an isolated subagent so it doesn’t pollute your conversation context.

3. Write the instructions

Below the frontmatter, write what you want Claude to do. This is just markdown. Be specific. Be bossy.

---
name: my-skill
description: Does the thing when you need the thing done
---

# My Skill

You are a [role]. When invoked, do [specific thing].

## Steps

1. First do this
2. Then do that
3. Output in this format

## Rules

- Always check X before doing Y
- Never do Z

Think of it as writing a really detailed prompt.

4. Handle arguments with $ARGUMENTS

If your skill takes input, use $ARGUMENTS in the body. Whatever the user types after the slash command gets substituted in before Claude sees it.

---
name: explain
description: Explain a concept simply
---

Explain $ARGUMENTS like I'm five years old.
Use no jargon. Use one analogy.

Now /explain dependency injection becomes “Explain dependency injection like I’m five years old.”

You can also grab individual arguments by position:

$ARGUMENTS    → everything ("dependency injection")
$ARGUMENTS[0] → first word ("dependency")
$ARGUMENTS[1] → second word ("injection")
$0, $1        → shorthand for the above

If you don’t put $ARGUMENTS anywhere in your file, Claude Code tacks it onto the end automatically.

5. Pull in live data with shell commands

You can run shell commands that execute before Claude reads the skill, using ! followed by a command in backticks:

## Current git state
!`git status --short`

## Recent commits
!`git log --oneline -5`

The output replaces the command inline. Claude sees the actual results, not the commands. So your skill can react to the current state of your repo, pull in API data, read config files, whatever.

6. Add supporting files (optional)

If your skill needs reference material, put it in the same folder:

my-skill/
├── SKILL.md
├── reference.md
├── examples.md
└── scripts/
    └── helper.py

Reference them from SKILL.md:

See [reference.md](reference.md) for the full API spec.

Use ${CLAUDE_SKILL_DIR} in bash commands to point to the skill’s folder regardless of where you’re running from:

python ${CLAUDE_SKILL_DIR}/scripts/helper.py

7. Test it

Start a new Claude Code session (or type / and look for your skill in the autocomplete). Skills are discovered at session start, so you need a fresh session after creating one.

Type /my-skill and see what happens. Iterate on the SKILL.md until it does what you want.

A real example

Here’s a minimal but functional skill that reviews a file for security issues:

---
name: security-check
description: Review a file for common security vulnerabilities
allowed-tools: Read, Grep, Glob
---

# Security review

Read the file at $ARGUMENTS and check for:

- Hardcoded secrets or API keys
- SQL injection vulnerabilities
- Unsanitized user input
- Insecure HTTP calls that should be HTTPS

Report what you find. If nothing looks wrong, say so. Don't pad the report.

That’s a working skill. Save it, open a new session, run /security-check src/auth.py, and Claude reads the file and checks for those specific issues.

Things that’ll trip you up

Skill not showing up? Start a new session. Claude discovers skills at launch.

Too many skills? Descriptions compete for context space. If you have dozens, some might get excluded. Keep descriptions short and specific.

Skill doing too much? Keep SKILL.md under 500 lines. Move reference docs to separate files in the same folder.

Want it project-specific? Use .claude/skills/ in your repo root instead of ~/.claude/skills/. Commit it so your team gets it too.