A custom slash command is a Markdown file Claude Code expands into a prompt when you type its name. This lab puts six commands in .claude/commands/, shows how arguments and front matter work, and keeps them off the bundled /review alias. Daily flags and memory files are in the Claude Code cheat sheet.

Project commands and personal commands

Custom commands were merged into skills. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy. Existing command files keep working. Skills add a folder for helper scripts and a few fields command files ignore. Use a command file when the whole workflow fits in one Markdown file. Use a skill when you need those extra files.

Scope Path Loads in
Project .claude/commands/<file>.md in the repo Sessions in this repository. Commit the file
Personal ~/.claude/commands/<file>.md All of your projects on this machine

The directory reference lists commands/*.md as both project and global, same as skills. Global files live under ~/.claude/. On Windows that directory is %USERPROFILE%\.claude.

When two definitions share a command name, resolution follows skills:

Conflict What /name runs
Personal and project The personal one
A skill and a command file The skill
Your skill and a bundled skill Your skill replaces the bundled command, and bundled aliases stay on the original
Your skill and a built-in command In a local terminal, your skill replaces the built-in command, and built-in aliases stay

/review is an alias of bundled /code-review. A project skill named code-review replaces /code-review only. Typing /review still runs the bundled review. The review command in this lab is /team:review so the name is unambiguous.

Command files are not watched inside directories you added with --add-dir. Restart the session after you edit one there. Files in the project .claude/commands/ you started in load with the session.

Cloud sessions do not read ~/.claude/skills/ from your laptop. A personal command under ~/.claude/commands/ is a local-terminal tool. Commit project commands when the team should share them.

Arguments

Everything after the command name is the argument string.

Placeholder Expands to
$ARGUMENTS The full string as typed. If the file never reads arguments, Claude Code appends an ARGUMENTS: line anyway
$ARGUMENTS[0], $0 First argument
$ARGUMENTS[1], $1 Second argument

Quoting is shell-style. /explain "session cookie" src/auth sets $0 to session cookie and $1 to src/auth. $ARGUMENTS stays the raw text, quotes included as you typed them.

argument-hint is only the autocomplete hint. It does not parse anything.

argument-hint: "[path]"

A value the user types that itself contains $1 or $ARGUMENTS is inserted as literal text. Claude Code does not expand placeholders inside the argument.

Front matter that changes behavior

Command files accept skill front matter except name and paths. The command you type comes from the file path. A name key in a command file is ignored.

Field What to use it for
description One line. Claude can match this and load the command when disable-model-invocation is false
argument-hint Hint in the / menu, for example [path]
allowed-tools Tools that skip the permission prompt for the turn that invoked the command. Space-separated, comma-separated, or a YAML list
model Model for the rest of that turn. Same values as /model, or inherit. The session model returns on the next prompt
disable-model-invocation true hides the command from automatic use. You still run it with /name

allowed-tools does not remove other tools. It pre-approves the ones you list, then the grant ends when you send the next message. The command body stays in the conversation. Review this field before you trust a command someone else committed: a repository command can grant itself a wide Bash rule.

Set disable-model-invocation: true on anything with a side effect, including commit helpers and refactors. Leave it off only when you want Claude to fire the command because the description matched the chat.

model: haiku on an explain command keeps that turn on the smaller alias without changing /model for the session. An alias your organization has blocked is skipped and the session model stays.

Namespacing with subfolders

A file in a subdirectory of .claude/commands/ gets a colon command. Each folder segment becomes a : segment, then the file name without .md.

File Command
.claude/commands/explain.md /explain
.claude/commands/team/review.md /team:review
.claude/commands/frontend/component.md /frontend:component

The same rule applies under ~/.claude/commands/. Use a folder when the short name is already a built-in or a bundled alias. Plugin commands add the plugin name in front, such as /my-plugin:db:migrate, which is a separate namespace from your project folders.

Six commands you can copy

Create the folder, then one file per section. Each command sets disable-model-invocation: true so it runs when you type it.

mkdir -p .claude/commands/team

Review: /team:review

File: .claude/commands/team/review.md

---
description: Review the current diff for bugs, missing tests, and risky config
argument-hint: "[optional path or topic]"
disable-model-invocation: true
allowed-tools: Read, Grep, Glob, Bash(git status *), Bash(git diff *), Bash(git log *)
model: sonnet
---

Review the working tree. Stay inside $ARGUMENTS when that text names a path or topic.
Otherwise review the full diff.

Read `git status`, `git diff`, and the last five commits for style.
Report only issues you can point at with a file and a reason.
Group findings as blocking, should-fix, and optional.
Do not edit files. Do not propose a commit.

Run /team:review or /team:review src/billing. The bundled /review command is unchanged.

Test: /test

File: .claude/commands/test.md

---
description: Run the project tests and summarize failures
argument-hint: "[optional test path or name]"
disable-model-invocation: true
allowed-tools: Read, Grep, Glob, Bash(npm test*), Bash(pytest*)
---

Run the tests. If $ARGUMENTS is non-empty, pass it through as a path or a test name filter.
Prefer the runner this repo already uses. Read the README or package manifest before inventing a command.

When something fails, quote the assertion and name the file.
When everything passes, say so in one line and stop.

/test runs the suite. /test tests/test_auth.py narrows it. This command asks Claude to run tests. A hook that runs them after every edit is a different mechanism, covered in hooks.

Commit message: /commit-msg

File: .claude/commands/commit-msg.md

The command drafts a message. It does not grant git commit.

---
description: Draft a commit message from the current diff
argument-hint: "[optional scope hint]"
disable-model-invocation: true
allowed-tools: Bash(git status *), Bash(git diff *), Bash(git log *)
model: haiku
---

Look at status, the unstaged and staged diff, and recent commit subjects.
Write one commit message.

Subject: imperative, 72 characters or fewer.
Body: only if the diff needs a reason that the subject cannot carry.
Use this scope hint when it is present: $ARGUMENTS

Print the message in a single fenced block.
Do not stage files. Do not create a commit.

/commit-msg auth nudges the subject toward that area. Copy the block into git commit yourself, or ask in a follow-up message if you want Claude to commit after you have read the message.

Explain: /explain

File: .claude/commands/explain.md

---
description: Explain a file, symbol, or diff in plain language
argument-hint: "[path or symbol]"
disable-model-invocation: true
allowed-tools: Read, Grep, Glob
model: haiku
---

Explain $ARGUMENTS.

Start with what it does in two sentences.
Then the inputs and outputs, then one sharp edge a caller can hit.
Quote short snippets. Link symbols to the file you read.
If $ARGUMENTS is empty, ask which file to open.

/explain @src/worker.py still works because @ is the usual file mention from the cheat sheet. $ARGUMENTS receives the text you typed after /explain.

Refactor: /refactor

File: .claude/commands/refactor.md

---
description: Refactor a named file or symbol without changing behavior
argument-hint: "[path or symbol]"
disable-model-invocation: true
allowed-tools: Read, Grep, Glob, Edit, Write, Bash(npm test*), Bash(pytest*)
model: sonnet
---

Refactor $ARGUMENTS. Keep behavior the same.

Before editing, state the change in three lines: what moves, what stays, how you will check.
Touch only the files required for that change.
After editing, run the smallest test command that covers the change.
If you cannot find a test, say so and stop before a wide rewrite.

The allowed-tools grant lasts for the turn that started with /refactor. The next message asks for permission again under your normal rules.

Docs: /docs

File: .claude/commands/docs.md

---
description: Update the docs that match a code change
argument-hint: "[path or topic]"
disable-model-invocation: true
allowed-tools: Read, Grep, Glob, Edit, Write
model: haiku
---

Update documentation so it matches the current code for $ARGUMENTS.

Prefer an existing doc file over a new one.
Describe the behavior a caller can observe.
Do not add a changelog entry unless the repo already keeps one next to this feature.
If code and docs disagree, trust the code and say which line you used.

A ! line inside the file

Interactive shell mode, the ! you type in the prompt, is separate from this. A line in a command file that starts with ! followed by a command in backticks runs while the command is expanded. Claude sees the command output, not the command text.

Current status:
!`git status --short`

That injection runs through the shell tool, and your permission rules still apply. Set disableSkillShellExecution to true in settings when policy should replace those lines with a disabled notice. Skills synced from a claude.ai account do not run these commands on your machine.

Use injection when the prompt is useless without live data, such as git diff. Use allowed-tools plus instructions when Claude should choose the command.

When a command is the wrong tool

A command loads its body into the main conversation and leaves it there. That is what you want for a checklist you will keep discussing.

Move the work to a subagent when the exploration would flood the chat with search hits. Move it to a hook when it must run on every edit whether or not someone remembers the slash command. Standing facts that belong in every session stay in CLAUDE.md, which the cheat sheet lays out. A command is one reusable procedure inside a longer agentic session, not a second memory file.

After you add the files, open a new prompt and type / then team to confirm /team:review is listed. If a command is missing, the session was started in bare mode or with project settings turned off, or the file name collides with a reserved built-in. Rename it or put it in a subfolder.

FAQ

Where do custom Claude Code slash commands go?

Put a Markdown file in .claude/commands/ to share it with the repo, or in ~/.claude/commands/ to use it in every project on your machine. The file name becomes the command. On Windows, ~/.claude is %USERPROFILE%\.claude. A skill directory at .claude/skills/<name>/SKILL.md creates the same kind of /name command and wins if both exist.

How do I pass arguments to a Claude Code slash command?

Text after the command name is the argument string. In the file, $ARGUMENTS expands to the whole string. $0 or $ARGUMENTS[0] is the first word, and $1 is the second. Wrap a multi-word value in quotes when you invoke the command. argument-hint in the front matter is the autocomplete hint, such as [path].

What is the difference between a project command and a user command?

A file under the repository .claude/commands/ is project scope and is meant to be committed. A file under ~/.claude/commands/ is personal and loads in all of your local projects. Commands use the same mechanism as skills: a personal definition outranks a project definition when the command name matches, and a skill outranks a command file with the same name.

Why does my /review command still run the built-in review?

/review is the alias of the bundled /code-review skill. A custom skill named code-review replaces /code-review and does not replace that alias. Name your checklist something else, or put it in a subfolder so the command is /team:review.

Which front matter keys does a command file accept?

Command files accept the skill fields except name and paths, which are ignored. The useful ones are description, argument-hint, allowed-tools, model, and disable-model-invocation. You invoke the file by its path under commands/, not by a name key.

How this guide was verified

Written by hand from the official documentation, every command re-checked, and reviewed a second time before publishing. Last reviewed on .

Official sources read for this article

Share.

Haythem Rehouma builds and teaches DevOps and AI tooling: Kubernetes, Docker, Terraform, Claude Code, ChatGPT and n8n. Every KubPoint guide is written from the official docs and re-tested before it goes live.

Comments are closed.