A Guide to CLAUDE.md vs Skills vs MCP in Claude Code
TL;DR
Claude Code has three extension mechanisms: CLAUDE.md, Skills (which now subsume Commands), and MCP. CLAUDE.md is the foundation layer loaded into every session — the place to put coding conventions and build commands. Skills are the on-demand procedure / knowledge layer, supporting auto-discovery and supporting files. MCP is the protocol for connecting to external services. CLAUDE.md is the “constitution,” Skills are the “playbooks and domain knowledge,” and MCP is the “hands and feet.”
Overview of the Extension Mechanisms
As you spend more time with Claude Code, you’ll run into three extension points: CLAUDE.md, .claude/skills/, and MCP servers (.claude/commands/ has been merged into Skills). They have different roles but also overlap, which makes them easy to confuse at first.
Here’s the overall picture.
graph LR
A["User instruction"] --> B["Claude Code CLI"]
B --> C["CLAUDE.md / rules"]
B --> D["Skills / Commands"]
B --> E["MCP Servers"]
C -->|"always loaded"| F["conventions / settings / knowledge"]
D -->|"on-demand"| G["templates / reference.md"]
E -->|"communication"| H["Figma / GitHub / DB / etc."]
Viewed as layers: CLAUDE.md (foundation knowledge layer) → Skills/Commands (procedure / task layer) → MCP (external connection layer).
CLAUDE.md: The Always-Loaded Foundation Layer
CLAUDE.md is the most basic Claude Code extension. It’s loaded automatically at the start of a session and applies to all work. Think of it as the project’s “constitution.”
What to put in it:
- Coding conventions (indentation, naming)
- Frequently used commands (build, test, lint)
- Project architecture overview
- Notes on the technologies and frameworks in use
Scope hierarchy
According to the official documentation, CLAUDE.md has multiple scopes.
| Scope | Location | Sharing |
|---|---|---|
| Managed policy | /Library/Application Support/ClaudeCode/CLAUDE.md etc. | Whole organization |
| Project | ./CLAUDE.md or ./.claude/CLAUDE.md | Shared via Git with the team |
| Project rules | ./.claude/rules/*.md | Shared via Git with the team |
| User | ~/.claude/CLAUDE.md | All your personal projects |
| Local | ./CLAUDE.local.md | Personal (auto-added to .gitignore) |
More specific scopes take precedence. For example, Project rules override User memory.
Modularizing with .claude/rules/
Once CLAUDE.md gets large, you can split it by topic under .claude/rules/.
.claude/
├── CLAUDE.md # main instructions
└── rules/
├── code-style.md # coding conventions
├── testing.md # testing conventions
└── security.md # security requirements
You can also write rules that apply only to specific files via the paths frontmatter.
---
paths:
- "src/api/**/*.ts"
---
# API development rules
- Follow RESTful naming conventions
- Use a unified error format
CLAUDE.md vs Skills (knowledge type) — where to draw the line
This is where confusion sets in. Both “give Claude knowledge,” but the criterion is clear.
- CLAUDE.md = rules you want applied in every session, every task. “This project uses pnpm.” “Tests use vitest.” That kind of thing.
- Skill (knowledge type) = knowledge needed only in specific work contexts. “How to implement a Figma design.” “Style guide for writing articles.” That kind of thing.
If you stuff every kind of knowledge into CLAUDE.md (which is loaded every time), you waste context. Knowledge that’s only used in specific situations should be split out into a Skill.
Commands: The Simplest Extension
Commands are the simplest extension — just drop a Markdown file under .claude/commands/.
.claude/commands/
├── deploy.md
├── review.md
└── fix-issue.md
You invoke them manually, like /deploy. You can also receive arguments via $ARGUMENTS.
# .claude/commands/fix-issue.md
Fix GitHub issue $ARGUMENTS following our coding standards.
1. Read the issue description
2. Implement the fix
3. Write tests
4. Create a commit
That’s it. Simple, and perfectly serviceable for one-off, formulaic tasks.
Skills: The Superset of Commands
The official documentation states it plainly.
Custom slash commands have been merged into skills. A file at
.claude/commands/review.mdand a skill at.claude/skills/review/SKILL.mdboth create/reviewand work the same way. Your existing.claude/commands/files keep working.
So Commands aren’t deprecated, but they’ve been functionally absorbed into Skills. The capabilities Skills add over Commands are these.
| Capability | Commands | Skills |
|---|---|---|
Manual invocation (/name) | o | o |
| Auto-detection / invocation by Claude | x | o |
| Supporting files (templates, examples, etc.) | x | o |
Subagent execution (context: fork) | x | o |
Dynamic context injection (!`command`) | x | o |
Invocation control (disable-model-invocation) | x | o |
The most important one is auto-detection. Commands require the user to invoke them explicitly via /name, but Skills can be triggered by Claude itself based on the description field — Claude decides “this Skill applies to the situation.”
Skill directory layout
.claude/skills/
└── my-skill/
├── SKILL.md # main instructions (required)
├── reference.md # detailed reference
├── templates/ # template collection
│ └── template.md
└── scripts/
└── validate.sh # executable scripts
Basic SKILL.md form
---
name: api-conventions
description: API design patterns for this codebase
---
When writing API endpoints:
- Use RESTful naming conventions
- Return consistent error formats
- Include request validation
description is the trigger Claude uses to auto-decide. Putting the right keywords there means Claude can load the Skill in the right situations without the user having to invoke it explicitly.
Two ways to use Skills
Skill contents fall into two broad categories.
1. Knowledge / guideline type — domain knowledge Claude consults during work.
---
name: api-conventions
description: API design patterns for this codebase
---
# write your API design conventions here
2. Task execution type — a playbook for performing a specific action.
---
name: deploy
description: Deploy the application to production
context: fork
disable-model-invocation: true
---
# write your deployment procedure here
Setting disable-model-invocation: true prevents Claude from auto-invoking the skill. It’s mandatory for operations with side effects, like deploys.
MCP: Connecting to External Services
MCP is fundamentally different from Skills. Where Skills define “what Claude should know or do,” MCP defines “which external services Claude can talk to.”
sequenceDiagram
participant U as User
participant C as Claude Code
participant M as MCP Server
participant E as External service
U->>C: "Implement this Figma design in React"
C->>C: Loads Skill (implement-design)
C->>M: MCP Tool call (get_design_context)
M->>E: Figma API
E-->>M: design data
M-->>C: code + screenshots
C->>U: React component generated
This diagram captures the relationship between Skills and MCP cleanly. The Skill provides the knowledge “how to implement a Figma design,” and MCP provides the “communication channel to the Figma API.”
MCP configuration scopes
| Scope | Location | Sharing |
|---|---|---|
| Project | .mcp.json | Shared via Git with the team |
| User | ~/.claude.json | All your personal projects |
When MCP is needed
- GitHub API operations (creating PRs, fetching issues)
- Fetching Figma designs
- Running database queries
- Sending notifications to Slack, etc.
- Browser automation
Conversely, if you don’t need to talk to external services, you don’t need MCP.
A Practical Decision Flowchart
flowchart TD
A["I want to extend functionality"] --> B{"A rule that should always apply?"}
B -->|"Yes"| C["CLAUDE.md / rules"]
B -->|"No"| D{"Need external communication?"}
D -->|"Yes"| E["MCP Server"]
D -->|"No"| F{"Reference materials across multiple files?"}
F -->|"Yes"| G["Skill"]
F -->|"No"| H{"Want auto-detection?"}
H -->|"Yes"| I["Skill"]
H -->|"No"| J{"Want subagent isolation?"}
J -->|"Yes"| K["Skill (context: fork)"]
J -->|"No"| L["Command"]
Real-World Combinations
In real workflows you combine these.
Example 1: Implementing a Figma design
- CLAUDE.md: React coding conventions, component naming rules
- MCP:
figma-remote-mcp(fetch design data from Figma) - Skill:
/implement-design(procedure for converting fetched data into code)
Example 2: Code review → fix → commit
- CLAUDE.md: project test policy, lint settings
- MCP: none (purely local operations)
- Skill:
/claude-review(definition of review procedure and viewpoints)
Example 3: Authoring and running image generation prompts
- CLAUDE.md: none (no relation to project conventions)
- MCP:
nanobanana(talks to the Gemini image generation API) - Skill:
/nanobanana-prompt-writer(domain knowledge for writing high-quality prompts)
In this layout CLAUDE.md plays the “constitution” role of always providing baseline rules, MCP is the “hands and feet” hitting APIs, and Skill is the “playbook” supplying knowledge for a specific task.
Conclusion
| Criterion | Choice |
|---|---|
| Rules / knowledge that should always apply across all sessions | CLAUDE.md |
| Communication with external services required | MCP |
| Knowledge / procedure for a specific work context + auto-detection | Skill |
| Just manually invoking a simple, formulaic procedure | Command (keep existing ones as-is) |
| When creating something new | Skill (Commands are not recommended) |
Don’t stuff everything into CLAUDE.md — keep only the always-needed baseline rules there, and split context-specific knowledge into Skills. This separation is what makes efficient use of the context window. Commands are kept for backward compatibility, but there’s no reason to create new ones.
That’s all.