Claude Code Skills vs CLAUDE.md vs Prompts: What's the Difference?
Purpose
This post explains the difference between Claude Code skills, CLAUDE.md, and system prompts. I keep seeing the three words used as if they meant the same thing, and that confusion is what makes the online “skill” files look so broken. They are not skills at all. They are system prompts mislabeled.
Direct Answer
They live at three different layers of Claude Code:
CLAUDE.mdis project-wide, always-loaded context. It holds global tone, repo conventions, and pointers to important files. It is the README for the agent.- System / system-level prompts are global, always-on instructions set by the runtime or the user. They shape the model’s persona and behavior across the whole session.
- Skills are small, named, on-demand modules the agent decides to load. Each skill is atomic, scoped, and has a clear condition under which it should fire.
Use CLAUDE.md for project rules the agent must always know. Use the system prompt for global persona and behavior. Use a skill for an atomic correction, procedure, or tool bundle that only matters in a specific situation.

I use this mental model: a system prompt and a CLAUDE.md are the always-on rails. A skill is the side-tool the agent picks up when its description matches the task.
Environment
- Claude Code (current release, with skills support)
- A project repo with
CLAUDE.mdat the root - A skills folder at
.claude/skills/<name>/SKILL.mdfor on-demand modules
What happened?
I started using CLAUDE.md for everything. I put the project stack, the lint rules, the deploy command, the bug-report template, and the “no comments in code” rule, all in one file. The file grew past 300 lines. Every conversation started by reading all 300 lines, and most of them were irrelevant to the current task.
Then I tried the other extreme. I put everything into a “skill” file that looked like a system prompt. The agent loaded it once and ignored most of it. The behavior did not change.
The problem in both cases was the same. I was using the wrong layer.
How to solve it?
I split my project config into the three layers based on one question: when does this rule need to be active?
Solution 1: Put always-on project rules in CLAUDE.md
# CLAUDE.md
## Stack- Python 3.12, FastAPI, SQLAlchemy Core (no ORM), PostgreSQL.- Use `python -m venv venv` for the virtual environment.
## Code style- No type comments. No docstrings on obvious functions.- All SQL lives in `data_access/`. Never inline raw SQL in routes.
## Logging- Console + daily rotated log files in `logs/`.The agent reads this on every turn in the repo. It costs context, but the cost is worth it because every rule here applies to every task.
Solution 2: Move per-project procedures out of CLAUDE.md and into a skill
A bad CLAUDE.md looks like this:
## Skill: deploy-to-stagingRun `rsync -avz --delete ./build/ deploy@staging:/srv/app/`.Then run `ssh deploy@staging "systemctl restart bswen-manage"`.That is a procedure, not a project rule. It only matters when the user asks to deploy. The better shape is a skill:
---name: deploy-stagingdescription: Use when the user asks to deploy the current buildto the staging server. Bundles the rsync and the service restart.---
Run, in order:
1. `rsync -avz --delete ./build/ deploy@staging:/srv/app/`2. `ssh deploy@staging "systemctl restart bswen-manage"`3. Tail `logs/$(date +%F).log` for 10 lines and paste any error into the reply.
If step 1 or 2 exits non-zero, stop and report. Do not retryautomatically.CLAUDE.md is back to project rules. The skill is loaded on demand. The agent sees the description, decides the trigger matches, and reads the body.
Solution 3: Keep persona in the system prompt, not in a skill
---name: senior-engineer-personadescription: Be a senior engineer.---
You are an expert full-stack developer with 20 years of experiencein React, Node.js, and TypeScript. Always write clean, maintainablecode.This belongs in the system prompt, not in a skill. It is a persona, not an atomic procedure. Putting it in a skill means the agent has to decide when “be a senior engineer” is the right trigger, and the answer is almost never. Move it to the system prompt or the CLAUDE.md voice section.
The reason
I think the three layers exist because they answer three different questions:
| Layer | Where it lives | When the agent sees it | Good fit | Bad fit |
|---|---|---|---|---|
| System prompt | Runtime / user | Always, session-wide | Persona, global behavior, hard rules | One-off procedures, project trivia |
CLAUDE.md | Repo root | Always, when working in the repo | Project conventions, file map, repo voice | Atomic corrections, scripts |
| Skill | .claude/skills/<name>/SKILL.md | On demand, when the agent decides the description matches | Atomic correction, procedure, script bundle | Project-wide rules, persona |
The cleanest test for “is this a skill?”:
- If it must always be on, it is
CLAUDE.mdor system prompt. - If it only matters in a specific situation, it is a skill.
- If it could be one command or one file the agent runs, it is a skill.
Why This Matters
- Cost.
CLAUDE.mdand the system prompt are loaded every turn. Putting a 200-line procedure there is expensive. Putting it in a skill is cheap, because the agent only loads it when relevant. - Discoverability. A skill’s
nameanddescriptionlet the agent pick it on its own. ACLAUDE.mdrule has no such trigger, so the model has to remember it from the always-on context. - Composability. Skills are atomic. You can copy a skill from one project to another.
CLAUDE.mdis repo-specific by design.
Common Mistakes
- Putting persona in a skill. That belongs in the system prompt or the
CLAUDE.mdvoice section. - Putting per-project rules in a skill. They will not fire on other repos. Either move them to
CLAUDE.mdor name the skill with a project prefix and accept the scope. - Putting one-off tasks in a skill. If you will only use it once, type the instruction. A skill earns its place only when the same text is re-typed more than once.
- Treating a skill as a hook. A skill is not a hook. It is content the agent reads when it decides the trigger matches.
Related Knowledge
- Skills vs slash commands. A skill is passive. The agent decides to load it. A slash command is active. The user types it. Some configs let you bind a slash command to a skill, but they are still two different mechanisms.
- Skills vs subagents. A subagent is a separate Claude session with its own context and tools. A skill is a chunk of text the current agent reads. Use a subagent when the work needs isolation, a skill when it needs a recipe.
- Skill discovery. The agent matches the skill
descriptionto the current task. Be specific. “Be a senior engineer” matches almost everything. “Use when finishing a code edit. Strips decorative comments” matches one thing, which is what you want.
Summary
In this post, I explained the difference between Claude Code skills, CLAUDE.md, and system prompts. The key point is that they live at three different layers. CLAUDE.md is always-loaded project context. The system prompt is always-loaded global behavior. Skills are atomic, on-demand, named modules the agent loads by description match. If you find yourself writing “skill” but mean “global rule” or “persona”, put it in the right layer. If you find yourself re-typing the same block of text, that is a skill.
Final Words + More Resources
My intention with this article was to help others share my knowledge and experience. If you want to contact me, you can contact by email: Email me
Here are also the most important links from this article along with some further resources that will help you in this scope:
- 👨💻 Reddit: Why are all the Claude Code skill files I see online completely pointless?
- 👨💻 Anthropic Skills documentation
- 👨💻 Anthropic Memory and CLAUDE.md guide
Oh, and if you found these resources useful, don’t forget to support me by starring the repo on GitHub!
Comments