If you have installed Claude Code and used it for a week, you have probably noticed a problem: you keep typing the same instructions. "Review this diff for security issues." "Summarize what changed." "Follow our commit convention." Slash commands fix this — and most guides stop at /help, which is a waste, because the custom command system is where Claude Code goes from "impressive demo" to "daily driver."
This guide covers both halves of the system: the built-in commands that matter (and the two that control your API bill), and how to build your own command library in .claude/commands/ that your whole team can share through Git.
1. What Are Slash Commands?
Slash commands are instructions that start with / and are handled by Claude Code itself, not sent to the model as an ordinary prompt. There are two kinds:
- Built-in commands — ship with the CLI. They manage sessions, context, configuration, and integrations. You cannot edit them, but you should know the ten or so that matter.
- Custom commands — Markdown files you write. The filename becomes the command. The file content becomes a reusable, parameterized prompt.
The mental model for custom commands: they are saved prompts with arguments. Nothing more magical than that — but because they live in files, they are versionable, reviewable, and shareable like any other code.
2. Built-in Commands Worth Memorizing
Claude Code has dozens of built-ins. These are the ones that actually change how you work day to day:
| Command | What it does | When to use it |
|---|---|---|
/init | Scans your repo and generates a CLAUDE.md with project conventions | First session in any new repo |
/clear | Wipes the conversation, resets context to zero | Switching to an unrelated task |
/compact | Summarizes history into a compact summary, frees context | Staying mid-task but context is filling up |
/cost | Shows token usage and cost for the session | Whenever you wonder why the bill is high |
/model | Switch the active model | Cheap model for mechanical work, best model for design |
/review | Asks Claude to review a pull request | Pre-merge checks |
/pr-comments | Fetches GitHub PR comments into the session | Addressing reviewer feedback |
/memory | Opens CLAUDE.md files for editing | Teaching Claude your conventions |
/mcp | Lists and manages MCP server connections | Debugging tool integrations |
/resume | Reopens a previous session | Coming back to yesterday's work |
Run /help for the full list — but if you only learn three, learn /clear, /compact, and /cost. They are the difference between a $4 session and a $40 one.
3. /clear vs /compact: The Cost Lever
These two commands deserve their own section, because they control the single biggest cost factor in Claude Code: context size. Every turn, the entire conversation history is re-sent to the model. As you read files, run commands, and iterate on code, that history grows — and your cost per turn grows with it, linearly.
/compact replaces the full history with a summary. The session keeps going; Claude retains the decisions and the plan, but forgets the noise. You can steer the summary with instructions:
/compact focus on the database schema decisions and the failing test list
/clear resets everything. New task, empty context, minimum cost per turn.
The rule of thumb I use:
- Mid-task and context is filling →
/compact. Losing the thread would cost more than the tokens. - Task finished, switching context →
/clear. The old conversation has zero value for the new task and 100% of the cost. - About to start a big feature →
/clear, then/initif the repo has noCLAUDE.mdyet.
A concrete habit: run /cost every 30–45 minutes in a heavy session. If the number makes you wince, /compact and watch the next interval drop.
4. Your First Custom Command
Custom commands are Markdown files in a .claude/commands/ directory inside your project. The filename (without .md) becomes the command name.
Create one:
mkdir -p .claude/commands
Now make a file called security-review.md:
Review the code changes in $ARGUMENTS for security issues.
Check specifically for:
1. Injection vulnerabilities (SQL, command, path traversal)
2. Hardcoded secrets or credentials
3. Missing input validation on public endpoints
4. Authentication or authorization gaps
For each finding: state the file and line, explain the risk in one
sentence, and suggest a concrete fix. If nothing is found in a
category, say so explicitly rather than staying silent.
Start a new Claude Code session in that project, type /, and the command appears with tab completion:
> /security-review src/auth/
# Claude Code now runs your review checklist against src/auth/
That is the entire mechanism. Write a Markdown file, get a reusable command. If the command does not show up, restart the session — older versions only scanned the commands directory at startup.
5. Passing Arguments with $ARGUMENTS
$ARGUMENTS is the placeholder that gets replaced by everything you type after the command name. Without it, arguments are appended to the prompt as extra context; with it, you control exactly where user input lands.
Add a hint so tab completion shows the expected format, using frontmatter at the top of the file:
---
description: Fix a GitHub issue end-to-end
argument-hint: [issue-number]
---
Read GitHub issue #$ARGUMENTS with `gh issue view`.
Then:
1. Reproduce the bug or confirm the request is implementable
2. Identify the files that need to change
3. Implement the fix with tests
4. Run the test suite and confirm nothing regressed
5. Summarize what changed and why
Usage: /fix-issue 1234. The argument lands in the prompt exactly where $ARGUMENTS sits, and the argument-hint makes the autocomplete UI read like a real CLI tool instead of a guess-my-parameters game.
6. Personal vs Project Commands
Commands live in two places, and the difference matters for teams:
.claude/commands/(project) — lives inside the repo. Commit it to Git and every teammate gets the same command library the moment they pull. This is where code-review checklists, commit conventions, and deploy workflows belong.~/.claude/commands/(personal) — lives in your home directory, available in every project. This is where your quirks belong: your personal commit message format, your favorite explanation style.
If a project command and a personal command share a name, the project version wins. That is the correct precedence for teams: the repo's convention should override any individual's habit.
Subdirectories become namespaces. A file at .claude/commands/frontend/component.md is invoked as /frontend:component. This keeps a large command library readable — and note that very old Claude Code versions required a /project: prefix; current versions use the bare or namespaced name.
7. Power Features: Bash, File References, Frontmatter
Three features turn simple saved prompts into genuine workflow automation.
Inline Bash Execution
Prefix a shell command with ! inside the Markdown, and its output is injected into the prompt before Claude sees it:
---
description: Commit staged changes with a conventional message
allowed-tools: Bash(git status:*), Bash(git diff:*), Bash(git commit:*)
---
Here is the current repository state:
!`git status --short`
Here is the staged diff:
!`git diff --staged`
Write a Conventional Commit message for these changes
(type, scope, imperative subject, body if needed). Then commit
with that message using the git commit tool.
The allowed-tools frontmatter declares exactly which tools the command may use — here, only Git commands. Without it, Claude will ask permission before each Git call; with it, /commit runs end to end.
File References
The @ syntax pulls file contents into the prompt:
Compare @src/api/routes.ts against @docs/api-spec.md and list
every endpoint that deviates from the spec.
This is more reliable than asking Claude to "find the route file" — you pin the exact files, the command behaves identically for every teammate.
Frontmatter Options
The full set of recognized frontmatter fields in current versions:
description— shown in autocomplete; write it like a CLI help stringargument-hint— parameter shape shown during completionallowed-tools— tool whitelist for the command's executionmodel— pin a specific model for this command (useful for cheap, mechanical tasks)
8. Common Mistakes
Mistake 1: Writing a Novel Instead of a Command
A command file is a prompt, not documentation. A 400-line command produces worse results than a focused 30-line one — the model spends attention on your prose instead of your code. If a workflow is genuinely complex, split it into two commands (/review, then /fix) rather than one monster.
Mistake 2: Leaving Out $ARGUMENTS When Input Is Required
If the command makes no sense without a file path or issue number, put $ARGUMENTS in the body and an argument-hint in the frontmatter. Otherwise teammates run the bare command, the prompt is ambiguous, and the model fills the gaps with assumptions.
Mistake 3: Committing Machine-Specific Personal Commands
Commands with absolute paths (/Users/alex/scripts/lint.sh) or personal tokens belong in ~/.claude/commands/, not in the repo. A quick check before committing .claude/commands/: could a teammate on Windows run this?
Mistake 4: Using /clear Mid-Task to "Save Money"
/clear throws away decisions, not just tokens. If you are three hours into a refactor and clear the context, Claude re-derives everything — at worse quality and higher total cost. Mid-task, /compact is the tool; /clear is for task boundaries.
Mistake 5: Duplicating Commands Between Personal and Project
A personal /test that behaves differently from the project's /test is a source of quiet confusion — results differ and nobody knows why. If the project defines a command, either use the project's version or rename yours.
Frequently Asked Questions
How are slash commands different from CLAUDE.md?
CLAUDE.md is loaded into context on every session — it holds standing instructions like coding conventions. Slash commands run on demand — they hold workflows you trigger when needed. If Claude should always know it, put it in CLAUDE.md; if you should decide when to run it, make it a command.
Do custom commands work in headless (non-interactive) mode?
Slash commands are an interactive-session feature. For automation, pass the same prompt file content directly with claude -p "$(cat .claude/commands/security-review.md)", or use the Agent SDK. The Markdown format stays identical, so the same library serves both.
Can one command chain into another?
There is no native chaining. A command's output can, however, instruct Claude to follow a multi-step workflow — and in practice that covers most "chaining" needs. For hard orchestration guarantees, you are better served by a script calling claude -p twice.
How do I see all available commands?
Type / at the prompt for the autocomplete list, or /help for the full built-in reference. Custom commands appear in the same list, with their description frontmatter shown next to them.
Can commands connect to external tools like Jira or Slack?
Indirectly, yes. Commands are prompts — the tool access comes from MCP servers. Define an MCP server for your tool, then write a command like /ticket <id> that uses it. Commands decide what to do; MCP provides the capabilities.
Do custom commands cost extra?
No. A command is just a prompt sent to the model you are already using. The only cost impact is positive: reused instructions mean shorter, more consistent prompts than re-typing them (imperfectly) each time.
Bottom Line
The built-in commands that matter fit on a sticky note: /clear between tasks, /compact mid-task, /cost to keep yourself honest. The custom command system is where the leverage is: a .claude/commands/ directory committed to your repo turns your team's tribal knowledge — review checklists, commit conventions, deploy rituals — into typed commands that run the same way for everyone.
Start with one command for the task you repeat most this week. If you type the same instruction twice, it should have been a command.