Comparison

Skills vs Subagents vs Slash Commands vs CLAUDE.md: What Goes Where

Four ways to give a coding agent instructions, and one question that decides between them: what can you afford to have in context on every single turn? A practical map, with the context-window arithmetic.

By Michał Jaskólski Updated 13 min read
  1. 01 Software Design software-design-philosophy Reducing complexity through thoughtful software design

After a few weeks with a coding agent you hit the same problem everyone else does: a dozen things the agent should do differently, and four plausible places to write each of them down. Does the deploy checklist go in CLAUDE.md? Is it a slash command? Should test-failure triage run in a subagent? When does a section of project instructions become a skill?

These get treated as four unrelated features because they arrived at different times and live on different documentation pages. They aren’t. They are four points on one axis — how much of the context window this costs you, and when — and once you see the axis, the choice is usually obvious.

  • Project instructions (CLAUDE.md and its .claude/rules/ cousin) are always-on: loaded in full, every session, before you type anything.
  • A skill is on-demand: its description sits in context so the model knows it exists, and the body arrives when the task matches.
  • A slash command is a skill you fire yourself instead of letting the model decide.
  • A subagent is a second context window — delegated work somewhere you can’t see, returning a summary.

If you want the other comparison — instructions versus connections — see Claude skills vs MCP; if you haven’t met the skill format at all, start with what an AI agent skill is.

One scoping note. The SKILL.md format is an open standard implemented across many agents. Subagents, slash commands and CLAUDE.md are, in the forms described here, Claude Code features; other agents have analogues (AGENTS.md being the obvious one) with different loading rules. Details specific to Claude Code, or likely to move between versions, are flagged.

What is the actual difference between them?

Project instructionsSkillSlash commandSubagent
What it isStanding facts and rulesPackaged procedure or referenceA skill you trigger by nameDelegated work in its own context
Lives inCLAUDE.md, .claude/rules/.claude/skills/<name>/SKILL.mdThe same file, with model invocation off.claude/agents/<name>.md
Who triggers itNobody — it’s just thereThe model when relevant (or you, by name)You, by typing /nameThe model, by delegating
Context windowYoursYoursYoursIts own, fresh
Cost at restFull text, every sessionName and description onlyNothingNothing
Cost when usedBody enters context and staysBody enters context and staysOnly the returned summary
Sees your conversationn/aYesYesNo, unless it forks it
Portable beyond Claude CodePartly (AGENTS.md)Yes, open standardVaries by agentVaries by agent
Best atShort, always-true factsProcedures worth finding automaticallyActions with side effects you want to timeWork whose output you’ll never re-read

Read the “cost at rest” row twice. That is the row that decides most arguments.

Always-on context is a tax you pay on every turn. On-demand context is a bet that your description is good enough to win the trigger.

Skills vs CLAUDE.md: what belongs in each?

CLAUDE.md files load into the context window at the start of every session. Claude Code walks up the directory tree from where you launched it, collects every CLAUDE.md and CLAUDE.local.md it finds, and concatenates them — root first, closest to your working directory last. Files in subdirectories are the exception: those load on demand, when the agent reads a file there.

The consequence is a hard budget. Anthropic’s guidance is to target under 200 lines per file, and the stated reason is worth quoting precisely: longer files “consume more context and reduce adherence.” Not just cost — adherence. A 900-line CLAUDE.md is not a more thoroughly instructed agent, it is a diluted one. The @path import syntax helps you organise a large file into several, but it does not help you pay for it: imported files load at launch alongside the file referencing them.

So the division is about frequency of relevance, not importance.

Belongs in CLAUDE.md: the build command. The test command. The package manager you use and the one you don’t. Where handlers live. The two or three conventions that differ from tool defaults and that the agent would otherwise get wrong every time.

Belongs in a skill: the release procedure. The incident runbook. The review checklist. Anything that is a sequence rather than a fact, and anything long enough to blow the 200-line budget alone. Claude Code’s documentation makes the trigger explicit: create a skill when “a section of CLAUDE.md has grown into a procedure rather than a fact.”

