Back to blog
Tutorials

Creating custom Slash Commands in Claude Code

Bruno Bracaioli
Creating custom Slash Commands in Claude Code

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.

Compartilhar:

Fique por dentro

Receba novos artigos sobre IA, desenvolvimento e tecnologia direto no seu email.