·11 min read

Custom Slash Commands in Claude Code

Learn how to create custom slash commands in Claude Code. Build reusable workflows for code review, testing, and deployment with .claude/commands/.

Claude Code runs terminal commands, edits files, and navigates your codebase autonomously. But every developer has workflows they repeat daily: reviewing a PR, running a deploy sequence, generating tests for a new module. Typing those multi-line prompts over and over wastes time and introduces inconsistency.

Custom slash commands fix this. You write a markdown file, drop it in a directory, and Claude Code picks it up as a /command you can run anytime. This guide covers everything from your first command to parameterized templates and team-shared command libraries.

What are custom slash commands?

Slash commands are reusable prompts stored as markdown files. When you type / in Claude Code, it shows a list of available commands -- both built-in and custom. Your custom commands live in the .claude/commands/ directory inside your project.

Each command is a .md file. The filename becomes the command name. A file at .claude/commands/review.md becomes /review. A file at .claude/commands/gen-tests.md becomes /gen-tests.

When you invoke a command, Claude Code reads the markdown file and treats its contents as a prompt. Everything you can write in a normal Claude Code message works inside a command file: instructions, references to files, multi-step workflows, formatting requirements.

Setting up the commands directory

Start by creating the directory structure:

mkdir -p .claude/commands

This goes at the root of your project. If you already have a .claude/ directory (for your CLAUDE.md configuration or skills), you're adding a new subfolder inside it.

Your project structure will look like this:

project-root/
  .claude/
    CLAUDE.md              # Project instructions
    commands/              # Custom slash commands
      review.md
      deploy.md
      gen-tests.md
    skills/                # Installed skills
  src/
  package.json

Writing your first command

Create .claude/commands/review.md:

Review the current git diff for the following:

