Claude Code

Claude Code Slash Commands: Build Custom Commands

8 min read

If you find yourself typing the same multi-step instructions into Claude Code over and over — "check the diff, write a conventional commit, open a PR" — a slash command turns that whole prompt into a single keystroke. Slash commands are the simplest way to codify a repeatable workflow, and because they are just Markdown files, they are trivial to write, version, and share across a team. This guide covers what they are, the exact file format, how arguments work, when to reach for a command instead of a subagent, and how to install ready-made ones in seconds.

What are Claude Code slash commands?

A slash command is a reusable prompt template you invoke by typing /name in the Claude Code session. Instead of retyping a detailed instruction every time, you save it once and Claude expands it inline when you call it. Claude Code ships with built-in commands like /init, /review, and /clear, but the real power is defining your own.

Think of a command as a parameterized prompt. It runs in your current conversation context, so it can see the files you have already discussed and build on the work in progress. That makes commands ideal for on-demand, human-triggered actions: you decide exactly when to fire them. Good candidates include:

  • Generating a commit message or opening a pull request
  • Scaffolding a component, route, or test file from a convention
  • Running a security or accessibility pass over the current changes
  • Refactoring a file to match your house style
  • Writing or updating documentation for the code you just changed

Browse the full Claude Code commands catalog to see how these patterns are structured in practice.

Where commands live: the .claude/commands folder

Claude Code discovers commands from two locations, and the folder decides the command's scope:

  • Project commands live in .claude/commands/ inside your repository. Commit them and every teammate gets the same commands. These are marked as "project" in the command list.
  • Personal commands live in ~/.claude/commands/ in your home directory. They follow you across every project and are marked "user".

The rule is simple: one Markdown file equals one command, and the filename is the command name. A file at .claude/commands/create-pr.md becomes /create-pr. Subdirectories act as namespaces for organization — a file at .claude/commands/git/create-pr.md is grouped under git in the command list, which keeps a large collection tidy without changing how you invoke it.

Anatomy of a command file

A command file has two parts: optional YAML frontmatter for configuration, and a Markdown body that becomes the prompt. Here is a complete, realistic example you might save as .claude/commands/git/create-pr.md:

---
description: Create a pull request from the current branch
argument-hint: [base-branch]
allowed-tools: Bash(git:*), Bash(gh:*)
model: claude-opus-4-8
---

## Context
- Current branch: !`git branch --show-current`
- Working tree: !`git status --short`
- Commits vs ${1:-main}: !`git log --oneline ${1:-main}..HEAD`

## Task
Open a pull request targeting the `$1` branch (default to `main`).
Write a clear title and a concise body that summarizes the changes,
lists any breaking changes, and notes how to test. Use `gh pr create`.

The frontmatter keys are all optional but worth knowing:

  • description — a short summary shown in the command menu and autocomplete.
  • argument-hint — placeholder text that hints at the expected arguments during autocomplete.
  • allowed-tools — restricts which tools the command may use. Scoping to Bash(git:*) lets it run git without prompting for unrelated commands.
  • model — pin a specific model for this command if it needs more or less horsepower than your default.

Everything below the frontmatter is the prompt. Write it the way you would brief a capable teammate: clear context first, then the task.

Passing arguments to commands

Commands become far more useful when they accept input. Claude Code gives you two ways to capture what the user types after the command name:

  • $ARGUMENTS — captures the entire argument string as one blob. Calling /fix-issue 4127 high-priority substitutes 4127 high-priority wherever $ARGUMENTS appears.
  • $1, $2, $3 — positional arguments, split on whitespace, just like shell parameters. This lets you treat inputs individually, for example $1 for an issue number and $2 for a label.

A minimal argument-driven command at .claude/commands/fix-issue.md could be as short as:

---
description: Investigate and fix a GitHub issue by number
argument-hint: [issue-number]
---
Find issue #$1, reproduce the bug, propose a fix, and add a
regression test. Explain the root cause before you edit any code.

Positional parameters also support shell-style defaults inside bash lines, as in ${1:-main} from the earlier example, which falls back to main when no branch is passed.

Running bash and referencing files

Two features turn a static template into a dynamic one:

  • Inline bash — a line prefixed with ! runs a shell command before the prompt is sent, and its output is injected into the context. This requires Bash in your allowed-tools. It is how the PR example above pulls in the live branch name and diff.
  • File references@ followed by a path embeds that file's contents. For instance, Review @src/auth/session.ts for security issues feeds the file straight into the prompt without a separate read step.

