Steering Claude Code: choosing between CLAUDE.md, rules, skills, subagents, and hooks
Anthropic published a decision framework (June 2026) for Claude Code’s seven
customization layers: CLAUDE.md, rules, skills, subagents, hooks, output
styles, and --append-system-prompt. The core axis is context cost vs.
instruction authority — and the single most important distinction is that
everything except hooks is advisory. Instructions in context can be ignored
under pressure or prompt injection; hooks are the only mechanism enforced by
the harness itself. The community distilled it to: “Hooks are law, CLAUDE.md
and skills are guidance, subagents are scoped workers.”
The framework at a glance
Section titled “The framework at a glance”| Layer | Load timing | Context cost | Best for |
|---|---|---|---|
| CLAUDE.md (root) | Session start, re-read on compaction | High | Project fundamentals |
| CLAUDE.md (subdir) | On-demand | Low | Subdirectory conventions |
| Rules | Session start or path-scoped | Medium | Constraints and standards |
| Skills | Name/description at start; body on invocation | Low | Procedural workflows |
| Subagents | Isolated context; only final message returns | Low | Parallel side tasks |
| Hooks | Lifecycle events, bypasses compaction | Low | Deterministic automation |
| Output styles / append | Session start (system prompt) | High | Significant role changes |
The layers, each with an example
Section titled “The layers, each with an example”1. CLAUDE.md — always-on facts
Section titled “1. CLAUDE.md — always-on facts”Project fundamentals the model should always know: build commands, layout,
conventions. Keep it under 200 lines; it’s delivered as a user message, not
the system prompt, so compliance isn’t guaranteed. Root CLAUDE.md re-injects
after /compact; nested ones don’t auto-reload.
Example — facts, not procedures:
# Acme API
- Monorepo: `apps/api` (Fastify), `apps/web` (Next.js), `packages/shared`.- Run tests with `pnpm test --filter <app>`; never run the full suite locally.- All timestamps are stored as UTC ISO-8601 strings.2. Rules — path-scoped constraints
Section titled “2. Rules — path-scoped constraints”Markdown files in .claude/rules/; with a paths: frontmatter they load only
when Claude touches matching files, keeping instructions out of context during
unrelated work. Unscoped rules load always, at the same priority as CLAUDE.md.
Example — .claude/rules/api-handlers.md:
---paths: - "src/api/**" - "**/*.handler.ts"---All API handlers must validate input with Zod. Migrations are append-only —never edit an existing migration file.3. Skills — reusable procedures
Section titled “3. Skills — reusable procedures”Folders under .claude/skills/<name>/SKILL.md. Only name + description load at
session start; the body loads on invocation (via /name or auto-matching).
Create one when “you keep pasting the same checklist into chat, or a section of
CLAUDE.md has grown into a procedure rather than a fact.” As of June 2026,
skills and custom slash commands (.claude/commands/) are unified — both
create the same /command.
Example — .claude/skills/release/SKILL.md:
---name: releasedescription: Cut a release — changelog, version bump, tag, GitHub release---1. Run `pnpm test` and `pnpm build`; abort on failure.2. Update CHANGELOG.md from commits since the last tag.3. Bump the version (`$ARGUMENTS` = patch|minor|major), commit, tag `vX.Y.Z`.4. Push with tags and create a GitHub release with the changelog section.4. Subagents — isolated workers
Section titled “4. Subagents — isolated workers”Markdown files in .claude/agents/ with YAML frontmatter (name, description,
tools, model). A subagent runs in a fresh context window; only its final
message returns. Use when a side task would flood the main thread with output
you won’t reference again. Rule of thumb vs. skills: skill when you want to
watch and steer each step; subagent when you only want the conclusion.
Community estimates put overhead at ~20k tokens per spawn (as of 2026-06,
unverified), so reserve them for genuine isolation needs.
Example — .claude/agents/log-analyst.md:
---name: log-analystdescription: Digs through server logs to find the root cause of an errortools: Read, Grep, Bashmodel: haiku---You analyze log files under ./logs. Given an error description, find thefirst occurrence, correlate request IDs across services, and report only:root cause, affected time window, and the three most relevant log lines.5. Hooks — enforced automation
Section titled “5. Hooks — enforced automation”Commands that fire on lifecycle events (PreToolUse, PostToolUse,
SessionStart, Stop, …), configured in settings.json. Exit code 2
blocks the action and feeds stderr back to Claude — this is the only layer
the model cannot ignore. Anti-pattern: writing “never do X” or “always do Y
after Z” as prose in CLAUDE.md; that belongs here.
Example — block edits to production config (.claude/settings.json):
{ "hooks": { "PreToolUse": [ { "matcher": "Edit|Write", "hooks": [ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/guard-prod-config.sh" } ] } ] }}where the script exits 2 with a message on stderr if the target path matches
config/production/**.
6. Output styles — replacing the role
Section titled “6. Output styles — replacing the role”Files in .claude/output-styles/ injected into the system prompt. Caveat: an
output style replaces Claude Code’s default coding instructions unless
keep-coding-instructions: true is set. Built-ins (Explanatory, Learning)
cover most needs.
Example — .claude/output-styles/mentor.md:
---name: Mentordescription: Explains every change like a senior engineer teaching a juniorkeep-coding-instructions: true---After each code change, add a short "Why this way" note covering thetrade-off you made and one alternative you rejected.7. --append-system-prompt — per-invocation additions
Section titled “7. --append-system-prompt — per-invocation additions”A CLI flag that adds to the system prompt without replacing anything. Must be passed on every invocation, so it’s mainly for scripts and CI rather than interactive use.
Example — a CI review job:
claude -p "Review the diff in this PR for security issues" \ --append-system-prompt "You are a security reviewer. Report only \exploitable findings with severity; do not comment on style."Anti-patterns to avoid
Section titled “Anti-patterns to avoid”- “Always do X after Y” in CLAUDE.md → should be a
PostToolUsehook. - Hard guardrails (“never do this”) as prompts → hooks with exit-code blocking.
- Multi-step procedures living in CLAUDE.md → move to skills.
- Unscoped rules that load during unrelated work → add
paths:. - Defaulting to subagents when a single-threaded skill would do.
- Personal preferences in project files → put them in
~/.claude/orCLAUDE.local.md.
How this repo applies it (as of 2026-07)
Section titled “How this repo applies it (as of 2026-07)”/ai-newslives as a skill (.claude/skills/ai-news/SKILL.md); its research phase delegates to subagents (throwaway intermediate output).- Note-writing conventions are a path-scoped rule (
.claude/rules/notes.md) that loads only when editingsrc/content/docs/**. - A
PostToolUsehook (.claude/hooks/validate-note.sh) validates note frontmatter on every edit — enforcement, not advice.
Sources
Section titled “Sources”- Steering Claude Code: when to use CLAUDE.md, skills, hooks, and subagents — Anthropic, Michael Segner, published ~2026-06-18, accessed 2026-07-14
- Claude Code docs: Memory, Skills, Hooks, Subagents — accessed 2026-07-14
- Claude Code Setup: Hooks, Skills, and Guardrails — Bartek, ~2026-07-03, accessed 2026-07-14 (production hook scripts; “instructions ≈95% reliable” is the author’s estimate)
- Claude Code Primitives: Skills vs Subagents vs Hooks vs CLAUDE.md — ~2026-06-23, accessed 2026-07-14 (source of the “hooks are law” line and unverified token-overhead figures)