Custom Commands Deep Dive — Differences from Skills and Best Practices
About 5 minutes
Mastering custom commands lets you execute repetitive workflows (blog post creation, PR reviews, i18n sync, etc.) with a single slash. This page systematically covers the structure of command files, design rules, and the steps for actually creating them.
The Difference Between Commands and Skills
Section titled “The Difference Between Commands and Skills”Commands and Skills are easy to confuse, but their roles are completely different.
| Aspect | Commands (/command) | Skills (SKILL.md) |
|---|---|---|
| Trigger | The user types /command | Claude automatically judges based on the situation |
| Invocation | Explicit and intentional | Implicit and automatic |
| Purpose | Execute a fixed workflow | Define behavior according to context |
| File location | shared/commands/*.md | shared/skills/*/SKILL.md |
| Template variables | $ARGUMENTS is available | None |
Commands let the user decide “what to do.” Skills let Claude automatically judge “how to behave.” The division of use is: the entire workflow for writing a blog post is executed with a /blog command, while the writing style rules and quality standards within the article are defined by blog-content/SKILL.md.
The Structure of a Command File
Section titled “The Structure of a Command File”Command files are written in Markdown format and placed in shared/commands/. .claude/commands/ is a symlink to this directory.
Basic structure:
# Command Name
A description of the command. Use `$ARGUMENTS` to receive the user's input.
## Steps
1. What to do first
2. What to do next
3. What to confirm last$ARGUMENTS expands to the argument portion when the user types /command argument. When you run /blog React's useEffect explained, the $ARGUMENTS in the command is replaced with React's useEffect explained.
A Real Example: The Structure of blog.md
Section titled “A Real Example: The Structure of blog.md”The shared/commands/blog.md in this project has the following structure.
Please create or update a blog post.
## For a new post
1. Create the Japanese article in `src/content/blog/ja/` (write it first)
2. Use the frontmatter template
3. Create the corresponding English article
4. Run `node scripts/ensure-slugs.js`
5. Conduct a review and fact-check
6. Check the local preview with `npm run dev`Commands that do not use $ARGUMENTS are also valid. They are suitable for cases where an entire fixed workflow should be executed without arguments.
Best Practices
Section titled “Best Practices”Start Command Names with a Verb
Section titled “Start Command Names with a Verb”Command names should start with a verb so it is clear at a glance what they do.
| Good example | Example to avoid |
|---|---|
/blog | /article |
/sync-i18n | /i18n |
/pr | /pullrequest |
This project’s shared/commands/ has blog.md, docs.md, pr.md, sync-i18n.md, and build.md. All of them have an “action” in their name.
Use $ARGUMENTS to Accept Flexible Input
Section titled “Use $ARGUMENTS to Accept Flexible Input”Allowing users to pass additional information to a command increases the command’s reusability.
# PR Summary
Please summarize the changes for the specified PR and organize the review points.
PR number or URL: $ARGUMENTS
## Steps
1. Get details with `gh pr view $ARGUMENTS --json title,body,files`
2. Check the diff of the changed files
3. Summarize and report the purpose of the changes, the scope of impact, and points to noteBe Mindful of Idempotency
Section titled “Be Mindful of Idempotency”Design the command so that running it twice does not break the system. For commands that create files, it is a good idea to include a step that says “if a file with the same name already exists, do not overwrite it and ask for confirmation.”
## Steps
1. Check if the target file already exists
2. If it exists, ask the user for confirmation before overwriting
3. If it does not exist, create it newInclude a Confirmation Step for Operations That Require Approval
Section titled “Include a Confirmation Step for Operations That Require Approval”Use the build.md design pattern as a reference. For commands involving production deployment or irreversible operations, explicitly include a step that asks for user confirmation before execution.
> ⚠️ **This command will trigger a production deployment.**
> Always ask the user for approval before executing.
## Confirmation Items Before Execution
Please confirm the following with the user before proceeding.
1. Has the local preview been confirmed?
2. Has the merge to main been completed?
3. Is it in a state that can be safely published to production?Place in shared/commands/ and Share via Symlink
Section titled “Place in shared/commands/ and Share via Symlink”Do not write command files directly in .claude/commands/; always place them in shared/commands/. By setting .claude/commands/ as a symlink to shared/commands/, all team members can use the same commands.
# Check the symlink
ls -la .claude/commands
# → .claude/commands -> ../shared/commandsHands-on Exercise
Section titled “Hands-on Exercise”Step 1: Check the Structure of an Existing Command
Section titled “Step 1: Check the Structure of an Existing Command”cat shared/commands/blog.md✅ Verify: If the file contents are displayed and include step numbers,
npm runcommands, and fact-check instructions, the read was successful.
Step 2: Actually Use the /blog Command
Section titled “Step 2: Actually Use the /blog Command”Launch Claude Code and run the command.
> /blog Introduction to Claude Code HarnessClaude starts creating an article following the steps in shared/commands/blog.md.
✅ Verify: If Claude starts responding with content such as “I will create a Japanese article in
src/content/blog/ja/”, the command has been loaded correctly.
Step 3: Create a New Command summarize-pr.md
Section titled “Step 3: Create a New Command summarize-pr.md”Create a new file shared/commands/summarize-pr.md.
# PR Summary
Please summarize the changes for the specified PR number and organize the review points.
PR number or URL: $ARGUMENTS
## Steps
1. Get PR details with `gh pr view $ARGUMENTS --json title,body,files`
2. Check the diff of the changed files
3. Organize and report the purpose of the changes, the scope of impact, and points to watch out for in the review✅ Verify: Run
ls shared/commands/and confirm thatsummarize-pr.mdis displayed.
Step 4: Confirm the Command Works
Section titled “Step 4: Confirm the Command Works”Run the new command in Claude Code.
> /summarize-pr 123Claude fetches the content of PR #123 and starts summarizing.
✅ Verify: If Claude is seen trying to run
gh pr view 123 --json ..., the$ARGUMENTSexpansion is working correctly.
Summary
Section titled “Summary”- Commands are definitions of workflows that the user explicitly invokes. Skills are definitions of behavior that Claude loads automatically
- Command files are placed in
shared/commands/in Markdown format, and.claude/commands/is a symlink - Using
$ARGUMENTSallows additional user input to be expanded within the command - Idempotency and approval flow design are the keys to commands that can be used safely in a team
Next Steps
Section titled “Next Steps”- Skills Design Patterns — Learn how to write Skills, which are counterparts to Commands and define Claude’s automatic behavior
- Agents Spec Design — Move on to designing complex workflows using sub-agents
Frequently Asked Questions
Section titled “Frequently Asked Questions”Q: Should command files be written in .claude/commands/ or shared/commands/?
A: Write them in shared/commands/. .claude/commands/ is a symlink to shared/commands/. By writing the actual content rather than the symlink destination, Git management, team sharing, and validation by harness:check work correctly.
Q: Is there any value in a command that does not use $ARGUMENTS?
A: Yes. Commands without arguments are convenient when “executing a specific procedure the same way every time.” They are suitable for fixed routine tasks that don’t need arguments, like /sync-i18n.
Q: How do I check if a command is not being recognized?
A: First, run ls -la .claude/commands to confirm the symlink is correctly pointing to ../shared/commands. Then confirm the file exists in shared/commands/. If it still isn’t recognized, restart Claude Code.
Q: Can Commands and Skills be mixed in the same file?
A: Technically possible, but not recommended. Separating the responsibilities of Commands as “the flow the user executes” and Skills as “the definition of Claude’s behavior” improves maintainability and readability.
See the references for the external specifications and background sources used on this page.[1][2]
References
Section titled “References”- Anthropic, Claude Code documentation
- Anthropic, Claude API documentation