SlashKitsBuy

Claude Code skills vs subagents vs slash commands: when to use which

Claude Code skills vs subagents vs slash commands, compared side by side: what each one is, where it lives, and a checklist for picking the right one.

Aryan Thakor, author

9 min read

Short answer: use a skill for knowledge Claude should pull in when a task needs it, a subagent for a focused job that should run in its own context window and report back, and a slash command for a workflow you trigger on purpose. CLAUDE.md sits underneath all three as the memory that loads every session.

They overlap enough that people mix them up, and the wrong choice usually shows up as a bloated context, an agent that never gets used, or a command nobody remembers to run. Below is how I think about each one, a comparison table, concrete examples, and the mistakes I see most often.

The four pieces in one paragraph each

CLAUDE.md: always-on memory

CLAUDE.md is project memory. Claude Code loads it at the start of every session, so it's the place for things that are true all the time: how to run tests, the package manager, naming conventions, "never edit generated files". It can import other files with @path lines. Because it's always loaded, every line costs context in every conversation. That's the tradeoff to keep in mind for everything below.

Skills: knowledge that loads on demand

A skill is a folder with a SKILL.md file (frontmatter name and description) plus optional supporting files like templates, scripts, or reference docs. Skills live in .claude/skills/ (project) or ~/.claude/skills/ (user). Only the name and description are loaded up front. When the task matches the description, Claude reads the body. So you can have dozens of skills installed without paying for all of them in every session.

Subagents: a specialist with its own context

A subagent is a Markdown file with YAML frontmatter in .claude/agents/ (project) or ~/.claude/agents/ (user). The frontmatter has name, description, and optionally tools and model. The body is the subagent's system prompt. When Claude delegates to it, the subagent runs in its own context window, does the work, and returns a result to the main conversation. The main thread sees the summary, not every file the subagent read. For the full setup, see the Claude Code subagents guide.

Slash commands: workflows you trigger

A custom slash command is a Markdown file in .claude/commands/ (project) or ~/.claude/commands/ (user). The file name is the command name, so ship.md becomes /ship. It runs as a prompt in the main thread, can take arguments through $ARGUMENTS or positional placeholders (zero-based $0, $1 in current versions), can pull in files with @path, and can include shell output with a ! prefix if allowed-tools permits Bash. The details are in how to write a Claude Code slash command.

Comparison table

CLAUDE.mdSkillSubagentSlash command
Who triggers itAlways loadedClaude, when the description matchesClaude (by description) or you, by askingYou, by typing /name
Where it livesProject root (and user-level).claude/skills/<name>/SKILL.md.claude/agents/<name>.md.claude/commands/<name>.md
File formatPlain MarkdownFolder with SKILL.md + optional filesMarkdown + YAML frontmatterMarkdown, optional frontmatter
ContextMain thread, every sessionMain thread (or the agent using it), only when relevantIts own context windowMain thread
Typical sizeShort, a page or twoMedium to large, can reference extra filesMedium system promptShort to medium prompt
Best forFacts true in every sessionDomain knowledge and patternsFocused, isolated jobsRepeatable workflows

The row that matters most is context. Skills and commands run in the conversation you're already in. Subagents don't, which is both their strength and their main limitation.

When to use a skill

Use a skill when Claude needs to know how to do something in a specific domain, and that knowledge isn't relevant to most sessions.

Example: a stripe-integration skill. It holds your patterns for webhooks, idempotency keys, how you map Stripe customers to users, which events you handle, and maybe a reference file with your webhook handler template. You don't want that in CLAUDE.md, because 90% of your sessions have nothing to do with billing. As a skill, it costs a line of description until someone asks Claude to "add a refund flow".

md
---
name: stripe-integration
description: Patterns for Stripe payments in this codebase. Use when working on checkout, subscriptions, webhooks, refunds, or anything that touches the Stripe API.
---

# Stripe integration

- All webhook handlers live in `src/billing/webhooks/` and verify the signature first.
- Every write to Stripe passes an idempotency key derived from our internal order id.
- Customer records map 1:1 to `users.stripe_customer_id`. Never create a customer without saving it there.

See `webhook-template.ts` in this folder for the handler shape.

Good skill topics: a framework's conventions, an internal API, a deployment process, a writing style, a design system. If it reads like a reference doc, it's probably a skill.

When to use a subagent

Use a subagent when the job is self-contained, produces a lot of intermediate noise, and only the conclusion matters to the main thread.

Example: a security-auditor reviewing a diff. It needs to read the changed files, chase imports, check how input is validated, maybe grep for similar patterns. That's a lot of file contents you don't want sitting in your main conversation. In its own context, it can dig through all of it and hand back a short list of findings.

md
---
name: security-auditor
description: Reviews code changes for security issues. Use proactively after changes to auth, input handling, file access, or anything that touches user data.
tools: Read, Grep, Glob, Bash
model: inherit
---

