Lesson 25 of 32
Choosing the Right Extension
A decision procedure for CLAUDE.md, skills, hooks, MCP, subagents and plugins, so you stop guessing which one a given problem belongs in.
You now know six ways to change how Claude Code behaves. CLAUDE.md, skills,
hooks, MCP servers, subagents, plugins. Each lesson made its own case, and each
case was convincing on its own terms, which leaves you in a slightly worse
position than before: six answers, and no way to pick.
This lesson is the procedure. It is the most useful thing in this part of the course, because the mechanisms are easy and the choice is where people go wrong.
The four questions
Do not start from the features. Start from the properties of the thing you are trying to arrange, and the feature falls out. Ask these in order and stop at the first one that answers.
- Step 1
Must it, or should it?
If the answer must hold every time regardless of Claude's judgement, you need a hook. Nothing else in the list is binding.
- Step 2
Always, or sometimes?
Every session, unconditionally: CLAUDE.md. Occasionally, when a task calls for it: a skill, whose body only loads when used.
- Step 3
Here, or elsewhere?
If the work would flood this conversation with output you will not reread, delegate it to a subagent. Otherwise keep it here.
- Step 4
Inside, or outside?
If the capability or the data lives in another system, that is an MCP server. No amount of instruction substitutes for a connection.
Plugins are not a fifth question, because they are not an alternative to any of the above. Packaging is orthogonal: decide what the thing is, then decide whether anyone but you needs it.
Why the first question is first
Because it is the one people get wrong, and because getting it wrong is invisible for weeks.
CLAUDE.md and skills are context. Claude reads them and mostly complies. Hooks
are code that Claude Code runs at a fixed moment, and Claude has no vote. A rule
in CLAUDE.md that has been followed nineteen times looks identical to a
guarantee, right up to the twentieth.
So the test is not how important the rule feels. It is whether a sensible exception should be allowed to override it. "Prefer named exports" should yield to a good reason. "Never write to the migrations directory" should not. The first is advice; the second is enforcement.
Tool restriction on a subagent belongs in the same category as a hook, which is worth noticing. A reviewer whose tool list has no editing tool cannot edit. That is structural, not advisory.
Walking three real ones
"Our API responses all use a specific error envelope." Question one: should a
sensible exception be allowed? Yes — there will be an endpoint where it does not
fit. So not a hook. Question two: does it apply always? Every time Claude touches
an API handler, which is often but not always. That makes it a candidate for a
path-scoped rule, or a short line in CLAUDE.md pointing at a skill that holds
the full envelope specification with examples. The line is always loaded; the
specification is not.
"Nobody should be able to commit a private key." Question one answers
itself. A PreToolUse hook, matching the tool that would do it, blocking with an
explanation. The version of this that lives in CLAUDE.md is not a weaker
version of the same thing; it is a different thing that happens to read
similarly.
"I want to know why this endpoint is slow, and I do not want to read the profiler output." Questions one and two do not apply. Question three does: the work is verbose, the conclusion is short, and you will not reread the intermediate steps. A subagent, with a prompt that specifies the shape of the report.
Where the choice is genuinely close
Two pairs are worth separating properly, because the distinction is real and subtle.
A skill or a subagent. These sound similar and are not. A skill is content — instructions or knowledge — loaded into whatever conversation you are in. A subagent is a worker with a context window of its own. If what you want is reusable instructions, that is a skill even if it describes a big job. If what you want is for the work to happen somewhere else, that is a subagent even if the instructions are two lines. They also combine: a subagent can preload named skills, so the worker arrives already knowing your conventions.
MCP or a skill. MCP is a connection; a skill is knowledge about how to use
it well. An MCP server puts your database within reach. A skill that documents
your schema, your naming conventions and which three tables actually matter is
what stops Claude writing technically valid queries against the wrong table.
Reaching for a skill when the honest problem is that Claude cannot see the system
is the most common miss here. Reaching for MCP when a command-line tool Claude
already has would do — gh, aws, your own scripts — is the second most common,
and the CLI is usually cheaper in context because it adds no tool listing at all.
Deterministic trigger, judged content
One refinement that resolves a lot of apparent conflicts. The guarantee and the judgement are separable.
A hook fires deterministically, but what runs inside it need not be a pattern match. A hook can hand the event to a model for a yes-or-no decision, or to a subagent that reads the code before deciding. So "this must be checked every time, and checking it requires understanding" is not a contradiction. It is a hook whose check happens to involve a model.
Watching the procedure run
WhyThis is a useful thing to do out loud with Claude, because saying the requirement precisely is most of the work. Watch where the first answer is wrong.
You typed: We keep merging migrations without a down migration. Should that be in CLAUDE.md, a skill or a hook?
Claude replied: A skill, most likely — it is a procedure with several steps, and you already have /add-migration. I would extend that rather than add a mechanism.
WhyReasonable, and wrong for a reason the answer cannot know. Claude picked from the shape of the task. The deciding property is one only you can supply.
You typed: It cannot depend on anyone remembering to invoke the skill. A migration with no down migration must not be committable, ever.
Claude replied: Then it is a hook, not a skill. A skill only runs when invoked, and you have just ruled that out. I would keep the skill for writing migrations well, and add a PreToolUse hook on the commit path that fails when a new migration file has no down section.
WhyBoth, with different jobs. The skill carries the knowledge of how to do it properly. The hook carries the guarantee. Neither substitutes for the other, and this pairing is what most mature setups look like.
You typed: The check needs to read the SQL and decide whether the down section actually reverses the up section. That is not a grep.
Claude replied: Then the hook's check should be a model rather than a script. Same event, same guarantee that it fires, but the decision is a judgement instead of a pattern match.
WhyThis is the whole lesson in one exchange. Three requirements — always, unskippable, needs judgement — and each one narrowed the choice. Nobody had to know the feature list.
When two of them define the same thing
Occasionally you will have the same thing configured in more than one place, and the resolution differs by mechanism in a way worth knowing.
CLAUDE.md files accumulate: personal, project and nested files are all loaded
together, and Claude reconciles them, which is why contradictions between them
produce arbitrary behaviour rather than an error. Skills and subagents override
by name, so one definition wins and the others are invisible. Hooks merge, so
every registered hook fires for its event, from every source. MCP servers
override by name too.
The practical consequence: a conflicting instruction is a silent quality problem, a conflicting skill name is a silent disappearance, and a duplicated hook is a thing that happens twice.
The order this actually grows in
Nobody designs this up front, and you should not try. Each mechanism has a recognisable trigger, and the honest advice is to wait for it.
| When this happens | Add |
|---|---|
| Claude gets the same convention wrong twice | A line in CLAUDE.md |
| You type the same prompt to start a task again | A skill you invoke |
| You paste the same playbook in for the third time | A skill holding the playbook |
| You keep copying data from a system Claude cannot see | An MCP server |
| A side task floods your conversation with output | A subagent |
| You need something to happen every time, unasked | A hook |
| A second repository needs the same setup | A plugin |
The same triggers tell you when to revise what you already have. A recurring
review comment is a CLAUDE.md edit, not another correction in chat.
What to take away
Choose by property rather than by feature. If it must happen regardless of what
Claude decides, it is a hook, because that is the only mechanism in this part of
the course that is binding rather than advisory. If it applies to every session
it belongs in CLAUDE.md, and if it applies sometimes it belongs in a skill,
where the body costs nothing until it is used. If the work would fill your
conversation with output you will never reread, it belongs in a subagent, and
isolation is the only reason to choose one. If the data or the capability lives in
another system, no instruction substitutes for an MCP connection. Plugins are not
a competing choice but a packaging decision made afterwards. The pairs that feel
close are separable: a skill is content and a subagent is a place, MCP is a
connection and a skill is knowledge about using it. And when a requirement needs
both a guarantee and a judgement, a hook can fire deterministically and let a
model make the decision inside it.
Next: what to do when the thing you configured does not work — the diagnostic order that tells you whether it loaded, which copy of it won, and whether it ever fired.
Check yourself
5 questions · pass 4/5 to unlock Debugging Your Configuration
1.Your team's rule is that no commit may ever contain a file matching
*.pem. Where does that belong?2.You have forty pages of documentation for an internal payments service. Claude needs it perhaps once a fortnight. Where does it go?
3.You want a thorough security review of a large diff, and you do not want the diff and the reviewer's working notes filling your conversation. What does that point to?
4.Claude keeps needing information from your issue tracker, and you keep pasting it in. Which mechanism is that?
5.A rule must be checked every single time, but deciding whether it was broken needs judgement rather than a pattern match. What fits?
5 left to answer