I’ve been using Claude Code for months, and I STILL had to look up the difference between a Skill and a Plugin last week.

Not because I’m forgetful. But because the Claude Code ecosystem has grown fast, and the naming can be confusing. “Commands” became a legacy concept. “Skills” absorbed them. “Agents” are sub-workers, not the AI itself. And “Plugins” bundle everything together into one installable package.

By the end of this post, you’ll never mix them up again. I’ll give you the mental model, real code examples, and five different analogies for each component — because one analogy never sticks for everyone, but five will.

Here’s the full map of what we’re covering:

Claude Code Components
├── CLAUDE.md ← Project memory (6 levels!)
├── Skills ← Expert knowledge modules
├── Commands ← Slash triggers (legacy, now part of Skills)
├── Hooks ← Auto-triggers on events
├── Agents ← Sub-workers (spawned, not main Claude)
└── Plugins ← Distributable bundles of all the above

The Complete Component Map

Before diving in, here’s where everything lives on disk:

your-project/
├── .claude/
│ ├── CLAUDE.md ← Project memory (alternative location)
│ ├── settings.json ← Config + hooks + permissions
│ ├── settings.local.json← Local overrides (gitignored)
│ ├── skills/ ← Expert knowledge modules
│ │ └── code-review/
│ │ └── SKILL.md
│ ├── commands/ ← Slash triggers (legacy)
│ │ └── deploy.md
│ ├── agents/ ← Sub-workers
│ │ └── researcher.md
│ └── rules/ ← Modular rules (loaded on-demand)
│ └── testing.md
├── CLAUDE.md ← Project root memory (main location)
├── CLAUDE.local.md ← Local-only memory (gitignored)
└── .gitignore

Seven things. Each has a specific job. Let’s go through them one by one.


Component 1: CLAUDE.md — Project Memory

What It Is

A Markdown file Claude reads at session start — every single session, automatically. It’s your permanent instruction set that persists across conversations so you don’t have to re-explain your project conventions each time.

Real Code

CLAUDE.md
## Project: Payments API
REST API for processing payments. Handles Stripe, PayPal, and bank transfers.
## Tech Stack
- Node.js + TypeScript + Fastify
- Prisma + PostgreSQL
- Zod for validation
## Architecture
Handler → Service → Repository → Database
## Conventions
- All async/await (no .then() chains)
- kebab-case for files, PascalCase for classes
- Service layer handles all business logic (never in handlers)
## Rules
**NEVER:**
- Commit .env files
- Put business logic in route handlers
- Access process.env outside config/index.ts

The 6 Levels You Probably Don’t Know About

Here’s the part most people miss: CLAUDE.md isn’t just one file. There are six levels of memory, loaded in order, more specific overrides broader:

