← Back to Blog

How to Make a Claude Code Skill (Step by Step)

A Claude Code skill is a custom slash command defined by a markdown file in ~/.claude/skills/. Each skill lives in its own folder with a SKILL.md file containing YAML frontmatter (name, description, allowed tools) and plain-English instructions. When invoked, Claude loads the file and enters a workspace shaped by those instructions. Skills support arguments via $ARGUMENTS, live data injection with shell commands, and supporting reference files in the same folder.

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.

But before the how-to, it helps to understand what you’re actually building. If you’re wondering when to build a skill vs. an agent, Skills vs. Agents in Claude Code covers the distinction.

What is a skill, really?

A skill is just English. No code. No magic. Just clear instructions in a file.

When you type /my-skill, two things happen: you invoke the skill, and Claude enters a kind of room. That room has a specific context, a specific set of instructions, specific tools, and its own vibe. It’s not a general-purpose chat session. It’s a space set up for one job.

Think about how different these rooms feel:

  • chief-of-staff: inbox on the desk, calendar on the wall, orientation energy. “Let’s figure out what matters today.”
  • vibe-coach: no distractions, one task, anti-scope-creep. “Finish this one thing before anything else.”
  • branding-coach: frameworks everywhere, confrontational energy. “What do you actually stand for?”

Same AI. Completely different experience, because the room is different.

Pick the right thing to build

Here’s the question worth sitting with before you build anything:

What do you wish you didn’t have to do?

Not the big stuff. Not “I wish someone else ran my company.” The small, repeatable things. The stuff you do the same way every time and kind of dread anyway.

One thing. That’s your first skill.

Some common ones people build:

  • Daily planner / chief of staff (get oriented at the start of each day)
  • Content repurposing (turn a long article into social posts in your voice)
  • Meeting notes organizer (paste in a transcript, get clean action items)
  • Code reviewer (check PRs against your specific standards)
  • Email drafter (write in your tone, not generic assistant-voice)
  • Research assistant (scoped to a specific domain or topic)

You can also browse community-built skills at skills.sh and install them directly. Someone’s probably already built what you need.

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. The more specific you are, the more useful the skill.

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. This is what makes a skill feel alive instead of static.

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. For more on managing context space, see Your CLAUDE.md Is Probably Too Long.

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.

Further reading

Common Questions

How do I create a Claude Code skill?

Create a folder at ~/.claude/skills/my-skill/ with a SKILL.md file inside. Add YAML frontmatter with a name and description, then write instructions in markdown below. Start a new Claude Code session, type /my-skill, and Claude loads the instructions.

What goes in a SKILL.md file?

YAML frontmatter with name, description, and optionally allowed-tools. Below that, plain-English instructions for what Claude should do. Be specific about steps, rules, and output format. The file is essentially a detailed prompt that shapes Claude’s behavior.

How do I pass arguments to a Claude Code skill?

Use $ARGUMENTS in your SKILL.md body. Whatever the user types after the slash command gets substituted in. For example, /explain dependency injection with Explain $ARGUMENTS simply becomes “Explain dependency injection simply.” You can also access individual words with $ARGUMENTS[0].

Why isn’t my Claude Code skill showing up?

Skills are discovered at session start. After creating a new skill, start a fresh Claude Code session. Also check that the folder structure is correct: ~/.claude/skills/skill-name/SKILL.md. If you have many skills, some may be excluded due to context space limits.


A note from Alex: hi i’m alex - i run code for creatives. i’m a writer so i feel that it is important to say - i had claude write this piece based on my ideas and ramblings, voice notes, and teachings. the concepts were mine but the words themselves aren’t. i want to say that because its important for me to distinguish, as a writer, what is written ‘by me’ and what’s not. maybe that idea will seem insane and antiquated in a year, i’m not sure, but for now it helps me feel okay about putting stuff out there like this that a) i know is helpful and b) is not MY voice but exists within the umbrella of my business and work. If you have any thoughts or musings on this, i’d genuinely love to hear them - its an open question, all of this stuff, and my guess is as good as yours.

Ready to build this yourself?

Join the next cohort of Code for Creatives

Join the Next Cohort →