How to Create a Custom Claude Code Skill (With a Real Working Example)
To create a custom skill for Claude Code, make a folder with a SKILL.md file inside it, placed at ~/.claude/skills/<skill-name>/ (available across all your projects) or at .claude/skills/ inside a repo (shared with your team). In SKILL.md, the YAML frontmatter must include name and description; the body holds your step-by-step instructions. Restart Claude Code to load the skill, then test it with a natural prompt that matches the description. The whole game is in the description: write it well and the skill fires automatically; write it vaguely and it never runs.
this article is based on the Claude Code CLI. Skills are a fast-moving feature and some details may change; I cite my sources at the end.
What is a custom skill in Claude Code? (quick definition)
A custom skill is a package of instructions - a folder plus a SKILL.md file - that teaches Claude Code to do a repeatable workflow exactly the way you want it done. Instead of retyping the whole "format this blog post to standard X, add a table of contents, write the meta..." prompt every time, you package that recipe once as a skill. From then on, Claude Code recognizes when to use it and follows your steps.
Newcomers often confuse a skill with two other things, so let's separate them fast:
- Skill - knowledge or a workflow that Claude Code invokes automatically when the context matches your description. You don't type any command.
- Slash command - a shortcut you type deliberately (for example
/commit). See the details in slash commands in Claude Code. - Subagent - a "sub-assistant" that runs heavy tasks in its own separate context. See the subagents guide.
If all four concepts still blur together, the article on skills vs subagents vs hooks vs MCP breaks it down more thoroughly. And if you're not yet clear on what a skill fundamentally is, read what Claude Code Skills are first, then come back here to actually build one. This article is 100% focused on getting a real skill running in the Claude Code CLI.
How does a skill work? (progressive disclosure)
Understand this mechanism and you'll write skills correctly from the start. Claude Code does not stuff the full contents of every skill into context - that would burn tokens and add noise. It uses progressive disclosure (load on demand), across three layers:
- Layer 1 - always resident: Claude Code keeps only the
nameanddescriptionof each skill in context. This is the "signpost" that tells it which skills exist and what they're for. - Layer 2 - loaded on match: only when the conversation context matches the
descriptiondoes the body ofSKILL.mdget read into context. - Layer 3 - loaded on demand: supporting files like
reference.mdorscripts/are opened only when Claude actually needs them.
The most important consequence: the description is the auto-invoke switch. If your description doesn't contain the context keywords a user will actually say, Claude Code will never open your skill body to read it - no matter how well that body is written. This is why most "it won't run" skills fail right at the description line, not in the content.
Setup: where the skill lives (personal vs project)
This is where most English-language tutorials skip ahead, because they talk about the claude.ai web app. With the Claude Code CLI, a skill lives on the filesystem and you have two places to put it, chosen by purpose:
| Location | Scope | When to use it |
|---|---|---|
~/.claude/skills/<name>/ |
Personal - available in every project on your machine | Your own skills: commit habits, writing style, workflows only you repeat |
.claude/skills/<name>/ (in the repo) |
Project - only in that repo, committable for the team | Project-specific conventions: coding standards, how to write migrations, the team's PR format |
The simple rule: your own workflow goes in ~/.claude/skills/; a whole team or project convention goes in .claude/skills/ inside the repo, then commit it to git so everyone gets it.
The only prerequisite is that Claude Code is installed (if it isn't, see the Claude Code installation guide). You can check your existing skills by asking directly in a Claude Code session - for example the prompt "list the skills you currently have" - or by opening the ~/.claude/skills/ folder. After creating a new skill, remember to restart so it gets scanned in.
How to create a custom Claude Code skill in 5 steps
Here's the full workflow. I'll use one running example throughout - a blog-formatter skill that cleans up a raw Markdown blog post - so it's easy to picture, but the approach applies to any workflow.
Step 1 - Pick one repeatable workflow
Don't rush to write a skill for something you've never done by hand. Practical tip: do it manually with Claude Code a few times until it produces exactly the result you want, and only then distill that prompt/workflow into a skill. A good skill is the crystallization of a proven process, not a guess.
A few good candidates to start with: formatting a blog post to your standard, generating commit messages to the project's convention, writing unit tests from an existing template, or reviewing API docs. Pick something you do at least once a week - that's where the ROI shows.
Step 2 - Create the folder tree + SKILL.md file
A minimal skill needs only a folder and a SKILL.md file. You add supporting files when you need them. The full folder tree looks like this:
~/.claude/skills/
blog-formatter/
SKILL.md # required - the main instructions
reference.md # optional - long details, loaded on demand
scripts/
format.py # optional - a bundled script
Create the folder from the terminal:
mkdir -p ~/.claude/skills/blog-formatter
cd ~/.claude/skills/blog-formatter
Name the folder in kebab-case, short and descriptive of what the skill does (blog-formatter, commit-msg). For a small skill, a single SKILL.md is enough - only split out reference.md or scripts/ once the body starts getting long.
Step 3 - Write the YAML frontmatter (name + description)
Open SKILL.md. At the very top is a YAML frontmatter block between two --- lines, containing two required fields: name and description. This is the part that decides whether the skill auto-invokes or not, so write it carefully.
The formula for a good description: what it does + WHEN to use it + trigger keywords that the user will actually say out loud. Compare:
| Bad description (skill won't run) | Good description (auto-invokes correctly) |
|---|---|
description: Blog format skill |
description: Standardize a Markdown blog post - add a table of contents, fix headings, generate a meta description. Use when the user says "format this post", "clean up this article", "tidy up the Markdown". |
The left one is vague, has no context, and Claude has no idea when to call it. The right one spells out what, when, and the exact phrases users tend to type. Write the description as if you were telling a new coworker "here's when to come to me."
Step 4 - Write the instruction body
Right below the frontmatter is the Markdown body - this is the workflow Claude Code reads and follows when the skill is called. A good body should include:
- Purpose - what problem this skill solves.
- When to use it - restate the context (reinforces the description).
- Inputs to ask for - if information is missing, what to ask the user.
- The steps - a clear, numbered procedure.
- Output standard - what a correct result looks like.
- Mistakes to avoid + an example input/output.
Golden rule: concise is key. A bloated body burns context and distracts Claude. When the instructions get long (lookup tables, many examples), split them into reference.md and point to it from the body - thanks to progressive disclosure, the supporting file loads only when needed.
Step 5 - Reload & test the skill
Claude Code scans the skills folder at startup, so after creating or editing SKILL.md you need to restart: type /exit and reopen the Claude Code session. Then test with a natural prompt that matches the description - for example: "Format the blog post in draft.md for me." If you wrote it well, Claude Code recognizes it and calls the blog-formatter skill. Confirm it used the right skill (Claude usually reports which skill was invoked), then check that the result meets the standard you set in Step 4.
A complete custom skill example (copy-paste and run)
Here's a full SKILL.md I've actually written and used. Copy it verbatim into ~/.claude/skills/commit-msg/SKILL.md, restart, and try it right away:
---
name: commit-msg
description: Generate a Conventional Commits message from the currently staged changes. Use when the user says "write a commit", "commit message", "make a commit message", or right before committing code.
---
# Generate a Conventional Commits message
## Purpose
Read the staged diff and write a short, standards-compliant commit message.
## When to use
When the user is about to commit or asks for a commit message.
## Inputs to ask for
If nothing is staged, run `git diff --staged` to see the changes.
If it's still empty, ask the user: "Have you run `git add` yet?"
## Steps
1. Run `git diff --staged` to read the changes.
2. Determine the type: feat / fix / docs / refactor / test / chore.
3. Determine the scope (the main module/folder changed).
4. Write the subject line: `type(scope): short description` - max 72 chars, present tense.
5. If the change is complex, add 1-3 bullet points in the body explaining "why".
## Output standard
- Subject ≤ 72 chars, no trailing period.
- Description is clear and matches what was actually done.
- Do NOT invent changes that aren't in the diff.
## Mistakes to avoid
- Don't use the wrong type (adding a feature but labeling it `fix`).
- Don't write vague messages like "update code", "misc fixes".
## Example
Input diff: add an email validation function in `src/auth/`.
Output:
feat(auth): add email format validation on signup
Real result: once it's loaded, I just type "write a commit" and Claude Code runs git diff --staged, classifies it correctly, and returns a standards-compliant message - without me restating the convention every time.
One observed limitation (honestly): if the diff is huge or mixes several kinds of change, the combined message sometimes picks a type that isn't the best fit - at which point you should still split the commit or fix it by hand. The skill nails 90% of cases; it doesn't replace your judgment entirely.
Test & debug when a skill doesn't trigger
A finished skill that Claude Code "ignores" is very common. Here's the checklist I run through, in order, when a skill refuses to fire:
- Broken YAML syntax. A missing
---, wrong indentation, or a stray character in the frontmatter means the whole skill is silently skipped. Check the frontmatter block first. - Vague description / missing context keywords. This is the number-one culprit. If your prompt contains no phrase that overlaps with the
description, the skill isn't called. Add the exact words a real user would say. - Haven't restarted Claude Code. The skills folder is only scanned at startup. After editing, you must
/exitand reopen. - Duplicate name or wrong path. Two skills with the same
name, or aSKILL.mdin the wrong folder (case mismatch, wrong level) won't load. - Body too long, causing noise. A bloated body can make it harder for Claude to follow the procedure. Trim it and move the excess into
reference.md.
Quick diagnostic tip: force a manual call to isolate the problem. Prompt directly: "Use the blog-formatter skill to do this." If the forced call works fine, the bug is in the description (it can't auto-invoke). If the forced call still fails, the bug is in the YAML or the path.
Share & publish your skill
Once you've written a good skill, you should share it - and this is the part almost no English tutorial covers. There are three ways, from simple to more polished:
- Commit it to the repo for the whole team. Put the skill in
.claude/skills/inside the project andgit commit. Anyone who clones the repo gets that skill immediately - the fastest way to standardize a process for a team. - Push it to GitHub for the community. Create a repo of skills; others clone it or copy the skill folder into their own
~/.claude/skills/. Include a README describing what each skill does. - Package it as a plugin. With several related skills, you can bundle them into a plugin for tidier distribution (I have a separate article on Claude Code plugins).
Bonus: skills use an open standard (Markdown + YAML frontmatter), so a SKILL.md written for Claude Code is often reusable in, or easily convertible to, other tools like Cursor or Copilot - write once, use in many places.
Don't want to write your own? Use 108+ prebuilt skills
Writing your own skills is a skill worth learning - it gives you full control to tailor things to your exact workflow, and I recommend it to anyone using Claude Code seriously. But if you want a production-ready skill set right now without building each one yourself, the Engineer Kit ships 60+ prebuilt skills (frontend, backend, database, DevOps, code review) and is a shortcut worth considering.
Take the shortcut: the AgentKit prebuilt skill bundle — now $149 (from $198) packages 108+ skills for Claude Code - usable right away instead of writing each file yourself. To be honest: you should still know how to write skills (like in this article) to customize the specialized parts; the kit handles the repetitive groundwork.
Frequently asked questions (FAQ)
How is a skill different from a subagent?
A skill is a package of instructions that Claude Code loads into the current context when the context matches, running in the same session. A subagent is a sub-assistant that runs heavy tasks in its own separate context, independently. Light, repeatable work goes to a skill; large work that needs isolation goes to a subagent.
Where does SKILL.md go?
Put it at ~/.claude/skills/<name>/SKILL.md if you want it across every project (personal), or at .claude/skills/<name>/SKILL.md inside a repo if you want to commit and share it with the team (project). Each skill is its own folder containing a SKILL.md file.
Why doesn't my skill run automatically?
Usually because the description is vague and missing the keywords you actually say in your prompt. Also check: whether the YAML frontmatter has a syntax error, whether you've restarted Claude Code, and whether the folder path is correct.
Do I need to restart after creating or editing a skill?
Yes. Claude Code only scans the skills folder at startup, so after creating or editing SKILL.md, you need to /exit and reopen the session for the skill to be loaded.
Can a skill written for Claude Code also be used with claude.ai?
The skill standard (Markdown + YAML frontmatter) is open, so the content is usually reusable. However, the loading differs: Claude Code uses a local file folder (~/.claude/skills/), while the claude.ai web app loads them its own way. Treat a SKILL.md file as a reusable asset, not something that's plug-and-play identical everywhere.
Are there ready-made skills I can use right away?
Yes. If you don't want to start from scratch, kits like AgentKit package 108+ skills for Claude Code across many domains. You should still know how to write your own for customization, but a kit saves you the repetitive groundwork.
Conclusion + next steps
Custom skills are the most effective way to "teach" Claude Code to work to your exact standard without repeating prompts. Start small: pick one workflow you do every week, distill it into a SKILL.md, write a really clear description, test, and iterate. Read what Claude Code Skills are next to nail the fundamentals, and slash commands in Claude Code to pair skills with deliberate shortcuts. And when you need a production-ready skill set right away instead of writing each one, consider a prebuilt kit (see the box below).
Want a more powerful Claude Code right now? If you don't have time to write each skill yourself, a prebuilt kit gives you 60+ tested Engineer skills - use them immediately, and still customize further.
Sources: Claude Code Docs - Skills (Anthropic, updated 2026) for the SKILL.md structure and loading mechanism. Skills are an evolving feature; details may change between versions.