Slash Commands: One / Calls Up All Claude's Quick Actions
📚 Series Navigation: The previous article 35 Control and Modes taught you how to tighten or loosen the reins on Claude during a session (permission modes,
/model,/effortand other switches). This article brings the perspective back to that entry point you type every day but might not truly understand—slash commands. Type a/, and everything from switching models and clearing context to one-click processes you carve out yourself is all in this one menu. I'll guide you through identifying all the built-in ones, and then teach you how to carve out a few of your own.
A lot of people did something pretty silly when they first started using Claude Code.
Every time they wanted to clear the conversation and restart, they obediently did this whole routine: first Ctrl+C to exit claude, then restart claude in the terminal, wait for it to reload the project, read CLAUDE.md again—taking about ten seconds in total. Doing this consecutively for a week or two, they felt in their hearts, "Well, it's a restart, it's supposed to be like this." Until they flipped through the official documentation and stumbled upon a /clear command, with one sentence stating, "Start a new conversation with an empty context." Only then did they discover: Turns out typing three characters within the session would do it, and those two weeks of restarts were completely wasted effort.
What's even more embarrassing came later. /compact can compress a long conversation and continue chatting, /model can switch models without restarting, /init can generate CLAUDE.md with one click... All these are things that were either manually brute-forced before, or they simply didn't know could be done. These commands have always just been lying there in that / menu, all listed if you just type a slash, but they were never explored.
Sharing this embarrassing story is to prevent you from taking detours: Slash commands are not "advanced gameplay", they are the most fundamental control panel of Claude Code. The vast majority of "meta-operations" you want to do in a session—not making it write code, but tuning the program itself—entering them is all done through this one /. This article will first help you identify the built-in batch, and then teach you how to carve the prompts you manually type every day into your own one-click commands.
After reading this article, you will get:
- A one-sentence explanation of what a slash command is, and why it only counts at the beginning of a message.
- A list of built-in commands grouped by "usage scenario" (
/help,/clear,/compact,/init,/model,/agents,/mcp,/memory, etc.), no need to memorize, just look them up as needed. - The complete steps to write a slash command yourself: drop a markdown in
.claude/commands/, add frontmatter, use$ARGUMENTSto pass parameters. - An advanced trick: make the command fill in "on-site data" like
git diffitself before sending it to Claude. - What namespaces are all about, and why commands that come with plugins will never clash with yours.
- The exact relationship between slash commands and Skills (in one sentence: slash commands are the "shout out loud" usage of Skills, detailed in Article 26).
- A hands-on practice you can run along with that provides expected outputs: carve a
/explaincommand with parameters in 5 minutes and verify it.
01 Figure it Out First: What Exactly is a Slash Command, and Why Does it Only Count at the Beginning
Let's give the conclusion first: A slash command is a "control instruction" you type in a Claude session—it's not spoken for Claude to hear so it works, but directly commands the Claude Code program itself: switch models, clear context, run a process, open a panel.
Think back to the previous thirty-plus articles. Dealing with Claude has always been split into two types of speech. One type is legitimate requirements: "Help me refactor this function," "What's wrong with this error message"—these are spoken for the model to hear. The other type is meta-operations: "Clear the conversation and restart," "Switch to a cheaper model," "Generate a project description"—these shouldn't rely on "chatting" with the model, but should have a direct switch. Slash commands are the unified entry point for these switches.
Analogy: The printed buttons on a TV remote control. When you watch TV, changing channels, adjusting volume, switching inputs, opening the menu—you don't shout at the TV, "Please help me turn the volume up," you press the corresponding button on the remote. Each button does one specific thing, takes effect immediately when pressed, requires no explanation, and won't be misunderstood. Slash commands are this row of buttons for Claude Code: /clear is the clear-screen button, /model is the change-input button, /help is that menu button—typing them executes a fixed action hardcoded in the program, which is a different matter from "asking the model for help."
The official positioning is very straightforward:
Commands control Claude Code from inside the session. They provide a quick way to switch models, manage permissions, clear context, run workflows, etc.
There is a point where beginners most easily stumble, and the official docs specifically emphasized it—slash commands are only recognized at the beginning of a message:
Commands are only recognized at the beginning of a message. Text after the command name is passed to it as arguments.
To put it bluntly: you have to make / the first character of this message for it to be treated as a command. If you write "Help me see what /clear does", this /clear is in the middle of the sentence, will not be executed, and will only be sent to Claude as normal text. This design is reasonable—otherwise, when you discuss the command itself with Claude, the conversation would be cleared as soon as /clear is mentioned, which would be a mess. Remember: the command starts the line, everything following it is arguments.
Let's bring this down to a few real moments you will encounter, and feel when to press this row of "buttons":
- Chatting along and realizing the model isn't strong enough—no need to exit and restart, type
/modelto change to a stronger one right there, and the conversation continues. - Finished one task, want to switch to a completely new job—type
/clearto wipe the table clean, the old conversation can still be retrieved with/resume. - Just cloned an unfamiliar project, want Claude to understand it first—type
/init, it reads the code once and spits out aCLAUDE.md.
The common thread among these things: none of them are "making Claude write code," but "tuning Claude Code itself"—this is exactly the home ground of slash commands.
So how do you know which commands are available? The most effortless way—type a / in the session, the menu pops up immediately, listing all the commands currently available to you; then type a few more letters, and it filters in real time. Official original words:
Type
/to see every command available to you, or type/followed by letters to filter.
💡 One-sentence summary: Slash commands are Claude Code's "control button row"—they manage the program itself (switching models, clearing context, running workflows), not assigning work to the model; they only count at the beginning of a message, typing a
/lets you see all available commands.
02 Built-in Command List: No Need to Memorize, Look Up by "Which Step Are You On"
There are dozens of built-in commands. Trying to memorize them one by one is purely making things hard on yourself. The official Claude Code documentation itself organizes them by "the typical flow of a session"—whichever step you are on, you naturally should use those few. I have sorted the most commonly used ones into a few groups following this logic. Just find the row based on "what you want to do right now."
Let's clarify one thing first: among these dozens, the vast majority are "built-in commands" (behavior hardcoded in the CLI, pressing them executes fixed logic), and a small handful are marked as Skill in the documentation—those are "bundled Skills," which are essentially a prompt to Claude, letting it use its own tools to orchestrate and complete (like /code-review, /debug). There are even fewer marked as Workflow—those are dynamic processes parallelized across multiple subagents (like /batch, /deep-research); the calling experience is the same, but the underlying layer is more complex. You just need to know this exists. You call all three types by typing / plus the name, and there's no difference in usage, the only difference is how they are implemented underneath—this detail was unpacked in Article 26 when talking about Skills, so we won't expand on it here.
Group 1: Setting up the stage when just entering a project
| Command | What it does | When you use it |
|---|---|---|
/init | Generates a starting CLAUDE.md for the project | First time starting work in a repository (detailed in Article 12) |
/memory | Edits CLAUDE.md memory files, manages auto-memory | Want to fine-tune that description after /init (detailed in Article 25) |
/mcp | Manages MCP server connections and authorization | When you need to connect external services (detailed in Article 22) |
/agents | Manages subagent configurations | When you need to configure specialized minions (detailed in Article 23) |
/permissions | Manages "allow / ask / reject" permission rules | Want to decide if it asks you before acting (detailed in Article 20) |
This group is basically a fixed routine when entering a new project: first /init to let it read the code once and spit out a draft CLAUDE.md, then /memory to go in and correct the few items it guessed wrong. Saves you from writing that description from scratch—the first time you use this workflow, it's genuinely a bit of a pleasant surprise.
Group 2: Working halfway, adjusting state
| Command | What it does | When you use it |
|---|---|---|
/model | Switches models, and saves as default for new sessions | Want to switch to a stronger or cheaper model |
/clear | Starts a new conversation with empty context (old ones can still be retrieved with /resume) | Switching to a completely new task, wipe the table clean |
/compact | Compresses the current conversation into a summary, freeing up context to keep chatting | Conversation too long, workbench almost full (detailed in Article 19) |
/context | Draws the current context usage into a colored grid | Want to see "who is taking up my workbench" |
/plan | Directly enters plan mode | Let it produce a plan without acting before major changes |
/clear and /compact are the easiest to confuse, the pitfall mentioned at the beginning was not distinguishing "clear" from "compress". In a nutshell: Switching to an unrelated new task use /clear (wipe the whole table clean and restart), keeping the same task but chatted too long use /compact (organize the scratch paper into a page of key points and continue). Article 19 specifically unpacked this pair, here you just need to remember "change task clear, continue task compact."
Group 3: Checking before handing over the work
| Command | What it does |
|---|---|
/diff | Opens an interactive diff viewer to see uncommitted changes |
/review | Reviews a PR in the current session |
/security-review | Specifically scans the current branch changes for security vulnerabilities |
/code-review | Reviews diffs to find bugs and simplifications, can add --fix to change directly |
Group 4: A few in the miscellaneous section you'll eventually use
| Command | What it does |
|---|---|
/help | Shows help and available commands |
/config | Opens the settings interface, adjust themes, models, output styles, etc. |
/doctor | Checks your installation and config, press f to let it fix automatically |
/resume | Restores an old conversation by ID or name, or opens a selector |
/skills | Lists all currently available Skills |
/rewind | Rewinds the conversation and/or code to a checkpoint (next article's protagonist) |
Note: Not every command is displayed to everyone. The official docs put it clearly—"Availability depends on your platform, tier, and environment." For instance,
/desktoponly appears on macOS and Windows when logged in with a Claude subscription,/upgradeis only available on Pro and Max tiers. The menu you see when typing/is the true full set that this machine and this account can actually use right now—take it as the standard, don't get hung up on commands in other people's screenshots.
I haven't provided the complete list for these four groups (the official master table has dozens of rows), but they cover 90% of your daily scenarios. For the rest, whatever you want to do on a whim, type / plus a few letters to filter; it's much more practical than flipping through documentation.
💡 One-sentence summary: Don't brute-memorize built-in commands, look them up grouped by "which step you are on"—setting up (
/init,/memory,/mcp,/agents), working (/model,/clear,/compact,/context), before delivery (/diff,/review,/code-review), miscellaneous (/help,/doctor,/resume); the menu is the true full set for your machine, type/to see it.
03 Carving a Command Yourself: Just Drop a Markdown in .claude/commands/
Having identified the built-in commands, what really makes slash commands easy to use is that you can build them yourself.
Why build them yourself? Think about those "repetitive labors" in your daily dealings with Claude—every time you ask it to commit code, you urge the same set of rules; every time you review a PR, you type the same opening remarks; every time you explain code, you emphasize "speak human language, don't pile up jargon." When you type the same prompt for the fifth time, it's a signal: it's time to carve it into a command.
Analogy: Programming a "learning button" on a remote control. Good universal remotes have a "learning button"—you record a string of common operations (turn on → switch to HDMI2 → set volume to 15) into it, and from then on, pressing this button runs the whole string of actions automatically, no need to press them one by one anymore. Custom slash commands are this learning button: you "record" a prompt you have to type repeatedly into a command, and from then on, typing the command name automatically sends out that prompt.
How to build one? It's so simple you might not believe it—drop a markdown file in the .claude/commands/ directory, and the filename is the command name. The official documentation writes it very clearly:
Files in
.claude/commands/deploy.md... will create/deploy.
That is to say, if you create a .claude/commands/commit.md and write your commit rules inside, it automatically becomes the /commit command. The filename (minus the .md suffix) is the command name you type, with zero configuration.
Let's take a most down-to-earth example. You create a new .claude/commands/review.md and write inside:
Please review my current uncommitted changes, focusing on three things:
1. Are there any missing error handling
2. Are there any hardcoded configuration values (ports, keys, paths)
3. Are there any tests that should be added but are missing
List them point by point in Chinese, indicating which file each point is in.After saving it, you type /review in the session, and what Claude receives is this entire prompt above—it's equivalent to you typing that exact text word for word, but you only typed seven characters.
There is a crucial distinction about "where to put it", which is perfectly in line with what was said earlier when discussing MCP and Skills:
| Where it's put | Command scope | Does it go into git |
|---|---|---|
Project level .claude/commands/ | Only this current project | Yes, the whole team can pull and use it |
Personal level ~/.claude/commands/ | All your projects | No, it's your private one |
The logic is exactly the same as Skills: If this command is exclusive to this project and you want collaborators to use it too (like the release process for this project), put it at the project level and commit it into the repository; if it's only for yourself and universal across projects (like your personal habits for explaining code), put it at the personal level ~/.claude/commands/. Several small cross-project commands lie in ~/.claude/commands/ year-round, and they are there no matter which project you switch to; this saves much more worry than reconfiguring them for every project.
💡 One-sentence summary: Custom commands are "recording a repeatedly typed prompt into one key"—drop a markdown under
.claude/commands/, the filename is the command name, zero configuration; put it at the project level to share with the team, or at~/.claude/commands/for personal cross-project universality.
04 Adding Flavor to Commands: Frontmatter and $ARGUMENTS Passing Parameters
The /review command from the previous section is already usable, but it has an obvious limitation: the content is hardcoded and cannot take parameters. You can't tell it "just review this one file src/auth.ts"—it reviews all changes every time. To make the command flexible, you need to add two things: frontmatter and parameter placeholders.
Use $ARGUMENTS to catch the parameters you pass
First, solve parameter passing. Claude Code provides a placeholder $ARGUMENTS—everything you type after the command name will be substituted into the position of this placeholder. The example given in the official documentation is the most intuitive:
Fix GitHub issue $ARGUMENTS following our coding standards.
1. Read the issue description
2. Understand the requirements
3. Implement the fixThe official original words explaining its effect:
When you run
/fix-issue 123, Claude receives "Fix GitHub issue 123 following our coding standards..."
Do you see it? You type /fix-issue 123, and that 123 is stuffed into the position of $ARGUMENTS. A command template, with parameters that you change at will—this is where commands are truly useful.
There is also a considerate fallback: the official documentation says, if you passed parameters, but didn't write
$ARGUMENTSin the command at all, Claude Code will automatically appendARGUMENTS: <your input>to the end of the command content, "so that Claude still sees what you typed". So even if you forget to write the placeholder, the parameters won't vanish into thin air.
Want to pass several parameters? Use $0 $1 to take them by position
What if a command needs to pass multiple parameters? Like "Migrate the SearchBar component from React to Vue", there are three independent values here. The official documentation provides a way to take parameters by position—$ARGUMENTS[N], or the shorter $N (both start counting from 0):
Migrate the $0 component from $1 to $2.
Preserve all existing behavior and tests.You run /migrate-component SearchBar React Vue, $0 is SearchBar, $1 is React, and $2 is Vue. Note a pitfall: The official docs say these positional parameters follow "shell-style quoting"—so multi-word values must be wrapped in quotes to count as one parameter. For example /my-cmd "hello world" second, only then is $0 the complete hello world, otherwise it will be split by the space. (While $ARGUMENTS is not affected, it's always the entire original string you typed.)
Use frontmatter to control the command's behavior
Just being able to pass parameters isn't enough. Your /deploy, /commit commands carry side effects—you definitely don't want Claude taking it upon itself to deploy for you just because it "thinks your code looks done". This is where frontmatter comes in to manage things.
Frontmatter is a block of YAML configuration written between two --- lines at the beginning of the file (you saw this concept when talking about SKILL.md in Article 26; custom command files support identical frontmatter). The two fields you should know most about are:
---
description: Stages and commits the current changes
disable-model-invocation: true
---
Commit the current changes, using Chinese for the commit message, prefix following feat/fix/docs:
1. Run the test suite first
2. git add changes
3. Commit with standard Chinese messagedescription: A one-sentence explanation of what this command does. Claude relies on it to judge "whether to automatically use this command", so it's recommended to always include it.disable-model-invocation: true: Set totrue, this command can only be manually shouted by you, Claude will not trigger it automatically. Tasks with side effects that you want to personally time (deployments, commits, sending messages) should all have this added.
This leads to a cognition you must get clear on, to save you from being startled by it "acting on its own"—your custom commands are by default "callable by both you and Claude". You typing /commit is a manual call; but because you wrote a description, when Claude feels it matches, it might also call it itself. This is exactly the manifestation of slash commands and Skills being the "same thing" (detailed in Article 26)—if you're afraid of it randomly acting on its own, add disable-model-invocation: true to lock it as purely manual. Commands like /commit should have this as the first rule, otherwise it really might commit unreviewed changes for you a few times.
| The effect you want | What frontmatter to add |
|---|---|
| Command has side effects, only I am allowed to manually shout it | disable-model-invocation: true |
| Let Claude know when to use this command | Write a good description |
| Restrict which tools it can use while active without asking every time | allowed-tools: Bash(git add *) Bash(git commit *) |
💡 One-sentence summary:
$ARGUMENTScatches all input after the command name,$0/$1takes by position (multi-word values must be quoted); in the frontmatter,descriptionlets Claude know when to use it,disable-model-invocation: truelocks it to manual only—commands with side effects must add the latter.
05 An Advanced Trick: Let the Command Bring Its Own "On-Site Data"
At this point, your command can pass parameters, but there's an even fiercer trick—let the command fill in the on-site data itself before sending it to Claude. This trick is called dynamic context injection, and it is the most underestimated capability of custom command files.
First, let's talk about what it solves. In your /review command, what's written is "Please review my current uncommitted changes"—but when Claude gets this sentence, it still has to run a git diff itself to know what you changed. Is it possible to stuff the diff directly in before it even reads the command? Yes.
The syntax is writing !`command` in the command—an exclamation mark plus backticks wrapping a shell command. The official documentation explains it very clearly:
The
!`<command>`syntax runs a shell command before sending the content to Claude. The command output replaces the placeholder, so Claude receives the actual data, not the command itself.
For example, let's upgrade /review. You write this in .claude/commands/review.md:
## Current Changes
!`git diff HEAD`
## Instructions
Review the changes above, focusing on missing error handling, hardcoded configuration values, and tests that should be added. List them point by point in Chinese.What will happen to that line !`git diff HEAD`? The execution order stated officially is like this:
- Claude Code first runs
git diff HEAD - Replaces the output of this command into that line
- What Claude sees is a complete prompt that has already been filled with your real diff at this moment
That is to say, what Claude gets in its hands is not "go run a diff", but "here are the user's changes: ... (real content), please review". This is preprocessing, not Claude executing it itself—it only sees the final filled result. After adding this line to that /review, you can distinctly feel it "gets into the state right from the start," without needing to take a detour to check the changes first.
A few details you must know before using it, to avoid pitfalls:
- The exclamation mark must be at the start of a line, or immediately following whitespace to take effect. If you write it like
KEY=!cmd`` hugging other characters, it will be treated as normal text and the command won't run. - For multi-line commands, don't use the inline syntax; use a fenced code block starting with
```!instead (one command per line inside). - This capability can be turned off: There is a
disableSkillShellExecutionin the settings; once set totrue, these commands will uniformly not execute, and will be replaced with an English prompt[shell command execution disabled by policy]. It's most useful in team-hosted settings—to prevent someone from stuffing an arbitrarily running shell command into a command in a shared repository.
Incidentally, a small tip for auto-completion: add a line argument-hint in the frontmatter (like argument-hint: [issue-number]), and when you type the command name, auto-completion will prompt "what parameters this command should pass". When you have many commands, this hint can save you from flipping through documentation.
💡 One-sentence summary:
!`command`allows a slash command to fill in on-site data (likegit diff) first before sending to Claude, so Claude gets real data instead of "go run a command"; the exclamation mark must be at the start of a line, use```!blocks for multiple lines, and teams can disable it with one click usingdisableSkillShellExecution.
06 Namespaces: Why Commands Bundled with Plugins Never Clash
When you've built a lot of commands yourself, and then install a few plugins (each plugin also bringing a bunch of commands), a realistic problem arises: Will their names clash? For example, you wrote a /review, and a plugin you installed also has a /review, when you type it out, which one actually runs?
Let's first talk about the kind that will clash and the kind that won't, the key is looking at where the command comes from.
Among your own commands: Decided by priority
If it's your own .claude/commands/ file having the same name as a Skill in .claude/skills/—the official documentation gives a clear rule:
If a skill and a command share the same name, the skill takes precedence.
That is to say, if you have a .claude/commands/deploy.md, and also a .claude/skills/deploy/SKILL.md, typing /deploy goes to that Skill. Just remember this rule "same-name Skill wins", you rarely intentionally build two with the same name anyway.
Commands bundled with plugins: Relies on namespaces, simply won't clash
Plugins' handling method is more thorough—they simply don't compete with you for names. Official original words:
Plugin skills use the
plugin-name:skill-namenamespace, so they cannot conflict with other levels.
Analogy: Adding a company prefix to people with the same name in your phone contacts. If you have two "Zhang Wei"s in your contacts, how would you save them? Probably note them as "Zhang Wei (Sequoia)" and "Zhang Wei (Hillhouse)"—add a prefix, and the two will never be confused again. Namespaces do exactly this: that review inside the plugin my-plugin, at your place is called /my-plugin:review, the chunk of plugin name at the front is the "company prefix". So even if you yourself also have a /review, the two commands—one with a prefix and one without—don't interfere with each other.
This is why it was said earlier in Article 24 about plugins that "plugin Skills will never clash with yours"—it relies entirely on this plugin-name:command-name namespace system. If you install multiple plugins, and each comes with a review, they are respectively /plugin-a:review, /plugin-b:review, each shouting its own.
There is another type of command with "double underscores" that you might run into: Prompts exposed by MCP servers. The official docs say they use a format like /mcp__<server>__<prompt>, dynamically discovered from connected servers. If you see a /mcp__github__xxx, don't be confused—that's a command bundled with some MCP server (detailed in Article 22).
💡 One-sentence summary: When your own commands have the same name "Skill wins over command"; plugin commands rely on the
plugin-name:command-namenamespace, inherently won't clash; MCP server commands use the/mcp__<server>__<prompt>format—three origins, recognizing the prefix keeps things untangled.
07 Slash Commands and Skills: What Exactly is Their Relationship, Clarified in One Sentence
Having studied up to here, you might be muttering to yourself: Slash commands, Skills, why do these two sound so similar? What's the difference between what I just wrote in .claude/commands/ and the SKILL.md written in .claude/skills/ from Article 26?
This is a good question, and also the knot beginners get tangled in most easily. Let me untie it for you in one sentence:
Custom slash commands have been officially merged into the Skill system. Your
.claude/commands/files can still be used exactly as before, but a Skill is an "upgraded version"—it has the added abilities to carry supporting files, be triggered automatically by Claude, and to load only on-demand when long documents are referenced via progressive disclosure (rather than fully preloading).
The official original statement is very direct:
Custom commands have been merged into skills. A file in
.claude/commands/deploy.mdand a skill in.claude/skills/deploy/SKILL.mdboth create/deployand work the exact same way.
So these two are not opposing things at all, but two ways of writing the same capability. Looking at it from another angle: "Slash command" is more like an "invocation method" (you type / to shout it out manually), while a Skill is the "entity" being shouted at. The table in Article 26 already thoroughly explained the positioning of Skills, slash commands, and Subagents. Here, I'll just add a comparison of "the same thing, how to choose between the two ways of writing it":
| Your requirement | Use old-style command (.claude/commands/xx.md) | Use Skill (.claude/skills/xx/SKILL.md) |
|---|---|---|
| Just a prompt segment, purely manual shouting | ✅ Enough, least effort | Also works, but overkill |
| Want to include templates / scripts / example files | ❌ Cannot include | ✅ It's a directory, can hold a bunch of supporting files |
| Want Claude to "automatically invoke it when appropriate" | Can do if description is written, but Skill is designed for this | ✅ Home turf |
| Want to stuff long reference docs without occupying context | ❌ Cannot accompany subsidiary files (templates/scripts/long docs) | ✅ Supports subsidiary files directory, long docs can be referenced on demand in SKILL.md, not automatically fully loaded upon invocation |
A rule of thumb: For a small job that is just a segment of prompt and you shout it out manually yourself (like that /review), an old-style .claude/commands/ with a single markdown is the least effort, don't fiddle around; the moment you find yourself thinking "I want to give it a template," "I want to stuff a long document in but don't occupy the context," "I want it to judge for itself whether it should be used"—then you should upgrade to a Skill (how to write it is in Articles 26 and 27; if you're too lazy to handwrite it, use the skill-creator from Article 28).
To put it bluntly, the "custom slash commands" you learned in this article are the most lightweight entry point into the Skill system. First use it to play smoothly with the matter of "one-click prompts"; when you need more capabilities, just smoothly upgrade to a Skill—the official documentation clearly states "your existing files continue to work," and .claude/commands/ is an officially supported writing format with no intention of being deprecated.
💡 One-sentence summary: Custom slash commands have been merged into the Skill system—the old-style
.claude/commands/is the most lightweight entry point (purely a prompt segment, manual shout); when you need supporting files / auto-triggering / progressive disclosure, upgrade to a Skill; both create same-named commands and are used identically.
08 Hands-on: Carve a /explain Command with Parameters in 5 Minutes
Just reading without practicing won't help you remember. Below I'll guide you from scratch to carve a truly usable, parameter-passing slash command—an /explain that "explains code / errors in plain English." The whole process doesn't rely on any complex environment; an empty directory is enough to run through it.
Step 1: Create the command directory (Mac / Linux)
In any of your project directories (if you don't have one, mkdir an empty one and go in), create the .claude/commands/ folder:
mkdir -p .claude/commandsWindows users: Manually create these two levels of folders .claude\commands\ in the project root directory.
Expectation: There is an empty .claude/commands/ directory added under the project.
Step 2: Write the command file
Use an editor you are handy with to save the following content as .claude/commands/explain.md:
---
description: Explains a piece of code or an error in plain English. Use this when the user wants to understand some code or an error message.
---
Please explain the following thing in plain English that a beginner can understand:
$ARGUMENTS
Requirements:
1. First, say what it is doing overall in one sentence
2. Then break it down line by line / section by section clearly
3. If it is an error message, point out the most likely cause and how to fix it
4. Minimize jargon, use everyday analogies if possibleNote two places: What is boxed by --- at the beginning is the frontmatter; that description sentence lets Claude know what this command does. The $ARGUMENTS in the main body is for catching the code / error message you will pass in later.
Expectation: There is an explain.md inside .claude/commands/.
Step 3: Start Claude, confirm the command has been recognized
claudeAfter entering, first type a / (just type the slash, don't hit enter), and look at the pop-up menu:
Expectation: You can see /explain in the menu, and next to it is the description you wrote. Seeing it in the menu = command has been loaded correctly. If you don't see it, it's mostly likely because the file wasn't saved in the right place—verify that it's in .claude/commands/explain.md, not some other path.
Step 4: Shout it with parameters
Now really use it—type the command name, followed by the thing you want to explain (this string will be stuffed into $ARGUMENTS):
/explain print(sum([1,2,3]) / len([1,2,3]))Expectation: Claude receives your complete prompt, where $ARGUMENTS has been replaced with print(sum([1,2,3]) / len([1,2,3])). It will follow your four-step requirements—first an overall sentence (calculating the average of these three numbers), then break it down by section, less jargon, analogies if possible. You only typed the command name plus a snippet of code, and that entire set of "explanation requirements" automatically took effect. This is the power of $ARGUMENTS.
Step 5: Change the parameter and do it again
With the same command, change it to explain an error message:
/explain ZeroDivisionError: division by zeroExpectation: The /explain is triggered similarly, but this time $ARGUMENTS becomes that error message. Claude will emphasize the 3rd requirement and talk about "the most likely cause and how to fix it" (the divisor became 0). One template, parameters changed at will—this is exactly where custom commands are better than manually typing prompts.
Having run through these five steps, you have personally verified the three core aspects of custom slash commands—"filename is command name", "frontmatter adds description", and "$ARGUMENTS passes parameters". From now on, whenever you want to carve any command, the essence is this set of processes, nothing more than changing a filename, changing a prompt segment, and adding frontmatter fields as needed.
💡 One-sentence summary: Carving a command takes just three steps—drop a markdown under
.claude/commands/(filename is command name), adddescription, use$ARGUMENTSto reserve a parameter spot; type/to see if it entered the menu, then shout it twice with different parameters; verifying it by hand is more solid than memorizing ten rules of documentation.
09 Summary
This article has lifted the veil on slash commands from being "an entry point you type every day but hadn't mastered"—it is the control panel of Claude Code. From the dozens of built-in switches to the one-click processes you carve yourself, everything is behind a /.
Stringing the core points together for review:
| What you want to figure out | Answer | Key point |
|---|---|---|
| What is a slash command | Claude Code's control instructions | Manages the program itself, not assigning work; only counts at the start of a message |
| How to remember built-in cmds | Look up by usage scenarios | Setting up / working / before delivery / misc; type / to see true full set |
| How to build commands yourself | Put markdown in .claude/commands/ | Filename is command name; project-level sharing / personal-level cross-project |
| How to pass params to commands | $ARGUMENTS / $0 $1 | Input after command name automatically replaces; multi-word values need quotes |
| How to make cmds carry on-site data | !`command` dynamic injection | Fill in real output like git diff before sending to Claude |
| How to control cmd behavior | frontmatter | description informs when to use, disable-model-invocation locks manual |
| Will commands clash | Three sources have rules | Skill wins over command, plugins rely on namespaces, MCP uses /mcp__ prefix |
| What's the relationship with Skill | Merged into the Skill system | Commands are the most lightweight entry, upgrade to Skill when more abilities needed |
You should now be able to: Understand that menu with one /, find the built-in command you should use according to "which step you are on"; carve the prompts you type repeatedly into a command under .claude/commands/, use $ARGUMENTS to make it take parameters, and use frontmatter to manage its behavior; distinguish who wins when commands have the same name and why plugin commands don't clash; and understand that slash commands and Skills are originally the same thing—the former is the most lightweight entry point of the latter; once you play with it smoothly, you can upgrade upwards at any time.
Looking back at the "restart method" from those first two weeks mentioned at the beginning—in the end, it was just because that / menu was never flipped open. After this article, whenever you want to do something to Claude Code itself, your first reaction should be to type a slash and see if there is a ready-made switch; if not, spend two minutes carving one. Just this bit of habit can save you a whole lot of wasted time.
Next article 37 "Checkpoints"—I only briefly mentioned that /rewind at the end of this article; the next article specifically unpacks it. What do you do if Claude makes a bunch of code changes and the direction goes off track? You can't always rely on manual git reset or just stare blankly. The next article teaches you how to use Claude Code's built-in checkpoint mechanism, just like saving and loading games, to "rewind" the code and conversation together back to a clean state. Think about it: if there's automatically a "save point" every few steps of changes, wouldn't you be much bolder in trial and error?