- Published on
Add Claude Code Skills as Slash Commands
- Authors

- Name
- Alex Peng
- @aJinTonic
If you find yourself pasting the same instructions into Claude Code, it mean it is time to make a skill.
A skill is a small, focused instruction package. In Claude Code, it can be loaded automatically when it is relevant, or invoked directly as a slash command. A file at .claude/skills/review-route/SKILL.md becomes /review-route.
Creating a skill
Lets create a skill review-route for reviewing code with the following folder structure.
your-project/
└── .claude/
└── skills/
└── review-route/
└── SKILL.md
Notice how it is under the .claude/skills folder and the name of the skill is the folder name. A skill folder can also hold supporting files alongside SKILL.md. This includes things like templates, examples, scripts, reference docs or anything Claude should have access to when running that skill.
In .claude/skills/review-route/SKILL.md we will add the following:
---
description: Review an API route or request handler for correctness, security, and maintainability.
argument-hint: <file-or-directory>
disable-model-invocation: true
allowed-tools: Read Grep Glob
---
Review `$ARGUMENTS`.
1. Read the target and the code it calls.
2. Identify input-validation, authorization, error-handling, and data-exposure issues.
3. Check that status codes and response shapes follow nearby conventions.
4. Report findings first, ordered by severity. Include file paths and line numbers.
5. If there are no findings, say so and call out any remaining test gaps.
Do not edit files unless the user explicitly asks for a fix.
Run it from Claude Code with:
/review-route app/api/users/route.ts
Claude replaces $ARGUMENTS with whatever you pass after the command and in this case it is the path to review.
The two metadata fields shape how the command behaves:
disable-model-invocation: truemeans only you can trigger this skill. Claude won't start it on its own. That's a sensible default for deliberate actions like review, release, or deployment.allowed-toolspre-approves specific tools for the skill's turn. Keeping this list narrow avoids broad permission grants while still skipping the usual approval prompts.
The result is a command with a clear boundary: it reads and reports, but it never quietly changes code.
Choose where a skill lives
Where you put a skill determines who can use it. Pick the smallest scope that makes the workflow useful.
| Location | Who can use it | Example |
|---|---|---|
~/.claude/skills/<name>/SKILL.md | You, in every local project | Your personal changelog workflow |
.claude/skills/<name>/SKILL.md | Everyone working in this repository | A project-specific test or review routine |
<plugin>/skills/<name>/SKILL.md | Users who enable the plugin | A reusable organization or tool integration |
For team workflows, commit project skills to the repository. A new teammate gets the command alongside the codebase, rather than stumbling across it in an onboarding doc.
Claude Code also finds skills in nested directories. In a monorepo, apps/web/.claude/skills/deploy/SKILL.md can define a deployment procedure specific to the web app without making it the default for every package.
Give commands useful inputs
$ARGUMENTS is the simplest way to pass input. Everything you type after the command name gets substituted in. When a command takes multiple distinct values, you can name them instead.
Here's a command that drafts a release note from a commit range:
.claude/skills/release-note/
└── SKILL.md
---
description: Draft a customer-facing release note from a Git revision range.
argument-hint: <from-ref> <to-ref>
arguments: [from_ref, to_ref]
disable-model-invocation: true
allowed-tools: Bash(git log:*) Bash(git show:*) Read
---
Create a release note from `$from_ref` through `$to_ref`.
1. Inspect the commits and changed files in that range.
2. Group user-visible changes into short sections.
3. Omit internal refactors unless they affect behavior, reliability, or performance.
4. Write plainly and do not claim an outcome the changes do not support.
5. Finish with a brief list of items that need product or engineering confirmation.
Run it with:
/release-note v2.3.0 HEAD
With named arguments, $from_ref gets the first value and $to_ref gets the second. You can also reference positional values directly with $0, $1, or $ARGUMENTS[0]. For arguments with spaces, quote them the same way you would in a shell:
/release-note "release/July fixes" HEAD
The argument-hint field isn't just decoration. It is what appears in the slash-command picker before someone runs the command, so make it descriptive.
Keep the prompt small and the procedure concrete
Think of a skill as an operating procedure, not a policy document. It's a prompt that's active only for its own turn, so every line should earn its place.
A well-written skill tells Claude what output to produce, which files or facts to check before making a claim, the order of steps and any non-negotiable checks, and when to stop and ask before proceeding.
Don't repeat things that belong in CLAUDE.md, like your package manager, architecture, or coding conventions. Those are durable project context. A skill is for a specific task with a clear start and end.
For longer reference material, keep it in the skill folder rather than pasting it into SKILL.md:
.claude/skills/onboard-api/
├── SKILL.md
├── examples.md
├── api-conventions.md
└── scripts/
└── verify-contracts.sh
Point to those files from SKILL.md and say when to read or run them. Claude loads the reference only when it needs it, keeping the command focused at the start.
Decide who may invoke the skill
By default, both you and Claude can invoke a skill. Claude uses the description field to recognize when a skill might be relevant and can apply it automatically.
That's useful for background knowledge. For example, an api-conventions skill that describes how the project structures errors and pagination can be picked up by Claude as it works without you having to ask.
For anything with side effects or that needs deliberate timing, restrict it to human-only:
disable-model-invocation: true
Setting disable-model-invocation: true makes it so claude won't trigger the skill on its own, but it still shows up in the / menu when you want it. Use this for commands like /deploy, /commit, /publish, or anything that calls an external service.
The opposite control is useful for pure reference material you don't want cluttering the menu:
user-invocable: false
This hides the skill from the slash-command picker while still letting Claude load it when relevant.
Test it in a real task
You don't need to restart Claude Code to pick up edits to an existing skill directory. Simply make the change, invoke the command, and see what happens.
For testing make sure you tests with inputs that stress the instructions. These may include:
- a path that doesn't exist
- an ambiguous or underspecified request
- a repository with no changes
- an argument that contains spaces or punctuation
If the output is too vague, add an explicit format. If it reads too much code, say where to start and what counts as enough evidence. If it does something you didn't intend, narrow the permissions, add a confirmation step, or restrict it to user-only invocation.
The best skills are focused. They encode one repeatable way of working, leave room for judgment, and make the cautious choice the easy one.
How to migrate an older command
For existing commands in .claude/commands/ they will continue to work as-is. If a command is just a short prompt, there's no need to upgrade it to a skill.
Consider migrating to a skill folder when you need supporting files, better discoverability via a description, or invocation controls. The migration is mostly a rename:
.claude/commands/review-route.md
↓
.claude/skills/review-route/SKILL.md
Note: When there is a command and a skill that has a the same name, skill takes precedence.