Custom Commands

Create and activate your own slash commands to automate repetitive workflows with Claude Code.

Learning objectives

  • Understand the slash command system
  • Create your own custom commands
  • Use $ARGUMENTS to make commands reusable

How to create a custom command

Custom commands are plain Markdown files stored in .claude/commands/. The filename determines the command name: review-pr.md becomes /review-pr, summarize.md becomes /summarize. Claude Code scans that directory automatically — no registration step required.

To create your first command:

# Create the commands directory if it doesn't exist
> mkdir -p .claude/commands

# Create a command file
> touch .claude/commands/review-pr.md

Open review-pr.md and write the prompt you want Claude to receive when you type /review-pr. No frontmatter required — the file content is the prompt template. Any text typed after the command name is passed in as $ARGUMENTS.

For example, if your file contains Review the pull request at $ARGUMENTS for correctness and style and you type /review-pr #142, Claude receives Review the pull request at #142 for correctness and style.

How a custom command resolves
direction: right

cmd: "/review-notebook notebooks/churn.ipynb"
file: .claude/commands/review-notebook.md
prompt: "Prompt with arguments"
claude: Claude Code

cmd -> file
file -> prompt
prompt -> claude

Template

Here is a complete, realistic command for a DS/ML workflow. It reviews a Jupyter notebook for common issues that affect reproducibility and model correctness.

Review the notebook at $ARGUMENTS for:
1. Reproducibility — are random seeds set? are paths relative?
2. Data leakage — does any preprocessing use future information?
3. Code quality — are functions documented? is logic reusable?
4. Output — are all cells run in order? are large outputs cleared?

Provide a structured report with a severity level (high/medium/low) for each issue found.

To invoke it:

/review-notebook notebooks/churn_model.ipynb

Claude replaces $ARGUMENTS with notebooks/churn_model.ipynb and runs the prompt. You can reuse the same command on any notebook in your project — no edits needed.

$ARGUMENTS captures everything after the command name as a single string. For instance, /compare-models models/v1.pkl models/v2.pkl passes models/v1.pkl models/v2.pkl as one block of text.

When you need individual arguments separately, use positional access: $ARGUMENTS[0] for the first, $ARGUMENTS[1] for the second — or the shorthand $0, $1, $2. A command that compares two model versions might use:

Compare $0 and $1. Focus on accuracy, latency, and memory footprint.
Output a structured table with one row per metric.

Running /compare-models models/v1.pkl models/v2.pkl substitutes each argument by position.

A few things worth getting right when writing command templates:

  • Be explicit about the output format. If you want a numbered list with severity labels, say so.
  • Do not assume Claude knows your project context. If the command depends on a convention (like “all data is in data/raw/”), state it in the template.
  • Write the prompt as carefully as you would write it by hand. The command is not magic — it is just a saved prompt.

Dos and don’ts

DoDon’t
Write commands for workflows you repeat more than twice a weekCreate commands for one-off tasks
Use $ARGUMENTS to make commands reusableHardcode specific file paths
Keep command files in .claude/commands/ and commit themStore commands in ad-hoc places outside the project
Write the prompt as clearly as you’d write it manuallyAssume Claude will infer missing context
Test the command on a real case before sharingShare untested commands with the team

The test-before-sharing rule matters more than it looks. A command that works well on one notebook may produce shallow results on another if the prompt is underspecified. Run it on two or three real cases before committing it as a team standard.