LevelLocationScope
1. Managed policy/Library/Application Support/ClaudeCode/CLAUDE.mdOrganization-wide
2. User memory~/.claude/CLAUDE.mdAll your projects
3. Project memory./CLAUDE.md or ./.claude/CLAUDE.mdTeam (checked into git)
4. Project local./CLAUDE.local.mdJust you (gitignored)
5. Project rules./.claude/rules/*.mdModular, scoped by path
6. Auto memory~/.claude/projects/<project>/memory/Per-project AI notes

A couple of non-obvious behaviors worth knowing:

  • Child directory CLAUDE.md files load on-demand, not at startup
  • You can import other files with @path/to/file.md syntax (max depth 5 — don’t go deeper)
  • Rules in .claude/rules/ let you split CLAUDE.md into focused modules (e.g., testing.md, api-conventions.md)

5 Analogies

  • Soldier: The mission briefing that every soldier reads before deployment. Once written by command, relied upon by everyone.
  • Romance: Your partner’s love language manual — written once, prevents 90% of misunderstandings. Nobody wants to re-explain “no, I don’t like surprises” every morning.
  • RPG: Your character’s backstory and class abilities. The dungeon master reads it before every session so you don’t have to re-introduce yourself.
  • Corporate: The company handbook that HR gives new employees. Everything in one place so nobody has to explain the same rules 40 times.
  • Gen Z: Your “about me” pinned post. First thing anyone sees. Sets expectations. No DMs asking basic questions.

When to Use It

Always. Every project. Within the first 10 minutes of starting a new codebase. Write it once, stop repeating yourself forever.

Common Mistakes

  • Writing documentation prose instead of directives. CLAUDE.md says “do this”, README.md says “here’s what this is”
  • Being too generic (“use TypeScript” doesn’t help — “use strict mode, no any, all functions typed” does)
  • Not including a ## Rules / NEVER section — that section alone saves hours of cleanup

Component 2: Skills — Expert Knowledge Modules

What It Is

A directory (not a single file) containing a SKILL.md that defines an expert persona, what tools it can use, and how it behaves. When invoked, Claude takes on that skill’s persona and constraints.

Skills are the modern, recommended way to do everything that used to be done with standalone commands. If you’re reading old docs that only mention “commands”, know that skills are the current path.

Real Code

Directory structure:

.claude/skills/code-review/SKILL.md
---
name: "code-review"
description: "Thorough code review with security and performance focus"
user-invocable: true
allowed-tools: ["Read", "Glob", "Grep", "Bash"]
model: "sonnet"
---
# Code Review Skill
You are a senior engineer specializing in security-focused code review.
When invoked, you:
1. Read the changed files in the current diff
2. Check for security vulnerabilities (SQL injection, XSS, auth bypasses)
3. Check for performance issues (N+1 queries, missing indexes, unnecessary loops)
4. Check for adherence to project patterns (read CLAUDE.md first)
5. Output a structured review: CRITICAL > HIGH > MEDIUM > LOW
Always provide specific line numbers and suggest concrete fixes.

Once created, users invoke it as /code-review. If placed in ~/.claude/skills/, it’s available across all your projects.

The YAML frontmatter controls behavior:

  • allowed-tools — limits what Claude can do when this skill is active
  • model — can specify a different model for cost optimization
  • user-invocable: true — makes it appear as a slash command

5 Analogies

  • Soldier: Sniper school training — specialized knowledge that makes you deadly effective at one specific thing, which nobody else can do as well.
  • Romance: That one thing they learned just for you. Your partner learned to cook your favorite Vietnamese dish, watches football with you even though they hate sports. Specialized effort for a specific person.
  • RPG: Passive skill equipped to your character. “Code Review Mastery” gives +25% to finding bugs and a special “Security Scan” ability.
  • Corporate: The security team specialist on loan to your project. They have expertise and access that generalists don’t have.
  • Gen Z: That thing you’re cracked at. Not everything, just that one thing. Everyone calls you for it. “Yo, can you review my PR? You’re GOATED at this.”

When to Use It

When you have a repeatable task that needs specific expertise or tool constraints. Code review, deployment checks, documentation generation, performance profiling — anything you do more than twice is a skill candidate.

Common Mistakes

  • Creating a flat .md file instead of a directory with SKILL.md inside
  • Forgetting user-invocable: true then wondering why /skill-name doesn’t work
  • Over-restricting allowed-tools — if the skill needs to run shell commands to verify its findings, give it Bash

Component 3: Commands — Slash Triggers (Legacy)

What It Is

A .md file in .claude/commands/ that gets triggered when you type /filename. Simple, flat, no YAML frontmatter. Just instructions with an optional $ARGUMENTS placeholder for input.

Important: Commands are now considered legacy. The official recommendation is to use Skills instead. But .claude/commands/ still works, and you’ll see it in older setups, so it’s worth understanding.

Real Code

File: .claude/commands/commit.md

Review the staged git diff and write a conventional commit message.
Steps:
1. Run: git diff --staged
2. Analyze what changed and why
3. Write a commit message following: <type>(<scope>): <description>
Types: feat, fix, docs, style, refactor, test, chore
4. Run: git commit -m "<message>"
Additional context: $ARGUMENTS

Invoke with /commit or /commit fix the auth timeout issue.

5 Analogies

  • Soldier: Radio call signs. “Alpha-6, do you copy?” — one phrase triggers a specific, well-understood protocol.
  • Romance: Pet names that trigger specific actions. Say “I’m tired” and they automatically put on your comfort show and order your favorite food. No explanation needed.
  • RPG: Hotkey bindings. Press F5 to quicksave. Press Q to drink a health potion. One keystroke, pre-defined action.
  • Corporate: Speed dial on the office phone. Press 3 for Legal, press 7 for IT support. Everyone knows what each number does.
  • Gen Z: “Say less.” The whole shortcut. No explanation required. Just say it and the other person already knows exactly what’s happening.

When to Use It

Honestly, if you’re starting fresh today, just use Skills. Use Commands only when you’re maintaining an existing setup that already uses them, or if you want something truly minimal with zero YAML overhead.

Common Mistakes

  • Creating new commands in 2025 — migrate to Skills for all new work
  • Not knowing about $ARGUMENTS — you can pass context to commands just like function arguments

Component 4: Hooks — Auto-Triggers

What It Is

Scripts that run automatically when specific events happen in a Claude Code session. Configured in .claude/settings.json. No prompting required — they fire based on events.

There are 17 hook events (not just the 4 you’ll see in most tutorials). The key ones:

EventWhen It FiresUse Case
PreToolUseBefore any tool callBlock dangerous commands
PostToolUseAfter a tool succeedsAuto-lint, run tests
StopWhen Claude finishes a turnSummarize changes
SessionStartSession beginsLoad context, log session
UserPromptSubmitUser sends a messageValidate prompt format
NotificationClaude sends notificationCustom alerting
SubagentStartSubagent spawnsLog agent lifecycle
SubagentStopSubagent completesCollect agent output

There are also 3 handler types (not just shell scripts):

  • command — shell script, the classic approach
  • prompt — AI evaluates the situation and decides
  • agent — spawns a subagent as a verifier

Real Code

.claude/settings.json:

{
"hooks": {
"PreToolUse": [{
"matcher": "Bash",
"hooks": [{
"type": "command",
"command": "bash .claude/hooks/block-dangerous.sh"
}]
}],
"PostToolUse": [{
"matcher": "Edit",
"hooks": [{
"type": "command",
"command": ".claude/hooks/auto-lint.sh"
}]
}],
"Stop": [{
"matcher": "",
"hooks": [{
"type": "command",
"command": ".claude/hooks/log-session.sh"
}]
}]
}
}

The hook script receives a JSON payload on stdin:

.claude/hooks/block-dangerous.sh
#!/bin/bash
input=$(cat)
command=$(echo "$input" | jq -r '.tool_input.command // ""')
if echo "$command" | grep -qE '\brm\s+-rf'; then
echo '{"error": "BLOCKED: rm -rf is not allowed."}' >&2
exit 2 # exit 2 = block the action
fi
exit 0 # exit 0 = allow it

Exit codes matter:

  • exit 0 — success, proceed
  • exit 2 — block the action (with your error message)
  • Any other non-zero — error, but don’t block

5 Analogies

  • Soldier: Tripwires and booby traps. You don’t stand guard 24/7 — you set up automatic triggers that fire when something specific happens.
  • Romance: Automatic habits born from caring. You always kiss goodbye before leaving without thinking. She automatically turns off your gaming PC when she sees you fell asleep. Pure reflex, no decision needed.
  • RPG: Passive abilities that auto-trigger on condition. “When HP drops below 30%, automatically use a health potion.” You didn’t press anything — the game handled it.
  • Corporate: Automated approval workflows. “When a document is submitted, automatically notify the legal team.” Nobody pressed a button. It just… happened.
  • Gen Z: Auto-reply and read receipts. “Seen 9:47 PM.” You didn’t actively respond, but something happened automatically the moment a condition was met.

When to Use It

Whenever you want something to happen reliably without being prompted. Auto-lint after edits, block dangerous commands before they run, log all AI actions for audit purposes, run tests when source files change.

Common Mistakes

  • Slow PreToolUse hooks — they run synchronously and block Claude while running. Keep them under 500ms.
  • Forgetting to chmod +x your hook scripts
  • Not handling missing JSON fields — always use jq -r '.field // ""' with a default value

Component 5: Agents — Sub-Workers

What It Is

Markdown files in .claude/agents/ that define specialized sub-workers. When Claude (or you, via the Task tool) spawns an agent, it runs as a separate context with its own rules, tool access, and model settings.

Key distinction: only the main Claude thread can spawn agents. Agents cannot spawn other agents. The main thread is the orchestrator.

Project-level agents (.claude/agents/) take priority over user-level agents (~/.claude/agents/).

Real Code

.claude/agents/researcher.md:

---
description: "Research specialist for finding documentation and external references"
tools: ["Read", "Glob", "Grep", "WebSearch", "WebFetch"]
model: "sonnet"
permissionMode: "acceptEdits"
maxTurns: 20
---
# Research Agent
You are a research specialist. Your job is to find accurate, up-to-date information from external sources.
When given a research task:
1. Search for official documentation first
2. Find 2-3 reliable sources
3. Summarize findings with source URLs
4. Flag anything that looks outdated or contradictory
You do NOT write code. You do NOT make changes to files.
You research and report. That's it.

The main thread spawns this agent via:

Task(subagent_type="researcher", prompt="Find the latest Stripe webhook documentation")

The YAML frontmatter controls:

  • tools — what tools the agent can use (limits its blast radius)
  • model — can use a cheaper model for cost optimization
  • permissionMode — how it handles permission prompts
  • maxTurns — prevents runaway agents

5 Analogies

  • Soldier: Squad members with different specialties. You’re the squad leader. You send the sniper to the rooftop, the medic to the casualty, the breacher to the door. Each person has one job and stays in their lane.
  • Romance: Your wingman or wingwoman. You’re at the event. They handle the research (“I heard she likes hiking”), you handle the conversation. Different roles, same mission.
  • RPG: Party members. You’re the main character. The healer handles HP, the tank handles aggro, the DPS handles damage. You can’t do everything yourself — that’s what the party is for.
  • Corporate: Department specialists on loan. Legal reviews the contract, Finance models the revenue, Engineering scopes the work. The project manager (you) coordinates. Specialists execute.
  • Gen Z: Group chat roles. Every friend group has them: the planner, the hype person, the one who finds the best restaurant, the one who books the Airbnb. Nobody does everything. Everyone has their thing.

When to Use It

When you have a task that benefits from specialization or isolation. Research tasks that need WebSearch. Code review agents with read-only tool access. Test runners that shouldn’t touch source files. Long-running parallel work.

Common Mistakes

  • Giving agents too many tools — restrict tools to only what’s needed for the job
  • Forgetting that agents can’t spawn sub-agents (only the main thread can)
  • Setting maxTurns too high — give each agent enough turns to complete its task, not unlimited

Component 6: Plugins — Installable Packages

What It Is

A distributable bundle that packages all the other components together. One plugin can contain skills, commands, agents, hooks, MCP servers, LSP servers, and default settings — everything needed to extend Claude Code for a specific use case.

You install a plugin once and get all of its capabilities. Skills get namespaced to prevent conflicts.

Structure

my-plugin/
├── .claude-plugin/
│ └── plugin.json ← manifest (name, version, description)
├── skills/ ← knowledge modules
│ └── deploy/
│ └── SKILL.md
├── commands/ ← slash commands (legacy)
│ └── rollback.md
├── agents/ ← subagent definitions
│ └── deploy-verifier.md
├── hooks/
│ └── hooks.json ← event handlers
├── .mcp.json ← MCP server configs
├── .lsp.json ← LSP server configs
└── settings.json ← default settings

plugin.json manifest:

{
"name": "my-deploy-plugin",
"version": "1.2.0",
"description": "Deployment tools for AWS + Vercel projects",
"author": "Your Name"
}

Install with:

Terminal window
claude plugin install my-deploy-plugin
# or from a local directory:
claude --plugin-dir ./my-plugin

After installation, skills are namespaced: /my-deploy-plugin:deploy instead of just /deploy. This prevents naming conflicts when you have multiple plugins installed.

5 Analogies

  • Soldier: The complete mission kit with everything pre-loaded. One case arrives — it has the weapons, the comms gear, the maps, the vehicle keys, the mission brief. Everything in one package, nothing to source separately.
  • Romance: The complete date package someone already planned. Restaurant reservation, flowers at the door, playlist queued up, backup plan if it rains. You didn’t have to think about any of it. It just works.
  • RPG: The DLC expansion pack. You buy “Desert Warrior DLC” and immediately have: 3 new weapons, 2 new passive skills, 1 new party member, access to the desert map, and 5 new side quests. One purchase, everything included.
  • Corporate: Enterprise software suite. You buy “Salesforce” and get CRM, email integration, reporting, mobile app, and API access. Not just one tool — a whole ecosystem. Configured and ready.
  • Gen Z: That app that just works from the App Store. Download, sign in, it’s all there. Settings, themes, integrations, the whole thing. No manual setup. No “now also download this other app and connect them.”

When to Use It

When you want to share your Claude Code setup with others, when you want to publish a reusable toolset for a specific framework or workflow, or when you’ve accumulated enough skills/agents/hooks that packaging them as a unit makes sense.

Common Mistakes

  • Building a plugin when you just need a skill — plugins are for distribution, not everyday use
  • Forgetting the namespace prefix after installation (/deploy becomes /plugin-name:deploy)
  • Not specifying allowed-tools in skill frontmatter inside a plugin — plugins you distribute may run in environments you don’t control

Component 7: Permissions & File Access

What It Is

The system that controls what files Claude Code can read and write. This is often confused with a fictional .claudeignore file — .claudeignore is NOT an official Claude Code feature. It doesn’t exist.

Instead, use permissions.deny in .claude/settings.json:

{
"permissions": {
"deny": [
"Read(.env)",
"Read(.env.*)",
"Read(secrets/**)",
"Write(*.production.*)"
]
}
}

Claude Code also respects .gitignore by default (controlled by the respectGitignore setting, which defaults to true). So if something is in .gitignore, Claude Code won’t touch it unless you tell it to.

5 Analogies

  • Soldier: Classified document clearance levels. You can read everything marked SECRET or below. TS/SCI? You never even see that folder exists.
  • Romance: The topics you agreed to never bring up. “We don’t talk about the Barcelona trip.” It’s not that it doesn’t exist — it’s just off limits by mutual agreement.
  • RPG: Locked inventory slots. Some items are quest-locked, story-locked, or character-class-locked. You can see them but you can’t touch them yet.
  • Corporate: Access control policy. HR can see payroll records. Engineering can’t. It’s not a secret that payroll files exist — they’re just not in your access scope.
  • Gen Z: The blocked list, no cap. Some things are just off the table. Not hidden. Not deleted. Just: not accessible to you. Full stop.

How They All Work Together

Here’s a real scenario that ties everything together.

I type /review into Claude Code.

  1. CLAUDE.md is already loaded — Claude knows this is a TypeScript project with strict conventions and that .env files are off-limits.

  2. Skill /review activates — Claude takes on the code review persona, restricted to read-only tools, using the review-specific instructions in SKILL.md.

  3. Hook PreToolUse fires before Claude reads any file — the audit logger records what’s happening.

  4. The skill spawns an Agent to check external API documentation in parallel while it reviews the code.

  5. Permissions block Claude from reading .env.production when the review touches the config layer.

  6. Hook PostToolUse fires after Claude finishes each file read — the timing logger records performance data.

  7. Hook Stop fires when the review completes — a script formats the output into the team’s Notion template and posts it to Slack.

Everything happened automatically from one /review command.

Here’s the relationship diagram:

Plugin (distributable package)
├── Skills (knowledge + slash commands)
├── Agents (sub-workers)
├── Hooks (auto-triggers)
├── MCP/LSP servers
└── Default settings
CLAUDE.md (project memory, 6 levels)
├── Loaded at session start
└── Provides context for everything
Hooks → Independent, event-triggered, configured in settings.json
Permissions → Independent, file access control in settings.json

Quick Reference Cheat Sheet

ComponentWhat It IsLocationInvoked By
CLAUDE.mdPersistent project memory./CLAUDE.md (6 levels)Auto, every session
SkillExpert knowledge module.claude/skills/<name>/SKILL.md/skill-name command
CommandSimple slash trigger (legacy).claude/commands/<name>.md/command-name
HookAuto-triggered scriptsettings.json hooks sectionEvents (PreToolUse, etc.)
AgentSpecialized sub-worker.claude/agents/<name>.mdTask tool spawn
PluginInstallable bundle.claude-plugin/plugin.jsonclaude plugin install
PermissionsFile access controlsettings.json permissionsEnforced automatically

FAQ

What is a Claude Code skill?

A skill is a directory in .claude/skills/ containing a SKILL.md file that defines an expert persona, what tools it can use, and how it should behave. It becomes a slash command (e.g., /code-review) that activates that specialized behavior on demand. Think of it as giving Claude a specialized hat to wear for a specific task.

What is the difference between a Claude Code skill and plugin?

A skill is one focused capability (code review, deployment, documentation). A plugin is a distributable package that can contain multiple skills, agents, hooks, MCP servers, and settings. Skills are for building; plugins are for distribution. You build skills during development. You package them into a plugin when you want to share them.

What is CLAUDE.md and why do I need it?

CLAUDE.md is a Markdown file Claude reads at the start of every session. It contains your project conventions, architecture patterns, tech stack details, and rules. Without it, Claude Code starts every conversation from zero and has to re-learn your project. With it, you get consistent, project-aware output from the very first prompt — every time.

What are Claude Code hooks?

Hooks are scripts that run automatically when specific events occur — before a tool call, after an edit, when a session starts, when Claude finishes a turn. They’re configured in .claude/settings.json. Use them for auto-linting, blocking dangerous commands, logging all AI actions, and running tests after edits.

What are Claude Code agents?

Agents are specialized sub-workers defined in .claude/agents/. They run in their own context with their own tool restrictions, model settings, and instructions. The main Claude thread spawns them via the Task tool. They’re great for parallel work, specialized tasks, or operations you want to sandbox away from the main context.

How do I create a Claude Code skill?

  1. Create the directory: mkdir -p .claude/skills/my-skill
  2. Create the SKILL.md: touch .claude/skills/my-skill/SKILL.md
  3. Add YAML frontmatter and instructions:
---
name: "my-skill"
description: "What this skill does"
user-invocable: true
allowed-tools: ["Read", "Grep"]
---
# My Skill
You are a specialist in...
  1. Invoke with /my-skill

How do I control what files Claude Code can access?

Use permissions.deny in .claude/settings.json:

{
"permissions": {
"deny": [
"Read(.env)",
"Read(.env.*)",
"Read(secrets/**)"
]
}
}

Note: There is no .claudeignore file — that’s a common misconception. Claude Code also respects .gitignore automatically (this can be disabled with "respectGitignore": false in settings).


Conclusion

Here’s the one-sentence version of each component:

  • CLAUDE.md — the memory that makes Claude know your project
  • Skills — specialized expert modes you can switch on with a command
  • Commands — simple slash shortcuts (use Skills for new work)
  • Hooks — automatic scripts that fire on events, no prompting needed
  • Agents — sub-workers you spawn for parallel or specialized tasks
  • Plugins — packaged bundles of everything above, ready to distribute

The mental model that works for me: CLAUDE.md is the foundation that everything else builds on. Skills and Agents extend what Claude can do. Hooks enforce how it behaves. Plugins package it all for sharing.

Pick ONE of these today and set it up. If you don’t have a CLAUDE.md yet, start there — 10 minutes, 20 lines, and you’ll immediately see the difference. If you already have a good CLAUDE.md, write your first hook. Auto-lint on edit or block rm -rf — either one will change how you work.

Want to go deeper? Hooks are covered in detail in Claude Code Hooks: The Power Feature Nobody Talks About. CLAUDE.md is covered in Why CLAUDE.md Is the Most Important File in Your Project.


Skills, Agents, Hooks, and Plugins are covered in depth in Phase 11: Automation & Headless and Phase 15: Templates, Skills & Ecosystem of the Claude Code Mastery course. Phases 1-3 are free.