
Why create your own /command?
Slash commands are the lowest-friction, highest-return investment in Claude Code. Five minutes to write a markdown file save 30 seconds per invocation — and when you invoke ten times a day, every day, the math pays off in the first week.
This article is a step-by-step tutorial. I'll assume you already know the difference between slash commands and skills — if not, take a detour through Slash Commands and Skills: customizing your Claude Code workflow first. Here the focus is practical: create, test, debug and share your first command.
Where the files live
Slash commands are markdown files in one of three folders:
| Scope | Path | When to use |
|---|---|---|
| Project | .claude/commands/ | Versioned commands, shared with the team |
| Personal | ~/.claude/commands/ | Your own shortcuts, across every project |
| Plugin | ~/.claude/plugins/<name>/commands/ | Distributed as a plugin |
The file name becomes the command name. .claude/commands/deploy.md shows up as /deploy. You can nest folders to create namespaces: .claude/commands/git/review.md becomes /git:review. Namespaces help when you have more than 10 commands — autocomplete groups them by prefix.
If this is your first time creating anything under .claude/, the folder probably doesn't exist. Create it manually with mkdir -p .claude/commands and start with your first file.
The minimum viable file
A slash command doesn't even need frontmatter. The simplest markdown file already works:
Run the tests with `npm test` and show me which ones failed. Don't try to fix anything yet — just report.
Save that as .claude/commands/test-report.md and type /test-report at the prompt. Claude Code injects the content as if you had pasted it manually. That's already a slash command.
From there, you can enrich it. Frontmatter gets you three useful things:
---
description: Run tests and report failures without trying to fix them
argument-hint: "[optional pattern e.g. auth.test]"
allowed-tools: Bash(npm test*), Read, Grep
---
Run `npm test ${ARGUMENTS:-}` and report only which tests failed. Use Read and Grep to show the relevant lines. Do not edit anything.
The three important fields:
description— shows up in autocomplete when you type/. Keep it short and imperative.argument-hint— the hint shown next to the command while you type. Optional, but it helps you remember what the command takes.allowed-tools— restricts which tools the agent can use while the command is active. Useful for "safe" commands that should not edit files.
Arguments: passing context
When you type /test-report auth, the text auth is available as an argument. There are two ways to reference it:
$ARGUMENTS— the entire string after the command name.$1,$2,$3— positional arguments separated by spaces.
Use $ARGUMENTS when the input is free text (a message, a query). Use $1, $2 when you expect fixed positions (a file and a function, for example). The ${ARGUMENTS:-default} syntax accepts a fallback when nothing is passed — useful for commands that run with or without a filter.
Example 1: a real /commit
One of the first commands worth writing is a standardized /commit. Save this at .claude/commands/commit.md:
---
description: Analyze the staged diff and create a conventional commit
argument-hint: "[optional scope]"
allowed-tools: Bash(git *)
---
Run `git status` and `git diff --cached` in parallel to understand what's staged.
Analyze the changes and draft a commit message following Conventional Commits:
- Type: feat, fix, refactor, docs, test, chore, perf
- Scope: ${1:-auto-detect}
- Description: imperative, 1 line, max 72 chars
If there are changes that don't fit a single type, stop and show me — I'll split the commits manually.
Then create the commit using HEREDOC to preserve formatting. Do not use --amend. Do not skip hooks.
Type /commit and the agent reads the diff, picks the type, writes the message and creates the commit. In five lines of config, you've encoded your team's convention.
Example 2: /review-pr
Another classic — reviewing a PR without opening the browser:
---
description: Review a GitHub PR by number
argument-hint: "<PR number>"
allowed-tools: Bash(gh *), Read, Grep
---
Fetch PR #$1 from the current repository:
1. `gh pr view $1 --json title,body,files,additions,deletions`
2. `gh pr diff $1`
Read the diff with a senior code-reviewer's critical eye. For every issue you find, report:
- File and line
- What is wrong
- Suggested fix (do not edit — just suggest)
If everything looks fine, say explicitly "looks good to merge".
Invoke with /review-pr 123. The agent fetches the PR, reads the diff and returns a text review. You compare it with what you've already seen and make the call.
Debugging when the command doesn't work
Three common traps in the beginning:
1. The command doesn't show up in autocomplete. Almost always a wrong path. Confirm .claude/commands/<name>.md (project) or ~/.claude/commands/<name>.md (personal). Then restart Claude Code if it was already open — it loads the list at start.
2. The argument is not being interpreted. If you used $ARGUMENTS but it's empty, the argument probably got stuck to the command name. It should be /test-report auth, not /test-reportauth.
3. The command seems ignored. If you wrote a very long command mixing conflicting instructions, the agent may prioritize the user prompt over the injected content. Keep each command with a single intent — if you need two behaviors, make two commands.
Sharing with the team
The beauty of project slash commands is that they're versioned. When you commit .claude/commands/commit.md, every new developer on the repo inherits the command automatically. That solves a classic problem: you teach the convention once, in the file, and it starts being executed by the agent of someone who never read it.
A good first commit is creating 3-5 team commands and a short README.md inside .claude/commands/ explaining what each one does. For a personal arsenal beyond the team commands, it's worth investing in the strongest skills — see 10 essential Skills for Claude Code productivity for ready ideas. And when you notice that a ritual gets too big for a single slash command, it's a sign it became a subagent or a skill — worth the comparison before inflating the file.
Next steps
Start now: create .claude/commands/commit.md with the example above, commit it to the repo, and use it for three days. On the next big task, combine that slash command with plan mode turned on — it's the pairing that most accelerates real work. When you want the complete view of the ecosystem and where slash commands fit, go back to the definitive guide to Claude Code.


