Commands vs Skills: Know the Difference, Use Both Right
Two ideas that used to feel separate, and how to think about them now.
Claude Code has changed here, so old advice can be misleading.
Historically, custom slash commands and skills were easy to describe as two separate systems:
- Commands were one-file prompt shortcuts.
- Skills were richer multi-file workflows.
That mental model is still useful, but the current docs make one thing clear: skills are now the primary extension mechanism, and custom command files have effectively been folded into the same slash-invocation world. Existing .claude/commands/ files still work, but new reusable workflows usually belong in .claude/skills/.
So the modern question is not "commands or skills?"
It is:
How much structure does this workflow need?
The Modern Mental Model
Use a simple prompt-style command when the workflow is tiny:
- A repeated instruction.
- A short template.
- A one-file checklist.
- Something you always invoke manually.
Use a skill when the workflow needs structure:
- Multiple steps.
- Supporting files.
- Scripts.
- Examples.
- Automatic discovery.
- Tool pre-approval.
- Subagent execution.
- Invocation controls.
If you are unsure and starting fresh, choose a skill. It can be as small as a command, but it can grow without moving later.
What a Legacy Command Looks Like
Legacy custom command files live in:
.claude/commands/
~/.claude/commands/
Example:
---
description: Explain a file in plain English
argument-hint: [file]
---
Explain `$ARGUMENTS` in under 200 words:
1. What it does
2. Main inputs and outputs
3. Dependencies
4. One gotcha
This creates a slash command you can invoke directly.
/explain src/services/invoices.ts
That is still useful. It is also intentionally small.
What a Skill Looks Like
Skills live in:
.claude/skills/<skill-name>/SKILL.md
~/.claude/skills/<skill-name>/SKILL.md
Example:
---
name: invoice-review
description: Review invoice-related changes for correctness, idempotency, payment safety, and missing tests.
argument-hint: [diff-or-files]
---
Review the invoice change in `$ARGUMENTS`.
Follow this process:
1. Read the changed files.
2. Identify payment state transitions.
3. Check idempotency behavior.
4. Check authorization boundaries.
5. Verify tests cover pending, paid, failed, and retried cases.
6. Return findings first, ordered by severity.
This can later grow:
.claude/skills/invoice-review/
SKILL.md
examples.md
payment-states.md
scripts/
list-invoice-tests.sh
That growth path is why skills are the better default.
Key Differences That Still Matter
A simple command is best when:
- The prompt fits comfortably in one file.
- You want explicit manual invocation.
- There are no supporting references or scripts.
- The command is mostly a text template.
A skill is best when:
- Claude should discover it automatically when relevant.
- The task has a repeatable process.
- The workflow needs examples or reference docs.
- You want helper scripts.
- You want invocation controls like
disable-model-invocation. - You want to run it in a subagent with
context: fork. - You want to pre-approve tools for that workflow.
The dividing line is not syntax. It is workflow depth.
Automatic Invocation
Skills can be available to Claude automatically. The description tells Claude when the skill is relevant.
For example:
description: Use when reviewing invoice code for payment safety and idempotency.
If you do not want Claude to invoke a skill on its own, add:
disable-model-invocation: true
Use that for deploys, commits, releases, billing actions, or anything with meaningful side effects.
Arguments
Skills and command-style workflows can accept arguments.
Use $ARGUMENTS for everything the user typed after the slash command:
Review this target: `$ARGUMENTS`
Current skills also support indexed arguments such as $0 and named arguments through frontmatter. Use those when the workflow has structured inputs.
Example:
---
name: migrate-component
description: Migrate a component between frameworks.
arguments: [component, from, to]
---
Migrate `$component` from `$from` to `$to`.
Invocation:
/migrate-component SearchBar React Vue
Tool Access
Skills can define allowed-tools to pre-approve specific tool usage while the skill is active.
Example:
allowed-tools: Bash(git status *) Bash(git diff *) Read Grep
Important nuance: this grants permission for listed tools. It is not a complete sandbox. Use permission deny rules when you need to block tools.
When to Convert a Command Into a Skill
Convert when any of these become true:
- The command grows beyond one clear page.
- You add examples.
- You need scripts.
- You want Claude to auto-discover it.
- You need invocation controls.
- You repeat the same workflow across a team.
- The prompt has turned into a checklist with real consequences.
The moment a command becomes a process, make it a skill.
Practical Examples
Use a simple command for:
- Explain this file.
- Summarize this diff.
- Draft a changelog entry.
- Apply this tiny checklist.
Use a skill for:
- Debug this class of incident.
- Review payment code.
- Run release readiness.
- Migrate a package.
- Generate and validate a report.
- Create a design review with supporting references.
The Decision Rule
Ask:
Is this a prompt, or is this a capability?
If it is a prompt, a command-style file is fine.
If it is a capability, use a skill.
In modern Claude Code, skills are the extensibility layer that can contain the command-shaped case too. Start there unless you have a reason not to.
Sources
- Extend Claude with skills
- Claude Code commands reference
- Claude Code best practices
- Create custom subagents
Part 7 of a seven-part series on using Claude Code efficiently.