Companion page: after you read this, see how to publish your skill as open source: GitHub repo, license, plugin, marketplace and updates, with create-launcher as the example.
01What a skill is, and why you want one
What. A skill is a folder with one file in it, SKILL.md. The file has two parts: a short header that says what the skill is for, and plain Markdown instructions that say how to do it. Think of it as a written procedure you hand to a new teammate, except the teammate is Claude.
Why. Look at the prompts you type more than once: "review this like we do", "write release notes in our style", "set this project up so I can run it". Each time you retype them you forget a detail, and each teammate words them differently, so results drift. A skill fixes the wording once, keeps it in a file you can edit and version, and makes the result repeatable.
How it works. Claude Code puts only the one-line description of every skill in the session. The full instructions load only when the skill is used. That is the key design: you can keep dozens of skills and pay almost nothing in context until one is needed. A skill runs in one of two ways. Claude loads it on its own when your request matches the description, or you call it with /skill-name.
02Skill, CLAUDE.md, prompt or command?
You already know two ways to steer Claude. A skill is the third, and it helps to know which to reach for:
.claude/commands/. Still works and makes the same /name. Skills are the newer form with more features (section 13).A simple test: if Claude should always know it, put it in CLAUDE.md. If you would only want it when a certain job comes up, make it a skill.
03Where skills live
What. The folder you put a skill in decides who gets it. Why it matters: a personal habit should not clutter your team's repo, and a team standard should not depend on one person's laptop. How: pick the folder that matches who should have it.
~/.claude/skills/<name>/SKILL.md. Every project, only you. On Windows that is $HOME\.claude\skills\. Good for your own habits..claude/skills/<name>/SKILL.md inside the repo. Commit it and every teammate who clones gets it. Good for team standards.packages/api/.claude/skills/.... Loads when Claude works on files under that folder. Good for monorepos where each area has its own rules./plugin-name:skill-name. Plugins get their own day later in the series.04A real skill: create-launcher
What. create-launcher is a skill I wrote and use. It inspects a project, works out its stack (Python, Node, or a frontend plus backend), and writes three start scripts, launch.sh, launch.bat and launch.ps1, so anyone can run the project on any operating system. It is open source at github.com/Kowshik46/create_launcher_skill.
Why it is a good skill. The job is the same every time but the details are fiddly: which package manager, where the virtual environment lives, how to stop every process on Ctrl+C, how to avoid PowerShell's execution-policy block. Writing that into a prompt each time is error-prone. Written once as a skill, it is correct every time.
How to install it. A skill is just a file, so installing means copying it into a skills folder. From PowerShell:
git clone https://github.com/Kowshik46/create_launcher_skill mkdir .claude\skills\create-launcher copy create_launcher_skill\.claude\skills\create-launcher\SKILL.md .claude\skills\create-launcher\ # for every project instead, use your home folder mkdir $HOME\.claude\skills\create-launcher
How to use it. Open Claude Code in a project and either type /create-launcher, or ask in plain words: create launcher scripts for this project. The second works because Claude compares your request with the skill's description. There is no restart: Claude Code watches skill folders. The one exception is a brand-new top-level skills folder created mid-session, where you run /reload-skills.
How it is built. Open its SKILL.md. Every part is doing a job:
--- name: create-launcher description: Use when the user asks to create a launcher, setup script, or run configuration for a project. Detects the stack, provisions a missing .env, and generates launch.sh, launch.bat and launch.ps1. --- ## Step 1: Detect services Python: requirements.txt or pyproject.toml. Node: package.json... ## Step 2: Environment files Copy .env.example to .env only if .env is missing. Never print it. ## Step 3: Rules for all three scripts Run from the script's own folder. Stop everything on Ctrl+C... ## Step 5: Verify Run bash -n launch.sh. Do not start the services unless asked. ## Step 6: Report List files, services found, TODOs, and how to run each script.
It also ships as a Claude Code plugin, which bundles skills for easy sharing: claude plugin marketplace add Kowshik46/create_launcher_skill. Want to publish your own skill as open source? Read the companion page, how to publish and share a skill, which covers the repo, license, plugin, marketplace and updates.
05Write your own, step by step
What and why. Your best first skill is a routine you already repeat. You do not need to invent anything: take the prompt you have typed three times and turn the best version of it into a file. Here is a small one that reviews your uncommitted changes.
How. Create the folder and file from PowerShell, or in VS Code with New Folder and New File in the Explorer:
mkdir .claude\skills\review-changes code .claude\skills\review-changes\SKILL.md
--- name: review-changes description: Reviews uncommitted changes and flags risks. Use when the user asks what changed, wants a review, or wants a commit message. --- ## Current changes !`git diff HEAD` ## Instructions Summarise the changes above in 3 bullets. Then list risks: missing error handling, hard-coded values, missing tests. End with a one-line commit message.
Two details matter. The very first line of the file must be ---, otherwise the header is treated as ordinary text. And !`git diff HEAD` is special: Claude Code runs that command before Claude reads the skill and pastes the real diff in its place (section 10). Run it with /review-changes, then improve the skill by editing the file, not by correcting Claude in chat, so the fix is permanent.
06The description: the line that matters most
What. The description is the only part of a skill Claude sees until it decides to use it. Why it matters: if the description does not match how you actually ask, Claude never loads the skill, however good the instructions are. How to write it: say what the skill does, then say when to use it, in the words people really type, and put the main use first.
Helps with code. Matches everything and nothing, so Claude cannot tell when it applies.Reviews uncommitted changes and flags risks. Use when the user asks what changed, wants a review, or wants a commit message. It names the job and the triggers.when_to_use field for more example phrases. It is appended to the description.when_to_use are cut at 1,536 characters in the listing, so lead with the key use case.07The header, field by field
Every field is optional, but knowing them lets you shape how a skill behaves. These are the ones you will actually use:
/command. Defaults to the folder name.[issue-number], and names for the inputs (section 09).true means only you can run it. For anything with side effects (section 08).false hides it from the / menu so only Claude uses it. For background knowledge.src/api/**/*.ts. The skill then loads automatically only when Claude works on matching files.context: fork runs the skill in a separate subagent (section 12).bash by default, or powershell for the !`command` lines on Windows.Typos fail silently. Unknown field names are ignored, and if the YAML cannot be parsed the skill loads with no fields at all. If a skill acts strangely, check the header first.
08Who may trigger it
What. By default both you and Claude can run a skill. Why change that: some skills should never fire by themselves. A deploy skill that Claude decides to run because you said "ship it" in passing is a bad surprise. How: one line in the header.
Rule of thumb: if running it twice by accident would hurt, make it disable-model-invocation: true.
09Arguments: make a skill reusable
What. Anything you type after the skill name is passed in as arguments. Why: one skill can then serve many cases, such as any issue number or any component name, instead of you writing a new skill each time. How: use a placeholder in the body.
--- name: fix-issue description: Fix a GitHub issue on a branch disable-model-invocation: true arguments: [issue, branch] --- Fix GitHub issue $issue on branch $branch. Follow our coding standards and write tests. # run it: > /fix-issue 123 fix/login-bug
/skill "hello world" two.arguments. Easier to read than numbers.ARGUMENTS: ... so the input is not lost.10Live context: feed it real data
What. A line written as !`command` runs a shell command first and is replaced by its output. Why: Claude then starts from the real diff, the real PR or the real test output instead of guessing or spending turns running commands. How: put the command in the body where the data belongs. For several lines use a fenced block that opens with ```!.
Know the limits. The command goes through your permission rules like any other. If an injected command fails, the whole skill stops, so use commands you know work in that project. The default shell is bash; add shell: powershell to the header when the command is PowerShell, as on many Windows machines.
11Supporting files and pre-approved tools
What. A skill folder can hold more than SKILL.md. Why: a long skill wastes context every time it loads. Keep SKILL.md short (under 500 lines) and move reference material, examples and scripts next to it. How: mention each file in SKILL.md with a line on when to read it.
release-notes\ SKILL.md overview: when and how style-guide.md read when writing the notes examples.md good and bad past notes scripts\collect.ps1 run, never loaded as text
Claude reads a supporting file only when the task needs it, and runs a script instead of loading it. To let a skill run specific commands without a prompt each time, pre-approve them in the header:
allowed-tools: Bash(git log *) Bash(git tag *) # or a bundled script: allowed-tools: Bash(${CLAUDE_SKILL_DIR}/scripts/render.sh *)
This only adds permission, and only for the turn that runs the skill. It clears on your next message and never loosens the Day 5 rules for anything else. Keep the list as narrow as the skill needs.
12Run it in a fork
What. Adding context: fork runs the skill in its own subagent, a separate Claude with a fresh context. Why: jobs that read dozens of files would flood your main conversation. In a fork all that reading happens off to the side, and only the summary comes back, so your main session stays sharp (Day 5). How: two header lines.
--- name: deep-research description: Research a topic thoroughly across the codebase context: fork agent: Explore --- Research $ARGUMENTS thoroughly: 1. Find relevant files with Glob and Grep 2. Read and analyse the code 3. Summarise findings with file references
agent chooses the kind of subagent. Explore is a read-only searcher, a safe choice for research. This is a first taste of subagents, which are the next topic.
13Custom slash commands: the older way
What. Before skills, a custom command was a single Markdown file in .claude/commands/ (project) or ~/.claude/commands/ (personal). Why you still see them: they keep working, and plenty of repos have them. .claude/commands/deploy.md and .claude/skills/deploy/SKILL.md both create /deploy, and if both exist the skill wins. How to choose: a command file is fine for a quick one-off prompt. Use a skill when you want supporting files, invocation control, paths or automatic loading. Skills can also replace a built-in command of the same name, so check the / menu before reusing a name.
14In VS Code
Skills are plain files, so the terminal and the extension read the same folders. A skill you write in one place appears in the other.
/ in the Claude panel. Project, personal and bundled skills are all listed./create-launcher. Arguments go after the name..claude/skills/<name>/SKILL.md and save. No restart needed./skills lists them all, and you can stack up to six at the start of one message, for example /write-tests /fix-issue 123.15When a skill does not trigger
The usual causes, in the order to check them:
--- on line 1, valid YAML, field names spelled exactly (hyphens included)./skills. If it is missing, run /reload-skills, or start with claude --debug and look at the log.skillOverrides setting can turn a skill off or restrict it to user-invocable-only.16Skills that already ship with it
Claude Code includes bundled skills, which are good working examples. Try /doctor for a setup check-up that asks before changing anything, /code-review for a review, /debug for a stubborn bug and /loop to repeat a prompt on a timer. Others include /batch, /verify, /run and /claude-api. Run one, notice how it behaves, then copy that shape for your own skills.
17Habits that make skills good
disable-model-invocation: true.turn what we just did into a skill in .claude/skills, then read and edit the result.18Try this today
/create-launcher on something you want to start with one command./name, once by asking in plain words, to prove the description matches.SKILL.md, not in the chat.Ready to share what you built? See how to publish a skill as open source.
Next up: subagents. How to split a big job across helpers that each work in their own context.