Skip to content
LinkedInX

Custom Commands Deep Dive — Differences from Skills and Best Practices

About 5 minutes

Target audience: Those who understand Level 3 (custom command basics) and Level 4 (CLAUDE.md hierarchy) and want to design reusable commands in a production harness.
Prerequisites: The mechanism of `.claude/commands/` and how to invoke `/command`

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.

AspectCommands (/command)Skills (SKILL.md)
TriggerThe user types /commandClaude automatically judges based on the situation
InvocationExplicit and intentionalImplicit and automatic
PurposeExecute a fixed workflowDefine behavior according to context
File locationshared/commands/*.mdshared/skills/*/SKILL.md
Template variables$ARGUMENTS is availableNone

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.


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.

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.


Command names should start with a verb so it is clear at a glance what they do.

Good exampleExample 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.

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 note

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 new

Include 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?
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/commands

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 run commands, and fact-check instructions, the read was successful.

Launch Claude Code and run the command.

> /blog Introduction to Claude Code Harness

Claude 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 that summarize-pr.md is displayed.

Run the new command in Claude Code.

> /summarize-pr 123

Claude fetches the content of PR #123 and starts summarizing.

✅ Verify: If Claude is seen trying to run gh pr view 123 --json ..., the $ARGUMENTS expansion is working correctly.


  • 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 $ARGUMENTS allows 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

  • 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

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]

  1. Anthropic, Claude Code documentation
  2. Anthropic, Claude API documentation
Quiz