{"slug": "what-actually-belongs-in-claude-md-and-what-to-move-to-skills-hooks-or-docs", "title": "What actually belongs in CLAUDE.md — and what to move to skills, hooks, or docs", "summary": "A developer argues that CLAUDE.md files grow too large and lose effectiveness, proposing a sorting strategy that moves situational rules to skills, deterministic checks to hooks, and reference material to docs files. The key insight: every line in CLAUDE.md taxes every request, so only invariants that are cheap to state and expensive to violate should stay there.", "body_md": "Your CLAUDE.md only grows. Every incident adds a rule, every preference becomes a paragraph, and six months in you have a file that reads like a wiki — and an agent that follows maybe half of it.\n\nThe uncomfortable mechanics: CLAUDE.md is loaded into context automatically, which means **every line is a tax on every single request**, whether it's relevant or not. And instructions are advisory — the more of them there are, the weaker each one pulls. I've watched my own rules drift off quietly in long sessions and only caught it in the diff.\n\nSo the real question isn't \"what should I write in CLAUDE.md?\" It's \"what has earned a permanent seat in context — and where does everything else live?\"\n\nClaude Code gives you four places to put guidance, and they have very different cost models:\n\n| Destination | Loaded | Costs tokens | Enforcement |\n|---|---|---|---|\n| CLAUDE.md | every session, automatically | always | advisory |\n| Skill | body only when the task matches | on demand | advisory, but scoped |\n| Hook | never enters context as prose | ~zero | deterministic |\n| docs/ file | when the agent (or a rule) points at it | on demand | none — it's reference |\n\nHere's the sorting test I use, one sentence per destination.\n\n**Keep it in CLAUDE.md if it's true on every turn, cheap to state, and expensive to violate.** Build commands, naming conventions, \"tests live in `test/`\n\n, mirrored by path\", the tone your commit messages use. If you'd want the rule active even in the middle of an unrelated refactor, it's an *invariant* — that's what the always-loaded file is for.\n\n**Move it to a skill if it starts with \"when doing X\".** Deploy checklists, a review rubric, the release-notes format, your migration playbook. A skill's name and description stay visible so the agent knows it exists, but the body only loads when the task actually matches. That's exactly the deal you want for situational expertise: discoverable, but not billed on every request. (Format details: [how to write a SKILL.md that actually triggers](https://dev.to/rulestack/skillmd-how-to-write-a-claude-code-skill-that-actually-triggers-format-template-27cp).)\n\n**Move it to a hook if the sentence contains \"never\" or \"always\" and a machine could check it.** Formatting before commit, protected paths, \"don't touch `.env`\n\n\", \"block pushes to main\". Don't ask a language model to *remember* what a shell script can *enforce* — a hook fires deterministically whether the context is fresh or fifty files deep. ([Hook config structure and matchers](https://dev.to/rulestack/claude-code-hooks-explained-config-structure-matchers-and-a-copy-paste-pretooluse-guard-58jj).)\n\n**Move it to a docs file if it's something the agent should read, not obey.** Architecture overviews, API quirks, the history of why the billing module is weird. Put it in\n\n`docs/`\n\n, and leave one line in CLAUDE.md saying when to read it: \"Touching billing? Read `docs/billing-history.md`\n\nfirst.\" Reference material rents context only when it's relevant.Three costs stack up on the always-loaded path:\n\nHooks dodge all three. Skills dodge the first two. Docs dodge all three but enforce nothing. CLAUDE.md is the only slot that pays full price — spend it on the few rules that deserve it.\n\n```\n# myproject — agent guide\n\n## Commands\n- Build: `pnpm build` / Test: `pnpm test` (single file: `pnpm test path/to.test.ts`)\n- Never run `pnpm deploy` directly — use the deploy skill.\n\n## Conventions (always)\n- TypeScript strict; no `any`. Errors are returned, not thrown, in `src/core`.\n- Tests mirror source paths. New modules need a test file in the same PR.\n- Commit messages: imperative mood, reference the issue.\n\n## Enforced by hooks (listed so you know they exist)\n- Format-on-edit, protected paths (`.env`, `migrations/`), test gate before commit.\n\n## Where things live\n- Architecture: `docs/architecture.md` (read before cross-module changes)\n- Billing quirks: `docs/billing-history.md` (read before touching `src/billing`)\n\n## When unsure\n- Prefer asking over guessing on anything in `migrations/`.\n```\n\nThat's the whole shape: commands, invariants, a pointer to what's machine-enforced, a map, and an escalation rule. One screen. The \"enforced by hooks\" section is deliberately redundant — the hook does the enforcing, the mention just stops the agent from being surprised.\n\n`.claude/skills/<name>/SKILL.md`\n\nwith a description that names the trigger. Never-events → hooks or CI checks. Reference → `docs/`\n\n, with a one-line pointer left behind.`src/billing`\n\nwith the word BILLING\" — so you can tell at a glance whether the file is being honored at all. (One honest caveat: none of this makes prose rules reliable. Advisory is advisory. What the sort gives you is a small enough always-loaded core that the model can actually hold it, plus deterministic enforcement for the things that genuinely can't be violated. If a rule keeps breaking after all this, that's your signal it wanted to be a hook all along.\n\nIf you're not sure how your rules files get read in the first place — CLAUDE.md, AGENTS.md, and Cursor's rules all load differently — start with [how each tool actually loads your project rules](https://dev.to/rulestack/how-cursor-claude-code-and-codex-actually-load-your-project-rules-and-why-yours-get-ignored-1l1j).\n\n*I'm Rulestack — I build and maintain drop-in rule, skill, and hook packs for Claude Code, Cursor, and Codex, at rulestack.gumroad.com. I post working AI-coding tips on Bluesky at @ai-shop.bsky.social — follow along if this was useful.*", "url": "https://wpnews.pro/news/what-actually-belongs-in-claude-md-and-what-to-move-to-skills-hooks-or-docs", "canonical_source": "https://dev.to/rulestack/what-actually-belongs-in-claudemd-and-what-to-move-to-skills-hooks-or-docs-34id", "published_at": "2026-07-30 00:51:10+00:00", "updated_at": "2026-07-30 01:32:29.368606+00:00", "lang": "en", "topics": ["developer-tools", "artificial-intelligence", "large-language-models", "ai-agents"], "entities": ["Claude Code"], "alternates": {"html": "https://wpnews.pro/news/what-actually-belongs-in-claude-md-and-what-to-move-to-skills-hooks-or-docs", "markdown": "https://wpnews.pro/news/what-actually-belongs-in-claude-md-and-what-to-move-to-skills-hooks-or-docs.md", "text": "https://wpnews.pro/news/what-actually-belongs-in-claude-md-and-what-to-move-to-skills-hooks-or-docs.txt", "jsonld": "https://wpnews.pro/news/what-actually-belongs-in-claude-md-and-what-to-move-to-skills-hooks-or-docs.jsonld"}}