There is a middle option most people miss: .claude/rules/ files accept a paths: frontmatter field of glob patterns, and a rule scoped that way loads only when the agent works with matching files — your React conventions arrive when it touches src/**/*.tsx and cost nothing otherwise. If your CLAUDE.md is bloated because half of it applies to one directory, that is the fix, not a skill.

Nearby sits auto memory — notes the agent writes itself, whose index also loads at the start of every conversation up to a documented limit (the first 200 lines or 25 KB). It is on the always-on side of the axis, and worth auditing for that reason.

Skills vs slash commands: are they still separate things?

This is the question with the most out-of-date answers on the internet, so here is the documented current state: in Claude Code, custom slash commands have been merged into skills. A file at .claude/commands/deploy.md and a skill at .claude/skills/deploy/SKILL.md both create /deploy and work the same way. Existing command files keep working; if both exist under one name, the skill wins.

What used to be the difference — “a skill is something the model picks up, a command is something you type” — is now a frontmatter field rather than a separate mechanism:

  • disable-model-invocation: true — only you can invoke it. This is the pure slash-command shape, and it has a property worth noticing: the description is not loaded into context at all. The model doesn’t know it exists until you run it. Resting cost: zero.
  • user-invocable: false — only the model can invoke it. For background knowledge that isn’t a meaningful action for a human to take. “Explain how the legacy billing system works” is not a command anyone types.
  • Neither field, the default — both of you can. Description in context, body on invocation.

That first bullet is the real reason to still think in terms of commands. It is what you choose when the thing has side effects and you want to control the timing: you do not want the agent deciding, unprompted, that the code looks ready and it will now deploy. /deploy, /commit, /release — turn model invocation off and you get a zero-context-cost action that fires exactly when you say so.

The command ergonomics survived the merge. Arguments arrive as $ARGUMENTS, or positionally as $1, $2, and shell output can be injected into the prompt before it is sent — so a /pr-summary skill arrives with the actual diff in it rather than instructions to fetch one.

The caveat: this merge is a Claude Code behaviour and a recent one. Other agents implement SKILL.md but structure their command layer differently. For a mixed team, keep the content in the skill body — the portable part — and treat invocation frontmatter as per-agent configuration.

Skills vs subagents: when do you need a separate context window?

Everything above shares one context window: yours. A subagent is the one mechanism that doesn’t. It runs “in its own context window with a custom system prompt, specific tool access, and independent permissions,” and returns a result to your conversation.

The decision is not about complexity or specialisation. It is about output volume versus follow-up need.

Reach for a subagent when the work produces a lot of text you will never look at again: a full test run, a codebase-wide grep for every call site, twelve files read to answer one question. The verbose output stays in the subagent’s context and only the conclusion comes back — worth a great deal, because a single unlucky grep can cost more of your window than the entire conversation preceding it.

Stay in the main conversation when the task needs iteration. Claude Code’s guidance is direct: use the main conversation when “the task needs frequent back-and-forth or iterative refinement,” when “multiple phases share significant context,” when the change is quick and targeted, or when latency matters — subagents start fresh and need time to gather context your session already has.

There is a design lens here that is more useful than it sounds. In A Philosophy of Software Design, a deep module hides significant implementation behind a simple interface; a shallow one wraps very little behind an interface costing more to learn than it saves. A subagent is a module whose interface is its description going in and its summary coming out. One that reads forty files and returns six lines is deep. One that reads a single file and returns its contents is shallow — you paid startup latency and a fresh context to move a Read call somewhere else.

Prompt

Use the software-design-philosophy skill to review my agent configuration against deep-versus-shallow module principles — treat each skill and subagent as a module whose interface is its description going in and its summary coming out, and tell me which ones hide real complexity and which are shallow pass-throughs I should collapse back into the main conversation

Software Design

What actually reaches a subagent?

