·10 min read

Claude Code Skills vs Commands vs Subagents

Claude Code skills vs commands vs subagents, explained: how each mechanism works, what it costs in context, and when to reach for hooks instead.

Claude Code has four extension mechanisms -- skills, slash commands, subagents, and hooks -- and they overlap just enough to be confusing. Here is the short answer on Claude Code skills vs commands vs subagents: skills are knowledge the model loads itself when a task looks relevant, slash commands are prompts you invoke explicitly, and subagents are delegated workers with their own separate context window. Hooks are the fourth piece: shell commands that fire deterministically on lifecycle events, whether or not the model agrees.

The differences come down to three questions: who triggers it (the model, you, or an event), where it runs (your main context or a separate one), and whether it is guaranteed to happen (probabilistic or deterministic). Get those three straight and every Claude Code customization decision becomes mechanical. This post walks through each mechanism with working examples, then ends with a decision matrix and a pattern for combining all four.

Claude Code skills vs commands vs subagents at a glance

MechanismInvoked byLives inRuns inBest for
SkillsThe model, when relevant.claude/skills/<name>/SKILL.mdMain context, loaded on demandDomain knowledge, conventions, procedures
Slash commandsYou, explicitly (/name).claude/commands/<name>.mdMain contextRepeatable prompts and workflows
SubagentsThe model (or you, on request).claude/agents/<name>.mdSeparate context windowLarge isolated tasks, parallel work
HooksLifecycle events, automatically.claude/settings.jsonOutside the model, as shell commandsGuaranteed checks, formatting, guardrails

One more axis worth internalizing: reliability. Skills and subagents depend on the model deciding to use them. Slash commands run when you type them, but what happens next is still up to the model. Hooks are the only mechanism with a hard guarantee -- they execute as code, not as instructions.

Skills: model-invoked knowledge

A skill is a folder containing a SKILL.md file with YAML frontmatter. The frontmatter description is the trigger: Claude Code loads skill names and descriptions at startup, and when a task matches a description, it pulls the full skill body into context. This progressive disclosure is the whole point -- you can maintain dozens of skills and pay almost nothing in tokens until one is actually needed.

---
name: postgres-migrations
description: Conventions for writing and applying Postgres migrations in this repo. Use when creating, editing, or reviewing database migrations.
---

# Postgres migrations

- Generate migrations with `pnpm db:generate`; never hand-edit an applied migration.
- Set column values explicitly in inserts; do not rely on database defaults.
- Every destructive change ships in two releases: deprecate first, drop later.

Skills can be more than one file. A skill folder can bundle reference docs, scripts, and templates alongside SKILL.md, and Claude reads the extra files only when it needs them. That makes skills the right home for anything too large or too situational for CLAUDE.md, which is loaded into every session unconditionally.

When to use skills in Claude Code

Reach for a skill when the knowledge is conditional: it matters a lot for some tasks and not at all for others. Migration conventions, a release checklist, the internal API your team keeps misusing, a testing recipe -- all skills. If Claude needs it every single session, put it in CLAUDE.md instead. If you need it to happen on demand at a moment you choose, that is a slash command. The full setup, including personal vs project scope and debugging descriptions that never trigger, is in our Claude Code skills guide.

Skills are also the most portable of the four mechanisms. A skill published to localskills.sh installs into .claude/skills/ for Claude Code, and the same published package also generates .cursor/rules for Cursor or .windsurf/rules/ for Windsurf -- one source of truth, every tool-native format written for you.

Slash commands: user-invoked shortcuts

Claude Code slash commands are markdown files in .claude/commands/. The filename becomes the command: .claude/commands/fix-issue.md becomes /fix-issue. When you run it, the file contents are injected as the prompt, with $ARGUMENTS replaced by whatever you typed after the command.

---
description: Fix a GitHub issue by number
allowed-tools: Bash(gh issue view:*), Read, Edit
---

Fix GitHub issue #$ARGUMENTS.

1. Run `gh issue view $ARGUMENTS` and read the full issue.
2. Locate the relevant code and implement a fix.
3. Add a regression test that fails without the fix.

The defining trait is who pulls the trigger. A skill activates when the model judges it relevant, which is powerful but probabilistic. A slash command activates when you type it, which makes it the right shape for workflows with a clear human decision point: "review this PR now," "cut a release now," "generate tests for this module now."

The failure mode to avoid is stuffing reference knowledge into commands. If you find yourself running /conventions at the start of every session to remind Claude how your codebase works, that content wants to be a skill or CLAUDE.md entry -- knowledge should load itself. Commands shine for verbs, not nouns. Our custom slash commands guide covers parameterized templates and team-shared command libraries in depth.

Subagents: delegated context windows

A subagent is a separate Claude instance with its own context window, its own system prompt, and optionally its own tool allowlist and model. You define one as a markdown file in .claude/agents/:

