§ Guides
By AI Blog Editor
Apr 20, 2026 · 1 min read
A field guide to Claude Code: CLAUDE.md, hooks, skills, plugins
Four primitives, often confused: the passive memory, the deterministic harness layer, the model-invoked capability, and the bundle. A pragmatic walkthrough, with diagrams and a decision picker.
Four things Claude Code gives you show up over and over in the docs — CLAUDE.md, hooks, skills, plugins — and they're easy to confuse. They sound adjacent. They sometimes live in the same directory. They each make Claude behave differently, for different reasons, at different moments in a turn.
This piece lays each one out, shows where it fits in the lifecycle, and gives you a quick way to decide which one to reach for. By the end, "should this be a hook or a skill?" should answer itself.
CLAUDE.md — the thing that's always there
CLAUDE.md is passive context. It's a Markdown file Claude Code auto-loads into the conversation. You write it; nobody runs it. Every prompt, every turn, it's sitting there.
It answers the question "what should Claude assume about this project before I even say anything?" Stack choices, house rules, the name of the canonical db pool, the fact that you use vitest not jest. Stable facts.
There are three scopes: project-level (in the repo), user-level (your home directory), and enterprise-level (org-wide). They stack — more specific overrides more general.
CLAUDE.md is the only one of the four that Claude cannot choose to ignore. The harness puts it in the context window, period.
Hooks — the deterministic harness layer
Hooks are shell commands the harness runs on lifecycle events. They are not code the model writes; they're entries you put in settings.json that fire when something specific happens. The model doesn't know they exist. The harness runs them, reads their output, and may or may not let the turn continue.
Events worth knowing
The event taxonomy is small but load-bearing. Each one fires at a precise moment in the turn, and picking the right one is the difference between an elegant rule and one that fights the harness.
SessionStart— fires once when Claude boots into a project. Good for injecting dynamic context that would be stale in CLAUDE.md: the current on-call rotation, the name of the active branch, a weather forecast if you're feeling whimsical.UserPromptSubmit— fires the moment you hit enter, before the model sees your prompt. Use it for redaction (strip secrets, rewrite PII) or for adding context the model should have for this prompt specifically.PreToolUse— fires before any tool call, after the model has decided what to do but before it does it. This is the veto seat: exit non-zero and the tool call is cancelled. Matcher-based, so you can scope it toBash,Edit(*.sql), or a specific MCP tool.PostToolUse— fires after a successful tool call. The place for "run the linter after every edit," "regenerate types after schema changes," "append a summary of what just happened."Stop/SubagentStop— fires when the turn (or a subagent) ends cleanly. Notifications, cost reporting, writing a session transcript to disk.Notification— fires when Claude is about to prompt you (permission request, idle). Pairs well withntfy, a desktop toast, or a terminal bell.
Exit codes: how a hook talks back
A hook's job is to do something and then tell the harness what happens next. It communicates through two channels: its exit code and its stdout. The contract is deliberately narrow.
- Exit
0— success, continue the turn. Anything on stdout is appended to the conversation as additional context the model will see on the next step. Use this to augment. - Exit
2— block. The tool call or prompt is cancelled, and stdout/stderr is fed back to the model as an error it must react to. Use this to refuse. Phrasing matters: the message you print becomes the model's next piece of evidence. - Any other non-zero — error. The harness surfaces the failure to you (not the model), the tool call is not blocked, and the turn continues. Treat this as "the hook itself broke" rather than a deliberate veto.
For structured control, hooks can also print a JSON object on stdout with fields like decision ("approve" / "block"), reason, and continue. This is the grown-up API for when exit codes feel too blunt.
What they're good for
The mental test for is this a hook? is: "I want X to happen without Claude deciding to do it."Formatting on save. Secret redaction before submit. A desktop notification when the turn ends. Running your test suite after every edit. Blocking any bash command that starts with rm -rf. Injecting the current date so the model doesn't hallucinate 2024.
The common thread: the action is dumb-on-purpose. No judgment required, no nuance, no reading a diff and deciding whether it's risky. Hooks are good at "always run this" and "never let that through." They're bad at anything that needs taste.
Security, since hooks run on your machine
Hooks execute with your user permissions — the same shell, the same environment, the same credentials as when you type commands directly. That's exactly the point (they can reach your linter, your database, your test runner), and it's also exactly the risk: a malicious entry in a shared .claude/settings.json is indistinguishable from a malicious entry in your .bashrc.
Review hooks the way you'd review a git hook or a CI step. If you pull someone else's plugin and it installs hooks, read them before running the next turn.
How hooks and skills compose
Hooks and skills are complements, not alternatives. A skill decides how to do a task; a hook enforces a rail the task has to stay inside. A "migration-review" skill can explain what a migration changes; a PreToolUse hook on Edit(*.sql) makes sure the migration file can't be written without the review actually running. One is judgment, the other is guarantee.
Skills — capabilities the model reaches for
Skills are on-demand, model-invoked packages. Each one lives in a folder with a SKILL.md: frontmatter declaring name and description, plus body instructions the model reads when it decides to use the skill.
The key word is decides. Unlike CLAUDE.md (always loaded) and hooks (harness-triggered), a skill is surfaced to the model as available, and the model picks it up when the description matches the task. Because the full content only loads on invocation, skills can be long and specific without bloating every turn.
Think of them as specialized playbooks. A frontend-design skill. A migration-review skill. A skill that knows your company's release notes template. The SKILL.md can reference helper scripts, prompt templates, and reference docs — all loaded lazily.
Plugins — the distribution layer
Plugins are bundles. A plugin is a packaged directory that can contain any mix of skills, subagents, slash commands, hooks, and MCP server definitions. It has a .claude-plugin/plugin.json manifest, it's installable from a marketplace, and it's the only one of these four concepts that isn't itself a runtime primitive.
You reach for a plugin when you want teammates to install the same toolkit with a single command, or when you want to publish something for the wider community. "Our engineering plugin" could bundle the migration-review skill, a hook that runs typecheck after edits, a release-notes subagent, and a postgres MCP server — all installed together.
- CLAUDE.mdalready in context before the turn begins
- Hook (UserPromptSubmit)optional: append context, redact secrets, block
- Claudereads context; decides to use a Skill? a Tool?
- Skillmodel invokes; SKILL.md content loads into the turn
- Hook (PreToolUse)runs before any tool; can block or modify
- Tool (Edit/Bash/…)the actual work
- Hook (PostToolUse)lint, format, validate, notify
- Hook (Stop)cleanup at end of turn
So which do I use?
Here's the decision, as a radio group. Pick the sentence that matches your need; the right tool and a concrete example appear on the right.
Interactive · § pick one
What do you actually need?
| Concept | Who triggers it | When it runs | Behaviour | Lives in |
|---|---|---|---|---|
| CLAUDE.md | You, in a file | Always (auto-loaded) | Never runs — it is passive context | Text in a repo file |
| Hook | The harness | On events (pre-tool, post-tool, submit, stop…) | Deterministic — your shell command | settings.json entry |
| Skill | The model (Claude) | When Claude judges it relevant | Probabilistic — description-based match | A SKILL.md file (+ optional scripts) |
| Plugin | "install" mechanism — contains the above | N/A — it is a bundle, not a runtime thing | Whatever is inside | marketplace install |
Common pitfalls
Stuffing CLAUDE.md with everything. CLAUDE.md is always in context. Every line costs tokens, every turn. Keep it to the stable facts. If it changes per task, make it a skill.
Using a skill when you needed a hook. If Claude might skip a skill invocation in a bad turn, but you absolutely must run the check, that's a hook. Skills are best-effort; hooks are guaranteed.
Using a hook when you needed a skill. Reverse failure. If the action requires judgment — "read this PR and decide if the migration is safe" — a hook is the wrong shape. Hooks are dumb-on-purpose.
Building a plugin before you need one. If you're the only one using the setup, a folder of skills + a settings.json with hooks is enough. Plugins earn their weight when more than one person installs them.
Tiny mental model
To wrap: CLAUDE.md is what Claude knows. Hooks are what the harness enforces. Skills are what Claude can reach for. Plugins are how you distribute all of the above. Get those four verbs right and the rest follows.
* * *
Thanks for reading. If a line here was useful — or plainly wrong — the comments are below and the newsletter has your back.
Elsewhere in this issue
3 more- 01
News
The first partner cut — days before Amazon's researchers flagged a Fable 5 vulnerability, the White House had already told Anthropic to revoke access for SK Telecom, its earliest Korean shareholder and a Project Glasswing partner, over concerns about the company's alleged ties to China. Five days later, Anthropic opened a Seoul office and signed every major Korean conglomerate that isn't SK.
Jun 19, 2026
- 02
The Patch
The Patch — June 19, 2026
Jun 19, 2026
- 03
News
The kill switch did the diplomacy — five days after Washington took Anthropic Fable 5 and Mythos 5 offline, Dario Amodei and Demis Hassabis sat down at the G7 in Évian-les-Bains and asked the allies to sign up for an explicitly US-led AI coalition. Canada said yes; France brought a list.
Jun 18, 2026
Letters
Arguments, corrections, questions. Anonymous comments allowed; be kind, be specific.