This is where most subagent disappointment comes from, so precision helps. A subagent does not inherit your conversation. The documentation is blunt: non-fork subagents “start with a fresh, isolated context window” and “don’t see your conversation history, the skills you’ve already invoked, or the files Claude has already read.”

What it does start with, per the docs: its own system prompt, the task message, CLAUDE.md files, git status, any skills preloaded through its skills frontmatter field, and a roster of its sibling agents. Output style, the main conversation’s auto memory and the context window size are named as things that never reach it.

Three consequences:

  1. The task message is the whole briefing. File paths, constraints, what “done” looks like. Half-instructed subagents produce confidently irrelevant work, and you don’t find out until the summary arrives.
  2. What isn’t in the summary is gone. The reasoning, the files read, the dead ends ruled out: discarded when it finishes.
  3. Project instructions travel; loaded skills don’t. That is what the skills frontmatter field is for — and note it behaves differently from a normal session, injecting the full skill content at startup rather than only the description.

The other configuration worth knowing is context: fork, which flips the relationship. Instead of a subagent that pulls in a skill, you write a skill that runs as a subagent: its body becomes the prompt driving a fresh context. Neat when a procedure is both well-specified and noisy — a research sweep, a broad audit — because you get isolation without a separate agent definition to maintain.

There are limits. Claude Code caps nesting depth (three layers below the main conversation by default) and concurrency (20 running subagents). Both defaults have moved before; check the current docs rather than designing around a number from an article.

How much context does each one really cost?

Rough shape, in the order you should worry about them:

Project instructions: full price, every session, forever. Every line of every CLAUDE.md in your path is in the window before your first message. This is the only one of the four with no on-demand story at all, which is why the 200-line target exists and why path-scoped rules are worth the setup.

Skills: near-zero at rest, then persistent. Description only until triggered — but once a skill’s content loads in Claude Code it stays in the conversation for the rest of the session rather than unloading when the task moves on. Compaction handles this with a budget: recent invocations are re-attached after a summary, truncated per skill, under a shared cap, filled from the most recent backwards, so in a long session the older ones quietly stop coming back. Either way: keep bodies short, and put long reference material in separate files the agent reads only when it needs them.

Slash commands with model invocation disabled: free until used. Nothing at rest, not even the description. Twenty operational procedures that only a human should ever start can all sit there for zero tokens.

Subagents: nothing at rest, and the whole point is what they don’t charge you. The cost is elsewhere — latency, because they start cold, and tokens spent rediscovering context your main conversation already had.

One correction to a common intuition: none of this is really about token price. It is about attention. A window stuffed with instructions that don’t apply to the current task makes the model worse at that task, independently of cost — which is the real argument for on-demand loading, and why the 200-line guidance talks about adherence rather than dollars.

How do they combine?

The good setups all look roughly the same:

CLAUDE.md names the map, skills hold the territory. A short line — “release procedure: use the /release skill” — costs a few tokens every session and buys reliable discovery of a 300-line procedure that costs nothing until the day you release.

Skills carry the knowledge, subagents carry the noise. A code-review subagent whose skills field preloads your review conventions beats either alone: the conventions live in one reviewable file your main conversation can also use, and the review’s file-reading happens where you never see it.

And none of them is enforcement. This is the most important sentence here. CLAUDE.md content is delivered as a message the model reads, not a hard constraint — the docs say plainly that there is “no guarantee of strict compliance.” Skills are the same: context, which shapes behaviour rather than binding it. If a rule must hold no matter what the model decides, the answer is a hook or a permission deny rule, which run as client-side machinery regardless of what the model concludes. Writing it in bolder capitals is not a substitute, and the failure mode is that it works nine times out of ten — exactly often enough to lull you.

Which one should I reach for?

