Claude Code slash commands, custom commands, and how skills fit in
Which Claude Code slash commands are worth learning, how custom commands relate to skills, and why a command can fail to show up or run.
Claude Code slash commands are the things you type after / at the prompt. Some are built in (/skills, /doctor, /context, /reload-skills). Others are yours: a skill folder or a file in .claude/commands/ becomes a /name command you can run on demand.
The short version of the custom side: skills are the current way to build custom commands. A skill is a SKILL.md in a skills directory, and /name runs it. Old command files in .claude/commands/ still load, but if a skill and a command file share a name, the skill wins. I'd write new things as skills.
What slash commands are in Claude Code#
There are four kinds of thing you can type after /, and the / menu mixes them together:
- Built-in commands, like
/doctoror/skills. These ship with Claude Code. The full list lives on the commands reference page. - Bundled skills, like
/verify,/simplify, and/code-review. They behave like commands but are skills under the hood. - Your own skills and command files, from the locations covered below.
- Plugin skills and MCP prompts. Plugin skills are namespaced as
/plugin-name:skill-name, and MCP prompts show up as commands too.
That last point explains most confusion. When people ask about "slash commands vs skills," they're usually looking at one menu that holds both.
Built-in commands worth knowing#
I'm not going to list every built-in here, because the reference page does that better and changes with releases. These are the ones the documentation ties to day-to-day setup problems, so they're the ones I'd learn first.
| Command | What it does |
|---|---|
/skills |
Lists the skills Claude Code loaded. Synced claude.ai skills appear under claude.ai sync, and a note explains any synced skill that lost its short name. |
/reload-skills |
Picks up skills in a top-level skills directory that didn't exist when the session started. |
/reload-plugins |
Applies changes to hooks/, .mcp.json, agents/, and output-styles/ in a skill folder that's also a plugin. |
/context |
Shows what's loaded. Synced skills are grouped under claude.ai sync here too. |
/doctor |
The in-session setup checkup, which can also apply fixes. |
/import |
Brings configuration from other coding agents into Claude Code. Takes --dry-run and --yes. |
/login |
Signs in. Skill syncing only starts after a restart if you sign in mid-session. |
/usage |
Usage info. /cost is a built-in alias for it. |
/code-review |
Bundled skill. /review is its alias. |
/verify and /simplify |
Bundled skills. /verify records a recipe at your repo root as a project skill. |
Two things from that table matter later. Aliases are separate names, and overriding a command doesn't override its aliases.
Outside a session, there's also a shell-side counterpart for a few of these. claude doctor prints read-only diagnostics without starting a session, and claude import codex --dry-run starts a session that runs /import. Both are in the CLI reference.
How to create a custom slash command#
The smallest version is a skill folder with a SKILL.md inside. Skills load from four places:
| Location | Path |
|---|---|
| Enterprise | Set by your organization |
| Personal | ~/.claude/skills/ |
| Project | .claude/skills/ in the repo |
| Additional directory | .claude/skills/ inside a directory you pass with --add-dir |
Here's a project skill. Put it at .claude/skills/release-notes/SKILL.md:
---
name: release-notes
description: Draft release notes from the commits since the last tag
---
Look at the commits since the most recent git tag.
Group them into Features, Fixes, and Internal.
Write the notes as a short markdown list.
Type /release-notes and it runs. The frontmatter name field sets the command name. If you leave it out, the folder name is what gets used for the command. For the exact precedence between the two, see "How a skill gets its command name" on the slash commands page.
You don't need to restart. Claude Code watches the skill directories (except in bare mode) and picks up adds, edits, and removals in the running session. The exception is a top-level skills directory that didn't exist when the session began. For that, run /reload-skills, and run it again after each later change there.
Keep Claude from running it on its own#
Some skills should only fire when you type the command. A deploy skill is the obvious case. Add disable-model-invocation: true to the frontmatter:
---
name: deploy
description: Deploy the current branch to staging
disable-model-invocation: true
---
Run the staging deploy steps for this repo.
This is documented as a way to stop Claude from invoking a skill. It has a side effect worth knowing: the commit-time check described below only applies to skills Claude can invoke.
One gap: the portion of the docs I worked from doesn't cover passing arguments to a command. If you need that, read the full slash commands page rather than guessing at a placeholder syntax.
Slash commands vs skills#
The two overlap enough that the old distinction mostly doesn't matter in practice:
- A file in
.claude/commands/still works as a command. - A skill with the same name as that file wins.
- Both can be invoked by name with
/name. - Skills get extras that a bare command file doesn't have in the docs: live change detection on
SKILL.md, enterprise and personal scoping, and thedisable-model-invocationcontrol.
My advice: leave existing command files alone until you have a reason to touch them, and write anything new as a skill. If you rename a command file into a skill folder with the same name, nothing breaks, because the skill simply takes over.
Which command runs when names collide#
This is where "my command does the wrong thing" comes from. The documented rules:
| Same name in | Which one runs |
|---|---|
| Enterprise, personal, project | Enterprise over personal, personal over project |
| Your skill and a bundled skill | Your skill replaces the bundled command, but not its aliases |
| Your skill and a built-in command | In a local terminal session, your skill replaces the built-in, but not its aliases |
A skill and a .claude/commands/ file |
The skill |
| Plugin skill and anything else | Both load, since the plugin one is /plugin-name:skill-name |
The docs give two concrete cases. With deploy in both ~/.claude/skills/ and the project's .claude/skills/, /deploy runs the personal one. A project usage skill replaces /usage, but /cost still runs the built-in.
Here's that logic as a runnable sketch, so you can try your own combinations. It only models the enterprise/personal/project ordering and the skill-over-command-file rule from the table.
ORDER = ['enterprise', 'personal', 'project']
def winner(where):
# where: set of places the same name exists
for place in ORDER:
if place in where:
return place + ' skill'
if 'commands-file' in where:
return '.claude/commands file'
return 'nothing'
cases = [
{'personal', 'project'},
{'project', 'commands-file'},
{'commands-file'},
{'enterprise', 'personal', 'project'},
]
for c in cases:
print(sorted(c), '->', winner(c))
Slash commands not showing or not working#
Work through these in order. They're all taken from documented behavior.
- You made a new top-level skills directory mid-session. Claude Code wasn't watching it. Run
/reload-skills. - Another command took the name. A built-in, bundled skill, plugin skill, file in
.claude/commands/, or MCP prompt can hold the short name. Run/skillsand read the note under the list. - It's a synced claude.ai skill that lost its short name. Then it only runs as
/anthropic-skills:<name>. A localdeployand a synceddeploymeans/deployruns the local one. - You used a reserved name.
anthropic-skills, and anything inside that namespace, is reserved. A skill folder, frontmattername, or.claude/commands/entry using it doesn't load, and a startup notice names the first thing to rename. - An MCP server is named
anthropic-skills. Its tools work, but its prompts don't appear as commands. Rename the server. - Skill changes in a plugin folder. Changes to
hooks/,.mcp.json,agents/, andoutput-styles/need/reload-plugins. Live detection only coversSKILL.mdtext. - You're in a cloud session, Cowork, or a routine. These don't read
~/.claude/skills/on your machine. Commit the skill to the repo's.claude/skills/, or enable it for your claude.ai account. Desktop scheduled tasks run locally, so they do load personal skills. - Case or look-alike names. Name comparison ignores case, spacing, and invisible characters, so
Commitandcommitcount as the same. A look-alike letter from another alphabet counts as different.
Synced skills also behave differently from local ones. In sessions on your machine, a synced skill's ! command lines and @ references reach Claude as literal text instead of running. If a skill you downloaded behaves oddly, check that first.
Common mistakes#
- Overriding a command and expecting the alias to follow. It doesn't. Your
usageskill won't catch/cost. - Editing files under
~/.claude/skills/synced/. Syncing only downloads. Your edits aren't saved to claude.ai, and a later sync can overwrite or remove them. Change the skill on claude.ai. - Assuming plugin, bundled, or claude.ai skills trigger the commit check. They don't. Only skills from enterprise, personal, project, or additional-directory locations (or a
.claude/commands/file) count. - Using
disable-model-invocation: trueand expecting commit checks. If Claude can't invoke the skill, it doesn't get the instruction. - Expecting sync in an API-key session. Syncing needs a claude.ai sign-in from
/loginand feature flag fetching. Sessions using an API key, Bedrock, bare mode, or--safe-modedon't sync.
Run your checks before each commit#
There's one place where a command name has a special effect. If a skill named verify or simplify is in place when a session starts, Claude Code's commit instructions tell Claude to run it right before each commit, except for changes to docs or tests. It needs Claude Code v2.1.286 or later, and includeGitInstructions can't be turned off. The recipe that /verify writes at your repo root is a project skill, so it qualifies. The bundled /verify and /simplify don't.
Quick reference#
- Custom command =
SKILL.mdin~/.claude/skills/<name>/or.claude/skills/<name>/. - Old
.claude/commands/files still work; a same-named skill beats them. - Name comes from frontmatter
name; setdisable-model-invocation: trueto keep Claude from invoking it. - Edits are picked up live. A brand-new top-level skills directory needs
/reload-skills. - Missing command? Run
/skillsand read the note under the list. - Enterprise beats personal, personal beats project.
- Overriding a command never overrides its aliases.
- Cloud and Cowork sessions don't read
~/.claude/skills/.
Quick answers
Are Claude Code custom slash commands the same as skills?
Close enough. A skill folder with a SKILL.md becomes a /name command, and old .claude/commands/ files still work. If a skill and a command file share a name, the skill runs.
Why is my Claude Code slash command not showing?
Most often the skills directory is brand new, so run /reload-skills. Otherwise another command may own the name, so run /skills and read the note under the list.
Where do I put a custom slash command?
For yourself, use ~/.claude/skills/<name>/SKILL.md. For a repo, use .claude/skills/<name>/SKILL.md. Enterprise and --add-dir locations also load.
Can I stop Claude from running a skill on its own?
Yes. Add disable-model-invocation: true to the skill's frontmatter. You can still run it by typing the command.
Next note