---
name: code-reviewer
description: Reviews code changes for correctness, security, and style. Use proactively after significant edits.
tools: Read, Grep, Glob, Bash
---

You are a senior code reviewer.

1. Run `git diff` to see what changed.
2. Check for correctness bugs, security issues, and convention violations.
3. Report findings grouped by severity with file and line references.

The main agent delegates to a subagent based on its description (or when you ask explicitly), the subagent works in isolation, and only its final report comes back to the main conversation. That isolation is the feature and the cost, in equal measure:

  • Feature: a subagent can grind through thousands of lines of build logs or a 40-file refactor scan without polluting your main context. Several subagents can run in parallel.
  • Cost: the subagent cannot see your conversation history, and you cannot see its intermediate reasoning. Everything it needs must be in its system prompt or its task description, and everything you get back is its summary.

Use subagents for work that is context-heavy and separable: codebase-wide audits, log analysis, research across many files, review passes. Skip them for quick edits -- spinning up a fresh context to change three lines costs more than it saves. The Claude Code subagents guide goes deeper on tool restrictions, model selection per agent, and parallel dispatch patterns.

Hooks: deterministic enforcement

Skills, commands, and subagents all ultimately rely on the model choosing to comply. Claude Code hooks do not. A hook is a shell command bound to a lifecycle event -- PreToolUse, PostToolUse, UserPromptSubmit, Stop, and others -- configured in .claude/settings.json. The hook runs every time the event fires. No judgment call, no probability.

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write"
          }
        ]
      }
    ]
  }
}

This example formats every file Claude edits, immediately, with no prompt tokens spent asking. A PreToolUse hook that exits with code 2 blocks the tool call and feeds its stderr back to Claude -- which is how you build real guardrails: block edits to generated files, forbid rm -rf, require tests to pass before a Stop event lets the session end.

The rule of thumb: if a behavior must happen 100% of the time, it belongs in a hook, not in prose instructions. "Always run the linter" in CLAUDE.md is a suggestion; a PostToolUse lint hook is a law. See the Claude Code hooks guide for the full event list and blocking semantics.

Decision matrix: Claude Code skills vs commands vs subagents

You want...Use
Claude to apply conventions without being askedA skill
A repeatable workflow you trigger at a moment you chooseA slash command
Heavy, separable work that would flood your main contextA subagent
A check or transformation that must happen every timeA hook
Context that applies to literally every sessionCLAUDE.md, not any of the four

Three quick tiebreakers for the common gray areas:

  1. Skill vs command: who should decide the timing? Model decides -- skill. You decide -- command.
  2. Command vs subagent: does the work need your conversation's context? Yes -- command (it runs in the main context). No, and it will generate a lot of noise -- subagent.
  3. Anything vs hook: is "usually" good enough? If a miss is annoying, use instructions. If a miss is unacceptable, use a hook.

Combining all four in one workflow

The mechanisms compose, and mature setups use them together. A realistic review pipeline:

  1. A /review slash command gives you the explicit entry point after you finish a change.
  2. The command's prompt tells Claude to delegate to the code-reviewer subagent, so a 2,000-line diff analysis never touches your main context.
  3. The subagent's system prompt points at your team's review skill, which encodes what "good" means in your codebase -- severity rubric, known false positives, conventions to enforce.
  4. A PostToolUse hook runs the formatter and linter on anything the fix-up pass edits, deterministically.

Each layer does the one job it is structurally best at: the command handles intent, the subagent handles isolation, the skill handles knowledge, the hook handles enforcement.

FAQ

Can a slash command trigger a subagent or a skill?

Yes. A command file is just a prompt, so it can instruct Claude to delegate to a named subagent, and any skill whose description matches the resulting task can still load. This is the standard way to give model-invoked machinery a human-invoked entry point.

Do skills and commands consume my context window?

Commands consume tokens only when you run them. Skills are cheaper than they look: only the name and description are loaded up front, and the body loads on demand. Subagents are the real context play -- their work happens in a separate window entirely, with only the summary returned.

Should shared team conventions be a skill or CLAUDE.md?

Both have a place. CLAUDE.md is for the small, always-relevant core; skills are for conditional depth. For conventions shared across a team -- especially one using Cursor or Windsurf alongside Claude Code -- publishing skills to a registry beats copying files between repos: skills on localskills.sh are versioned with rollback, and one localskills install writes each tool's native format.

Are hooks safer than instructions?

For enforcement, yes -- hooks execute deterministically outside the model. But they run arbitrary shell commands with your permissions, so review any hook before adding it, especially from third-party config you did not write.


Skills are the most shareable of the four mechanisms -- publish yours once and install it into Claude Code, Cursor, and Windsurf from a single source of truth. Create a free localskills.sh account to get started.

npm install -g @localskills/cli
localskills login
localskills install your-org/your-first-skill --target claude cursor