Stop at the first line that matches:

  1. It must hold regardless of what the model decides. Not one of these four. Use a hook or a permission rule.
  2. It’s a one-line fact that’s true in every session — the build command, the package manager, a naming convention. CLAUDE.md.
  3. It’s a fact that’s only true for part of the codebase. A .claude/rules/ file with paths: frontmatter.
  4. It’s a multi-step procedure you want the agent to find on its own. A skill. Spend your effort on the description — that is the entire discovery mechanism.
  5. It’s a procedure with side effects, and you want to choose the moment. A skill with disable-model-invocation: true. Free until you type it.
  6. It generates output you’ll read once and never again. A subagent, or a skill with context: fork.
  7. You’d need to iterate on the result three times. None of them — just do it in the main conversation.

The most common mistake we see is rule 2 swallowing rule 4: a CLAUDE.md that grew to 600 lines because every procedure got appended to it. The tell is that adherence gets worse as the file gets longer — which feels like the model ignoring you, and is actually you having diluted the instructions that mattered. Move the procedures out; the file gets shorter and the agent gets better at the same time.

Frequently asked questions

Are slash commands deprecated in favour of skills?

In Claude Code they have been merged rather than deprecated. A file in .claude/commands/ still works and still produces a slash command; a skill directory produces the same command plus a folder for supporting files, frontmatter controlling who can invoke it, and automatic loading when the model judges it relevant. If a command and a skill share a name, the skill wins. Existing command files need no migrating, but new work belongs in a skill directory.

Does a subagent see my CLAUDE.md?

Yes. Project instructions are part of what a subagent starts with, alongside its own system prompt, the task message, git status, any preloaded skills, and a roster of its sibling agents. What it does not get is your conversation history, the skills you already invoked, or the main conversation’s auto memory. Two built-in Claude Code agent types, Explore and Plan, deliberately skip project instructions and git status to keep their startup context small — so a research subagent may know less about your project than you assume.

Is a skill just a longer CLAUDE.md?

No, and the difference is when it loads. Project instructions are read in full at the start of every session whether or not they are relevant, which is why the guidance is to keep them under about 200 lines. A skill’s body loads only when the task matches its description, so a 400-line procedure costs almost nothing on the days you are not running it. Claude Code’s rule of thumb: facts that hold every session go in project instructions, anything that has become a multi-step procedure moves to a skill.

When is a subagent the wrong choice?

When you will iterate on the result. A subagent starts with a fresh context, paying latency and tokens to rediscover things your main conversation already knows, and everything it learned that is not in its summary is discarded. If your next message is “no, do it differently,” you have thrown away the state that would have made that cheap. Subagents pay off when the work is self-contained, verbose, and finished when it returns.

Do these concepts exist outside Claude Code?

Skills do, as an open standard implemented by a long list of agents. The other three are shakier. Most agents have some notion of always-on project instructions, often AGENTS.md — Claude Code reads CLAUDE.md instead, and the documented workaround is a CLAUDE.md importing the other file so both tools read the same content. Sub-agent delegation and user-triggered prompt templates exist elsewhere under different names, with materially different loading and isolation rules. Treat the skill body as the portable asset and everything else as per-agent configuration.

How do I know if my setup is too heavy?

Look at what is in the window before you type anything. If project instructions plus rules plus the memory index take a meaningful slice of context before the conversation starts, that is a slice you cannot spend on the task — and adherence drops as the pile grows. The usual fixes, in order: move procedures into skills, scope directory-specific rules with paths: frontmatter, turn off model invocation on skills only a human should start, and delegate anything producing output you will not re-read.

Where to go next

If the answer is “write a skill,” how to write an agent skill covers the format and the ways descriptions fail to trigger, and installing skills in Claude Code covers getting one loaded. If the missing piece might be a connection to an external system rather than instruction, that’s skills vs MCP. And our library packages canonical engineering and business books as skills:

npx skills add wondelai/skills --all --global

Primary sources for the specifics above: Claude Code skills, subagents, memory and project instructions, and the Agent Skills specification. Loading behaviour, defaults and limits change between versions; where this article and the docs disagree, the docs are right.

Work with us

We build the skills you already use. Now we’ll build yours.

Custom skills · Subagents · MCP integrations — shipped to production, not demoed.

Sprints from $3K · shipped to production, or you don’t pay the final milestone.