Claude Code: Skills, Sub-agents, Hooks, and CLAUDE.md — When to Use What

woman typing on laptop

Have you started playing with Claude Code and found yourself staring at four different ways to customize it — wondering which one to actually reach for? Well, let’s dig right in.

Claude Code launched in February 2025 as a terminal agent that could edit files and run bash commands. Since then it has grown into a proper extension platform, and that growth has introduced a real question for developers picking it up: CLAUDE.md, skills, sub-agents, and hooks all exist, they all affect how Claude behaves, and their purposes genuinely overlap at the edges. This post is my attempt to map out when each one earns its place.

What Each One Actually Is

Before getting into the decision-making, it helps to have a clear model of what each tool does.

CLAUDE.md is a plain markdown file that Claude reads as persistent project memory. Put it in your project root (or ~/.claude/CLAUDE.md for global config) and Claude will load it at the start of every session. It is not a command and it does not trigger anything — it is context. Your architecture decisions, coding conventions, project-specific gotchas, and anything else Claude should always know about belong here.

Skills are SKILL.md files that live in ~/.claude/skills/ (personal) or .claude/skills/ (project). Each skill is a playbook — a set of instructions Claude follows when the skill is relevant. Unlike CLAUDE.md, skills load on demand. Claude reviews available skill descriptions at the start of a task and pulls in the full instructions only when a description matches what it’s working on. You can also invoke them directly as slash commands.

Sub-agents are separate Claude instances that your main session spawns to handle a chunk of work in its own isolated context window. A sub-agent has its own system prompt, its own tool permissions, and its own model if you want. It runs in parallel with your main conversation, then hands back a summary. The key constraint: sub-agents report back to the parent session — they cannot talk to each other.

Hooks are shell scripts tied to specific lifecycle events in Claude Code — pre-tool-use, post-tool-use, notification, and user-prompt-submit. When that event fires, your script runs. No LLM judgment involved. A hook that blocks commits containing .env files will block that commit one hundred percent of the time.

The Key Mental Model

Here is the framing I keep coming back to:

  • CLAUDE.md is what Claude always knows
  • Skills are what Claude knows how to do when it’s relevant
  • Sub-agents are who Claude delegates work to
  • Hooks are what always happens, no matter what

That last distinction — always vs. sometimes — is the most important one. Claude Code treats CLAUDE.md as context it may or may not use, not as law. One source puts Claude’s reliable instruction-following at roughly one hundred fifty instructions before degradation kicks in, and Claude Code’s own system prompt already consumes around fifty of those slots before it ever reads your file. If you put a critical rule in CLAUDE.md and expect it to hold absolutely, you are going to be disappointed eventually. If you put that same rule in a hook, it holds.

two heads with thread tying them together

Be mindful that this doesn’t mean CLAUDE.md is unreliable for general context — it’s well-suited for that. It means security rules, formatting enforcement, and anything that needs deterministic behavior belong in hooks or real tooling (linters, formatters), not markdown.

When to Use CLAUDE.md

CLAUDE.md earns its keep for static knowledge that changes slowly and that Claude should carry into every session without being asked.

Good candidates:

  • Project architecture overview (“this is a WordPress multisite, the network admin lives at /wp-admin/network/“)
  • Coding conventions your team follows (“use wp_remote_get(), never file_get_contents() for HTTP requests”)
  • Which directories are off-limits
  • How to run tests locally
  • Links or pointers to key source files (file paths, not inline code snippets — those go stale fast)

What not to put here: code examples, rules that only apply to specific file types, and anything you also plan to enforce with a linter. The more irrelevant instructions you stack into CLAUDE.md, the more Claude’s attention gets spread across things that don’t matter for the current task.

When to Reach for a Skill

Skills shine when you have a repeatable workflow that is too heavy to live in CLAUDE.md but does not need to run every session.

The best use case is specialized domain knowledge. Ideally, you want Claude to know the particulars of your component library, your deployment pipeline, or your schema conventions — but only when it’s actually working on those things. A skill loads that playbook on demand, keeps your context clean the rest of the time, and can be invoked explicitly with a slash command when you want it.

A skill also works well when you want to standardize how a task gets done across a team. Write the playbook once, commit it to .claude/skills/, and everyone working on the project gets the same behavior when Claude tackles that task.

I’d reach for a skill when:

  • You find yourself pasting the same long prompt more than a few times
  • A workflow involves more than three or four distinct steps
  • You want the behavior portable across projects (personal skills) or consistent across a team (project skills)

When to Spin Up a Sub-agent

Sub-agents are for parallelism and context isolation. Two problems they solve well:

Context clutter. After a long session of searching, editing, and debugging, your main conversation thread is noisy. Spinning up a sub-agent to handle a research task or explore a large codebase keeps that work in its own window and hands you back a clean summary.

Parallel workstreams. When you have genuinely independent tasks — say, auditing PHP compatibility in one part of the codebase while updating documentation in another — sub-agents let those run concurrently instead of sequentially. Claude Code currently supports up to ten concurrent sub-agents.

Where sub-agents get expensive: they consume more tokens than a single session, and the coordination overhead is real. I’d reach for a sub-agent when a task is both large enough to pollute the main context and independent enough that it doesn’t need constant back-and-forth with the main session. Don’t spin one up just because a task feels complex.

When a Hook Is the Right Call

If you catch yourself writing a CLAUDE.md rule that starts with “always” or “never,” consider whether a hook should own that instead.

Hooks are the right tool when:

  • You need something to happen at a specific lifecycle moment with no exceptions (blocking a commit, running a formatter, posting a notification to Slack when Claude finishes a task)
  • You want to inject dynamic context at session start — like running a script that outputs today’s date, current branch name, or environment state
  • You are running Claude Code in unattended or automated contexts and need hard guardrails

The tradeoff is that hooks require you to write and maintain shell scripts, which adds a different kind of complexity. For most solo projects, a handful of focused hooks beats a sprawling set of CLAUDE.md rules trying to do the same job probabilistically.

A Practical Decision Framework

SituationReach for
Static context Claude should always haveCLAUDE.md
Repeatable multi-step workflowSkill
Task that should auto-load when relevantSkill (with a tight description)
Large independent task, keep main context cleanSub-agent
Parallel workstreamsSub-agent
Something that must always happen, no exceptionsHook
Security rule, commit guard, formatterHook
Dynamic context injected at session startHook (user-prompt-submit)

These tools stack, too. A skill can spawn a sub-agent to do the heavy lifting. A hook can enforce conventions that a skill teaches. CLAUDE.md holds the project overview that all of the above can reference. The interesting setups layer all four.

Claude Code rewards you for thinking carefully about what kind of instruction you’re giving. Not everything belongs in CLAUDE.md, and not every workflow needs a sub-agent. Getting that mapping right is most of the work.

I’ve been playing with all four on a few different projects and would love to hear how you’re structuring yours — especially if you’ve found clever combinations. Let me know!