Claude Code Slash Commands: Build Custom Commands
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-prioritysubstitutes4127 high-prioritywherever$ARGUMENTSappears.$1,$2,$3— positional arguments, split on whitespace, just like shell parameters. This lets you treat inputs individually, for example$1for an issue number and$2for 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 requiresBashin yourallowed-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 issuesfeeds 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:
| Mechanism | Trigger | Context | Best for |
|---|---|---|---|
| Slash command | You type /name | Runs in the current conversation | On-demand, repeatable prompts you fire manually |
| Subagent | Delegated automatically or by request | Separate, isolated context window | Specialized roles and long tasks that shouldn't clutter your main thread |
| Hook | Lifecycle event (e.g. before a tool runs) | Shell command the harness executes | Automatic 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:
- git/create-pr — turn the current branch into a well-written pull request.
- testing/generate-unit-tests — scaffold tests for a file or module.
- documentation/update-readme — regenerate a README from the current codebase.
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.