Source: ai-research/claude-blog-steering-claude-code.md — Anthropic first-party blog post, claude.com/blog/steering-claude-code-skills-hooks-rules-subagents-and-more (published 2026-06-18), written by Michael Segner, member of Anthropic staff (co-author of the loop-engineering post). Surfaced via a direct link inside that post’s turn-based-loop section (“For choosing between skills, hooks, and subagents… see our guide to steering Claude Code”).
Claude Code exposes seven distinct ways to instruct Claude’s behavior: CLAUDE.md files, rules, skills, subagents, hooks, output styles, and appending the system prompt. This first-party guide is the decision framework for choosing between them — each method trades context cost against authority, and picking the wrong one either wastes tokens (loading something that didn’t need to be always-on) or produces unreliable behavior (asking an instruction to do a hook’s job). It complements the wiki’s existing Skills vs MCP vs Plugins (extensibility-layer choice at setup time) and CLI vs MCP (runtime tool-selection choice) — this one is about where an instruction belongs, not which tool or extensibility layer to reach for.
Key Takeaways
- Three axes decide where an instruction belongs: when it loads into context, whether it survives compaction, and how much authority it carries. The full comparison is the table below — read it before writing your next CLAUDE.md line.
- CLAUDE.md and skills solve different problems. CLAUDE.md is for facts Claude should hold all the time (build commands, monorepo layout, team conventions); skills are for procedures (a 30-line deploy runbook belongs in
.claude/skills/, not CLAUDE.md, so it only loads when actually invoked). - Rules (
.claude/rules/) are a distinct, path-scopable primitive the wiki hadn’t documented before this post: apaths:frontmatter field lets a constraint (e.g. “all API handlers must validate input with Zod”) load only when matching files are touched, instead of sitting always-on like an unscoped rule or CLAUDE.md. - Subagents nest up to five levels deep, and the larger instructional body in a subagent’s definition never enters the parent conversation at all — only the final message (often an aggregated result) plus metadata returns. This is why dynamic workflows can orchestrate tens to hundreds of background agents without blowing up the main context window.
- “Never do this” doesn’t belong in CLAUDE.md. Prompted instructions are followed most of the time, but can fail under pressure, in long/ambiguous sessions, or via a prompt injection in an accessed file. A real guardrail needs to be deterministic — a
PreToolUsehook exiting code 2, or (for organization-wide enforcement that can’t be overridden locally) managed settings. - Skills and hooks are the building blocks of agent loops — the source post makes this connection explicit, tying the instruction-delivery framework directly to the loop-engineering taxonomy.
The Decision Table
| Method | When it’s loaded | Compaction behavior | Context cost | When to use |
|---|---|---|---|---|
| CLAUDE.md (root) | Session start; stays for the entire session | Memoized — read once, cached; re-read after compaction | High — every line costs tokens whether relevant or not | Build commands, directory layout, monorepo structure, coding conventions, team norms |
| CLAUDE.md (subdirectory) | On-demand, when Claude reads a file under that subdirectory | Lost until that subdirectory is touched again | Low | Conventions specific to a subdirectory |
| Rules | Session start (user-level) or only when matching files touched (path-scoped) | Re-injected on compaction | Medium — always-on unless path-scoped | Specific constraints/conventions (e.g. all API handlers validate input with Zod) |
| Skills | Name+description at session start; full body loads when invoked | Invoked skills re-injected up to a shared budget; oldest dropped first | Low | Procedural workflows (deploy/release checklists) |
| Subagents | Name/description/tool-list at session start; body loads only via the Agent tool | Only the final message (summary + metadata) returns | Low — zero cost until called; own isolated context window | Parallel work or side tasks that should run isolated and return only a summary (deep search, log analysis, dependency audit) |
| Hooks | Fire on lifecycle events | Bypass compaction entirely | Low — config lives outside main context | Deterministic automation: linters, Slack posts, blocking commands, chat-history backup on PreCompact |
| Output styles | Session start; injected into system prompt | Never compacted | High — occupies context window, overwrites default system prompt | Significant role changes (code assistant to general assistant) |
| Appending the system prompt | Session start; CLI flag | Never compacted; applies only to that invocation | Moderate — cached after first request | Tone, response length, formatting preferences |
The Seven Methods
CLAUDE.md files — always-on project memory. Root files load at session start and survive compaction (re-read, not lost); subdirectory files (app/api/CLAUDE.md) load on-demand and share path-scoped rules’ compaction behavior (gone until that subdirectory is touched again). The failure mode: in a shared repo, CLAUDE.md grows like any unowned config file — every team appends, nothing gets deleted, and the cost compounds because every line loads for every engineer regardless of relevance. Keep it under 200 lines, give it an owner, review changes like code, and use claudeMdExcludes in monorepos so teams don’t load conventions they’ll never touch. Org-wide standards (security, compliance) can be deployed via MDM as a centrally managed CLAUDE.md that individual settings can’t exclude.
Rules — markdown files in .claude/rules/. Unscoped rules behave like CLAUDE.md (always loaded, re-injected on compaction). Path-scoped rules add a paths: frontmatter field so a constraint only loads when matching files are touched:
---
paths:
- "src/api/**"
- "**/*.handler.ts"
---
All API handlers must validate input with Zod before processing.Reach for a path-scoped rule over a nested CLAUDE.md when the instruction is a cross-cutting concern that shows up in multiple, but not all, corners of the codebase.
Skills — folders in .claude/skills/. Only name and description load at session start; the full body loads when invoked (slash command or auto-match). Re-injected on compaction up to a shared budget across invoked skills, with the oldest dropped first. Procedures belong here, not in CLAUDE.md.
Subagents — markdown files in .claude/agents/. Name, description, and tool list load at session start; the body becomes the subagent’s system prompt and never enters the parent conversation. Runs in its own fresh context window; only the final message plus metadata returns. Nests up to five levels deep. Reach for a subagent instead of a skill specifically for the isolation — a side task (deep search, log analysis, dependency audit) that would otherwise clutter the main conversation with intermediate results you won’t reference again. Use a skill when you want to see and steer each step in the main thread.
Hooks — user-defined commands, HTTP endpoints, or LLM prompts firing on lifecycle events, registered in settings.json, managed policy settings, or skill/agent frontmatter. Five types: command, HTTP, and mcp_tool execute deterministically; prompt and agent use Claude’s judgment. Bypass compaction entirely because configuration lives outside the main context window — most hook output never returns to context unless explicitly configured to (a blocking hook’s stderr is the exception, so Claude knows why a call was denied). Use for anything that must happen deterministically: linters after edits, Slack posts on completion, blocking specific commands via a PreToolUse hook exiting code 2.
Output styles — files in .claude/output-styles/ injected into the system prompt, never compacted, highest instruction-following weight of any method here. The catch: changing the output style replaces the default one (unless keep-coding-instructions: true), silently dropping the defaults that make Claude Code a software-engineering assistant (change-scoping discipline, comment conventions, security handling, verification habits). Check the built-in Proactive / Explanatory / Learning styles before writing a custom one.
Appending the system prompt — the append-system-prompt CLI flag, additive-only (doesn’t replace Claude’s role) and scoped to a single invocation, not persisted. Higher context cost than most methods (increases input tokens, mitigated by caching after the first request) and has diminishing adherence returns — the more instructions piled on this way, the less strictly any of them get followed, especially if they contradict.
Five Anti-Patterns (and the Fix)
| If you’re doing this… | …the fix is |
|---|---|
| ”Every time X, always do Y” in CLAUDE.md | A hook in settings.json. The model choosing to run a formatter is different from the formatter running automatically. |
| ”Never do this” in CLAUDE.md | A PreToolUse hook (exit code 2 to block) or, for org-wide enforcement, managed settings — an instruction is the wrong tool for an absolute must, since it can fail under pressure, in long/ambiguous sessions, or via a prompt injection in an accessed file. |
| A 30-line procedure in CLAUDE.md | A skill in .claude/skills/ — CLAUDE.md is for always-true facts, not procedures that should load only when invoked. |
An API-specific rule without paths: | Add the paths: scope — an unscoped rule is mechanically identical to CLAUDE.md: always loaded, always costing tokens. |
| Personal preferences in a project-level CLAUDE.md | The user-level counterpart (loaded for every session regardless of repo) — keep project-level files for team-wide-but-codebase-specific preferences. |
Try It
- Audit your CLAUDE.md against the anti-pattern table. Any “always do Y” line is a hook candidate; any “never do X” line is a hook-or-managed-settings candidate; any multi-step procedure is a skill candidate.
- Introduce path-scoped rules before your CLAUDE.md hits 200 lines. If a constraint only applies to one directory tree,
paths:scoping keeps it out of context everywhere else. - Reach for a subagent specifically for isolation, not just parallelism. If a side task’s intermediate results (search hits, log lines, dependency trees) would clutter the main thread and you’ll never need to reference them again, that’s the subagent signal — not “this could also run in the main thread.”
- Before writing a custom output style, check whether
append-system-promptgets you there instead — it’s additive-only and won’t silently strip Claude Code’s default engineering-assistant behaviors the way a from-scratch output style can.
Open Questions
- Resolved 2026-07-16: of the companion posts originally flagged here as unfetched, two have now been ingested. “CLAUDE.md files: Customizing Claude Code for your codebase” (
claude.com/blog/using-claude-md-files, published Nov 25, 2025) was folded into The CLAUDE.md File — Anthropic Primer as a substantial extension (worked example, MCP-documentation pattern, custom slash commands,/cleardiscipline, secrets warning). “How Anthropic runs large-scale code migrations with Claude Code” (claude.com/blog/ai-code-migration, published 2026-07-16) became its own article, How Anthropic Runs Large-Scale Code Migrations with Claude Code — distinct methodology content, not a case-study duplicate of Dynamic Workflows. Resolved 2026-07-16: “How to configure hooks” (claude.com/blog/how-to-configure-hooks) was fetched and overlap-checked against Claude Code Hooks as planned — confirmed substantial overlap (that article documents 25 lifecycle events to this post’s 8), but the post contributed 7 facts not previously in the wiki, folded directly intohooks.mdrather than a new article: the 60-second default hook timeout (resolving a standing Open Question there), parallel execution across same-event hooks, automatic dedup of identical hook commands, matcher case-sensitivity, the/hooksmenu’s review-before-activation safeguard, and a debugging pattern (transcript tailing + a logging wrapper script). - The post doesn’t quantify the “shared budget” skills are re-injected against on compaction, or the exact conditions that trigger a subagent’s isolation to leak (e.g. does a
PreToolUsehook still fire inside a subagent’s isolated context?) — undocumented here.
Related
- Loop Engineering: Getting Started with Loops — the companion first-party post (same co-author, Michael Segner) that names skills and hooks as loop-building-block primitives; this article is the “which one, and where” guide those primitives assume.
- Skills vs MCP vs Plugins — the adjacent decision framework for extensibility-layer choice at setup time (this article is instruction-placement choice, a different axis).
- CLI vs MCP — How AI Agents Choose the Right Tool — the third leg: runtime tool-selection choice.
- The CLAUDE.md File — Anthropic Primer — the earlier, CLAUDE.md-only first-party explainer; this article adds the six-way comparison against rules/skills/subagents/hooks/output-styles/system-prompt plus the 200-line/ownership/MDM guidance.
- Claude Code Hooks — the deep-dive on hook lifecycle events, handler types, and exit-code semantics this article’s hooks section summarizes.
- Claude Code Subagents — the deep-dive on subagent mechanics; this post adds the five-level nesting-depth fact.
- The Complete Guide to Building Skills for Claude — the deep-dive this post links to directly for authoring a custom skill.
- Model vs. Effort — the “two separate dials” (capability, not instruction-delivery) this post explicitly distinguishes itself from.
- 12-Factor Agents — the framework-agnostic sibling thesis: “own your control flow,” here applied to instruction placement specifically.