Together these let a command gather its own context, so the person invoking it does not have to paste anything in.

Commands vs subagents vs hooks

Commands are one of several ways to extend Claude Code, and picking the right one matters. Here is the quick comparison:

MechanismTriggerContextBest for
Slash commandYou type /nameRuns in the current conversationOn-demand, repeatable prompts you fire manually
SubagentDelegated automatically or by requestSeparate, isolated context windowSpecialized roles and long tasks that shouldn't clutter your main thread
HookLifecycle event (e.g. before a tool runs)Shell command the harness executesAutomatic enforcement like formatting or blocking risky edits

Reach for a command when you want deterministic control over when something happens and the work should build on your current session. Reach for a subagent when a task deserves its own context window — a dedicated code reviewer that reads the whole diff without polluting your main thread is a classic case. Reach for a hook when the action must happen automatically on every matching event, no invocation required. Many strong setups combine all three.

Installing commands with npx

You do not have to write every command from scratch. ToolZip curates a searchable catalog of ready-to-install components, and each one drops into your project with a single command. To install a command, use the --command flag with a category/name path:

npx claude-code-templates@latest --command="git/create-pr" --yes

That writes the Markdown file into your .claude/commands/ folder, after which /create-pr is immediately available in your session. The same installer handles other component types by swapping the flag — --agent, --mcp, --setting, --hook, and --skill. A few commands worth starting with:

Explore the complete commands hub or the broader Claude Code catalog to find components that match your stack.

Best practices for writing commands

  • Keep each command focused. One clear job per file is easier to reason about and reuse than a sprawling do-everything prompt.
  • Always add a description. It is what you and your teammates see in the menu — vague descriptions make commands hard to find.
  • Scope allowed-tools tightly. Granting Bash(git:*) instead of all of Bash reduces permission prompts and limits blast radius.
  • Front-load context. Use inline bash and @ file references so the command gathers what it needs instead of relying on the user to paste it.
  • Commit project commands. Checking .claude/commands/ into git means the whole team shares one source of truth.
  • Name for discovery. Group related commands in subdirectories so a growing collection stays navigable.

Slash commands are the highest-leverage, lowest-effort way to make Claude Code fit your workflow. Start by installing one or two from the catalog, adapt them to your conventions, and graduate to writing your own once you see the pattern. Within a day you will have a personal library of one-keystroke workflows that used to take a paragraph of typing.

Browse Claude Code Commands

Reusable slash commands that automate repeatable prompts.

Open catalog →

Frequently Asked Questions

Where do I put custom Claude Code slash commands?
Project-level commands go in a .claude/commands/ folder at the root of your repository, which lets you commit them so the whole team shares the same commands. Personal commands go in ~/.claude/commands/ in your home directory and are available across every project. In both cases, each Markdown file is one command and the filename becomes the command name.
How do arguments work in a slash command?
You have two options. Use $ARGUMENTS to capture everything typed after the command name as a single string, or use positional parameters $1, $2, $3 to access individual whitespace-separated inputs. Positional parameters also support shell-style defaults like ${1:-main} inside inline bash lines.
When should I use a command instead of a subagent?
Use a slash command when you want to trigger a repeatable prompt manually and have it build on your current conversation. Use a subagent when a task deserves its own isolated context window or should be delegated automatically, such as a dedicated code reviewer that reads a full diff without cluttering your main session. Hooks are the third option for actions that must run automatically on lifecycle events.
Can a slash command run shell commands or read files?
Yes. A line prefixed with ! runs a bash command before the prompt is sent and injects its output into the context, provided Bash is listed in the command's allowed-tools frontmatter. A path prefixed with @ embeds that file's contents directly into the prompt, so the command can gather its own context.
How do I install a ready-made command from ToolZip?
Run npx claude-code-templates@latest --command="category/name" --yes, for example --command="git/create-pr". The installer writes the Markdown file into your .claude/commands/ folder and the command is available immediately. The same installer supports --agent, --mcp, --setting, --hook, and --skill for other component types.
What frontmatter fields can a command file include?
The common optional fields are description (a short summary shown in the menu), argument-hint (placeholder text for autocomplete), allowed-tools (restricts which tools the command may use, ideally scoped tightly like Bash(git:*)), and model (pins a specific model for that command). Everything below the frontmatter is the Markdown prompt itself.