You are a security reviewer. Look at the current diff (`git diff` and staged changes).
For each issue, report: file and line, severity (high/medium/low), what an attacker could do, and the fix.
Do not edit files. If you find nothing, say so plainly.

Restricting tools matters here. A reviewer that can't write files can't "helpfully" rewrite your auth module. You can also call it explicitly: "use the security-auditor agent on this branch".

Good subagent jobs: code review, test-failure triage, researching how something works across a large codebase, running a checklist and reporting pass/fail. The pattern is "go look at a lot of stuff, come back with a verdict".

When to use a slash command

Use a slash command when you have a workflow you run on purpose and want it to run the same way every time.

Example: /ship. You don't want Claude deciding on its own when to run your release checks. You want to type /ship when you think you're done and get the same sequence every time: tests, typecheck, lint, build, then a clear yes or no.

md
---
description: Run release checks before shipping
allowed-tools: Bash(npm run test:*), Bash(npm run typecheck), Bash(npm run lint), Bash(npm run build), Bash(git status:*)
---

Current changes:
!`git status --short`

Run, in order: `npm run test`, `npm run typecheck`, `npm run lint`, `npm run build`.
Stop at the first failure and report it with the relevant output.
If all pass, reply with SHIP and a one-line summary of what changed. Otherwise reply BLOCK and list what to fix.

Another example is /build-feature $ARGUMENTS: take a feature description, plan it, implement it, review it, and run the release checks. That's a workflow, and a command is the natural way to express "do these steps in this order when I ask". The release-check idea is covered more fully in adding a release gate to Claude Code.

How they combine

The three aren't alternatives so much as layers:

  • Commands orchestrate. A command runs in the main thread, so it can call several subagents in sequence and pass results between them.
  • Subagents do the focused work. Each one handles a step in its own context and returns a summary.
  • Skills supply the knowledge. Whoever is doing the work, main thread or subagent, pulls in a skill when the task matches.

There's a structural reason for this shape: subagents can't spawn other subagents. If you want plan, then implement, then review, then release check, something in the main thread has to walk that chain. A slash command is the cleanest way to write that down.

This is how I set up /build-feature in SlashKits: the command runs in the main thread, asks a tech-lead agent for a plan, hands each step to the right specialist agent, and finishes with a shipper agent that runs the checks and returns SHIP or BLOCK. The specialists use skills where they apply.

A note on skills and slash commands converging

In recent Claude Code versions, skills can also be invoked directly with a slash, and .claude/commands/ keeps working alongside them. So the line between "skill" and "command" is getting thinner in practice. Check the docs for your version to see exactly how it behaves.

I still find the distinction useful as a design question. Should Claude reach for this automatically when relevant (skill with a good description), or do I want to trigger it deliberately (command)? The answer shapes how you write the file.

Decision checklist

Run through these in order and stop at the first yes:

  1. Is it true in every session and short? Put it in CLAUDE.md.
  2. Do I want to trigger it myself, as a repeatable sequence of steps? Slash command.
  3. Does it involve reading a lot of material where only the conclusion matters? Subagent.
  4. Should it run with restricted tools, or a different model, than the main thread? Subagent.
  5. Is it reference knowledge for a specific domain that most sessions don't need? Skill.
  6. Does it need to coordinate several specialists? Slash command that calls subagents.

If two answers fit, you often want both: a skill that holds the knowledge and a command or agent that applies it.

Common mistakes

A giant CLAUDE.md

Everything goes into CLAUDE.md because it's the first file people learn about. Six months later it's 800 lines of billing rules, deploy steps, and style notes, all loaded into every session. Move the domain-specific parts into skills and keep CLAUDE.md to what is always relevant. If a section starts with "when working on X", it probably belongs in a skill.

A subagent for work that needs main-thread context

A subagent starts with a fresh context. It doesn't see the 40 messages where you and Claude worked out the approach. If you delegate "finish the refactor we discussed" to a subagent, it has to rediscover everything, or it guesses. Keep work that depends on the conversation in the main thread, and give subagents tasks that can be described in a paragraph.

A command that tries to be a knowledge base

A /stripe command with 300 lines of patterns only helps when you remember to type it. Worse, it dumps all 300 lines into the main thread each time. That content should be a skill, so it loads when the task calls for it. Keep commands about steps, and let them lean on skills for the how.

Vague descriptions, so nothing triggers

Skills and subagents are chosen by their description. "Helps with code" matches everything and therefore nothing in particular. "Backend helper" won't get picked when you ask about a webhook. Write descriptions that name the tasks and keywords that should trigger them:

text
Weak:   description: Security expert.
Better: description: Reviews code changes for security issues. Use proactively after changes to auth, input handling, file uploads, or SQL queries.

If an agent never gets used, the description is the first thing to fix. Phrases like "use proactively" encourage Claude to delegate without being asked.

Where to start

Pick the job you keep repeating. Explaining the same patterns over and over? Write a skill. Asking for the same review? Make it a subagent. Typing the same five-step instruction? Make it a command.