1. **Security issues**: SQL injection, XSS, command injection, exposed secrets
2. **Error handling**: Uncaught exceptions, missing try/catch, swallowed errors
3. **Type safety**: Any usage of \`any\`, missing return types, unsafe casts
4. **Performance**: N+1 queries, unnecessary re-renders, missing memoization
5. **Logic bugs**: Off-by-one errors, null reference risks, race conditions

Group findings by severity (critical, warning, suggestion). For each finding, include:
- The file and line number
- What the issue is
- A suggested fix

If there are no issues, say so explicitly.

Now type /review in Claude Code. It reads your diff, applies your checklist, and produces a structured review. Same quality every time, no matter how rushed you are.

Practical command examples

Deploy checklist

.claude/commands/deploy.md:

Run through this pre-deploy checklist:

1. Run the test suite and report any failures
2. Run the type checker and report any errors
3. Check for uncommitted changes in the working tree
4. Check that the current branch is up to date with origin
5. List any TODO or FIXME comments added in the current branch's diff

If all checks pass, summarize the deploy readiness. If any check fails, stop and report the failure with details.

Do NOT actually deploy -- just validate readiness.

This command replaces a mental checklist with an automated one. Every deploy gets the same verification, whether it's Monday morning or Friday at 5pm.

Test generation

.claude/commands/gen-tests.md:

Generate tests for the file I specify. Follow these rules:

- Use the existing test framework in this project
- Write unit tests, not integration tests
- Cover happy path, error cases, and edge cases
- Use descriptive test names that explain the expected behavior
- Mock external dependencies
- Follow the patterns in existing test files in this project

After generating tests, run them to verify they pass. Fix any failures.

Changelog entry

.claude/commands/changelog.md:

Look at all commits on the current branch that are not on main.

Write a changelog entry following this format:

## [version] - YYYY-MM-DD

### Added
- (new features)

### Changed
- (modifications to existing features)

### Fixed
- (bug fixes)

Infer the appropriate entries from the commit messages and diffs. Use clear, user-facing language -- not implementation details. Skip merge commits and chore commits.

Database migration review

.claude/commands/migration-check.md:

Find the most recent database migration file in the project. Review it for:

1. **Reversibility**: Can this migration be rolled back? Is there a down migration?
2. **Data safety**: Does it drop columns or tables that might contain data?
3. **Performance**: Will this lock large tables? Are there index additions on large tables?
4. **Compatibility**: Is this migration backwards-compatible with the current application code?

Flag any concerns and suggest safer alternatives where applicable.

Parameterized commands with $ARGUMENTS

Commands become more flexible with parameters. When a command file contains \$ARGUMENTS, Claude Code replaces that placeholder with whatever text you type after the command name.

Create .claude/commands/explain.md:

Explain the following code or concept in the context of this project:

\$ARGUMENTS

Break the explanation into:
1. **What it does** -- a plain-English summary
2. **How it works** -- step through the key logic
3. **Why it matters** -- how it fits into the broader architecture
4. **Gotchas** -- edge cases or non-obvious behavior to watch for

Now you can run:

/explain the authentication middleware in src/middleware.ts
/explain the caching strategy for API responses
/explain the database connection pooling setup

Each invocation gets the same structured format, but with different content.

More parameterized examples

Quick refactor (.claude/commands/refactor.md):

Refactor the following, keeping behavior identical:

\$ARGUMENTS

Rules:
- Do not change the public API or exports
- Do not change test behavior
- Run tests after refactoring to confirm nothing breaks
- Keep the diff minimal

Usage: /refactor the error handling in src/lib/api-client.ts to use Result types

Add documentation (.claude/commands/document.md):

Add JSDoc documentation to:

\$ARGUMENTS

Rules:
- Document parameters, return types, and thrown exceptions
- Add a brief description of what the function/class does
- Include one usage example in the JSDoc
- Do not change any code behavior

Usage: /document all exported functions in src/lib/auth.ts

Personal vs. project commands

Claude Code reads commands from two locations:

LocationScopeVisibility
~/.claude/commands/Personal (all projects)Only you
.claude/commands/Project (this repo)Everyone on the team

Personal commands are workflows specific to how you work. Maybe you have a particular way you like to review code, or a prompt for writing commit messages in your preferred style. These go in your home directory.

Project commands are workflows the whole team shares. The deploy checklist, the migration review, the test generator -- these should be consistent across all developers, so they live in the repo and get version-controlled with everything else.

When there's a name collision (same filename in both directories), the project command takes precedence. This lets teams override personal preferences with project standards where needed.

Organizing commands in subdirectories

As your command library grows, organize them into subdirectories:

.claude/commands/
  review.md
  deploy.md
  db/
    migration-check.md
    seed.md
  docs/
    api-docs.md
    changelog.md
  test/
    gen-tests.md
    coverage-report.md

Subdirectory commands are invoked with a colon separator. The file at .claude/commands/db/migration-check.md becomes /db:migration-check. This keeps the command list clean as your library grows.

Team-shared commands through version control

Since .claude/commands/ lives inside your project directory, commands are automatically version-controlled when you commit them. This gives you:

  • History: See when a command was added or changed, and why
  • Review: Command changes go through PR review like any other code
  • Consistency: Every developer on the team has the same commands
  • Rollback: Revert a command change if it produces worse results

Treat command files like code. When someone improves a review checklist or adds a new deploy check, it goes through the same PR process. This means your team's collective Claude Code knowledge accumulates in the repo rather than in individual developers' heads.

For conventions that span multiple projects, consider publishing your commands as skills on localskills.sh. A skill can include both instruction files and command templates, so your entire team workflow is installable with a single command. See how to publish your first skill for a walkthrough.

Writing effective commands

After building dozens of command files, these patterns produce the best results:

Be specific about output format

Bad:

Review the code.

Good:

Review the code. For each issue found, output:
- File path and line number
- Issue description (one sentence)
- Severity: critical | warning | suggestion
- Suggested fix (code snippet if applicable)

Claude Code follows formatting instructions closely. The more specific your template, the more consistent the output.

Include stop conditions

Commands should know when to stop:

Scan for unused exports in the src/ directory.

Stop conditions:
- Skip test files (*.test.ts, *.spec.ts)
- Skip files in src/generated/
- If more than 50 unused exports are found, report the first 50 and note the total count

Without stop conditions, commands can run longer than intended, especially on large codebases.

Reference project conventions

Link your commands to your project's rules:

Generate a new API route handler for the endpoint I describe.

Follow the conventions in CLAUDE.md and use src/app/api/users/route.ts
as the reference implementation. Match the error handling pattern,
response shape, and middleware chain exactly.

\$ARGUMENTS

This ties the command to your existing CLAUDE.md configuration, so the output stays consistent with the rest of your codebase.

Chain multiple steps

The most powerful commands are multi-step workflows:

Prepare this branch for PR review:

1. Run the linter and fix any auto-fixable issues
2. Run the type checker and fix any errors
3. Run tests and fix any failures
4. Generate a summary of all changes on this branch vs main
5. Draft a PR description following the template in .github/PULL_REQUEST_TEMPLATE.md

If step 1-3 produce changes, commit them with the message "chore: fix lint, type, and test issues"

Show me the PR description draft at the end.

This replaces five manual steps with one command. Each step builds on the previous one, and the whole workflow is reproducible.

Commands vs. skills vs. CLAUDE.md

Understanding when to use each:

ToolPurposeWhen to use
CLAUDE.mdPersistent project contextAlways-on rules and conventions
Skills (.claude/skills/)Modular instruction setsReusable patterns, installable across projects
Commands (.claude/commands/)On-demand workflowsActions you trigger explicitly

CLAUDE.md is passive -- Claude Code reads it automatically. Skills can work both ways: Claude loads them automatically when relevant, or you invoke them directly with /skill-name. Commands are on-demand workflows you trigger explicitly. A good setup uses all three: CLAUDE.md for project context, skills for shared conventions, and commands for repeatable workflows.

If you find yourself copying the same slash command across multiple repos, that's a signal to convert it into a skill. Skills published on localskills.sh can be installed into any project with one command and updated centrally.

Tips from the field

Start small. Your first two commands should be the workflows you run most often. For most developers, that's code review and test generation. Get those working well before building a large library.

Iterate on wording. The first version of a command rarely produces perfect output. Run it a few times, notice where Claude Code's output diverges from what you want, and tighten the instructions. Good commands go through 3-4 revisions.

Keep commands focused. A command that tries to do everything does nothing well. If your deploy command also generates changelog entries and sends notifications, split it into separate commands. You can always run them in sequence.

Use commands as documentation. A well-written command file documents your team's workflow. New developers can read .claude/commands/deploy.md to understand the deploy checklist, even if they don't use Claude Code.

Pair with Claude Code tips. Commands are most effective when Claude Code already has good project context from a well-structured CLAUDE.md. The command tells Claude what to do; the project configuration tells it how to do it in your specific codebase.


Start building your command library

Custom slash commands turn your best prompts into repeatable workflows. Start with one command for code review, refine it over a few uses, and expand from there.

For commands and conventions that should work across multiple projects and tools, sign up for localskills.sh and publish them as shared skills your entire team can install.

npm install -g @localskills/cli
localskills login
localskills publish