Tools
Tools: CLAUDE.md best practices - From Basic to Adaptive
2026-02-03
0 views
admin
How do you learn new things as a developer? ## Emergence of capability levels ## What I found? ## L0: Absent ## L1: Basic ## L2: Scoped ## L3: Structured ## L4: Abstracted ## L5: Maintained ## L6: Adaptive ## Quick self-check ## Why bother with levels? ## What I'm building My take on it is to find yourself an actual project (not tutorials) and start iterating. I wanted to learn LangGraph for my SageCompass project. SageCompass is a monorepo with LangGraph + Drupal (for RAG content management) and Gradio (for UI). I iterated ... a LOT. A lot lot. A lot lot lot. After 2 months of learning the principles of managing a python project and on top of that a LangGraph project, I felt ready to start using a coding agent (Codex at that time), to reduce refactoring times. As it turned out, coding agents are working significantly more reliably, if you have strong boundaries. I had my unit test structure hammered out, directives and contract were clear and strongly defined. SageCompass is a monorepo. I needed some highly elevated AGENTS.md setup to manage all of them together. The LangGraph part? Tight. Contracts, test structure, clear boundaries - the agent barely needed hand-holding. The Drupal part? I've been working with Drupal for 17 years. I know what I need, but I hadn't written it down for an agent yet. The Gradio part? I was still learning it myself - how do you write instructions for something you don't fully understand yet? I couldn't just have one big instruction file. Each component was at a different stage of readiness. Copy-pasting rules across them would have been worse than having no rules at all. That's when it hit me: instruction setups have capability levels. And if they have levels, they can be measured. And if they can be measured, they can be improved systematically. When I tried to port my LangGraph rules to the Gradio component, I needed to figure out which ones were universal and which ones were specific to a well-established, contract-heavy setup. A rule like 'never commit .env files' applies everywhere. A rule like 'implement nodes as make_node* factories' is meaningless outside LangGraph.
That forced me to categorize. Not just what rules do, but what level of project capability they assume. A basic project needs different instructions than one with enforced contracts and navigation maps. A starting point and Six levels. L0 to L6. Here's what each one means in practice. No CLAUDE.md. No AGENTS.md. Nothing. Claude works from its training data and whatever it can infer from your code. It'll guess your stack from package.json, maybe pick up patterns from existing files. But it has zero guidance about your preferences, constraints, or "never do this" rules. For quick scripts or throwaway experiments, this is fine. For anything you'll maintain, you're probably leaving value on the table. A file exists. It's tracked in git. Content might be /init boilerplate — the auto-generated stuff Claude Code produces. Might be a few lines you wrote yourself. The point is you've acknowledged that Claude needs context, and you've given it somewhere to live. This is the "I know this matters" stage. Most people get here quickly. What changes: Claude has something project-specific. It knows this isn't just a random repo. What's still missing: Rules. Claude knows about your project, but not your constraints. Explicit constraints. MUSTs and MUST NOTs. This is where you stop describing and start prescribing. Not just "here's what the project is" but "here's what you can and cannot do." The language matters. "Prefer TypeScript" is a suggestion Claude might ignore. "MUST use TypeScript strict mode" is a rule it tends to follow. For small projects with simple conventions, this is often enough. You have your rules in one place. Claude follows them. Life is reasonable. What changes: Claude follows your rules, not just generic best practices. What's still missing: Scale. When the file gets long, important stuff gets lost in the noise. External references. Multiple files. Content split by concern. You've hit the point where one file isn't working anymore. So you break it up. Architecture in one place. API conventions in another. Your CLAUDE.md becomes a router pointing to the right context. This is also where team collaboration gets easier. Different people can own different files. What changes: Separation of concerns. Easier to maintain. Each file has a job. What's still missing: All files load regardless of what you're working on. Editing tests? Claude still loads your API conventions. Noisy. Path-scoped loading. Different rules for different parts of the codebase. Edit src/api/users.ts? Only API rules load. Edit tests/user.test.ts? Only test rules load. This is where context efficiency gets real. You're not wasting tokens on irrelevant rules. Claude's attention stays on what matters for the task at hand. How you implement this depends on the tool. Claude Code uses .claude/rules/ with frontmatter. Cursor uses .cursor/rules/. The concept is the same. What changes: Claude adapts to what you're working on, not just what project you're in. What's still missing: Maintenance. Structures rot. Rules go stale. Same structure, but with habits to keep it current: The difference between L4 and L5 isn't features — it's upkeep. L4 is "I set this up." L5 is "I keep it working." What changes: Reliability over time. The setup doesn't quietly rot. What's still missing: Dynamic capabilities. Claude follows instructions but can't extend itself. Skills that load based on task. MCP servers for external integrations. At this level, Claude doesn't just follow instructions — it loads capabilities. Working on migrations? The migration skill activates with its own context. Need to hit an external API? MCP handles it. Very few setups are here yet. The tooling is new. The patterns are still emerging. What changes: Claude extends its abilities based on what it detects you're doing. From what I've seen, most setups are L1 (Basic) or L2 (Scoped). Some reach L3 (Structured). L4 (abstracted) and above is rare - not because it's hard, but because the patterns aren't widely known yet. It's not about chasing a high score. It's about having words for things. "I'm at L2 (Scoped) and wondering if L4 (abstracted) is worth the effort" is a conversation you can actually have. "My CLAUDE.md is pretty good" isn't. The right level depends on your project. A weekend hack doesn't need path scoping. A complex system with multiple domains probably does. The framework just helps you think about where you are and where you might want to go. I'm working on a validator that uses this framework: detects your level, checks structure, score your setup. (If you run it from Claude Code CLI, it helps you fix issues too.) It's early. Like, really early. I'm still working through core level implementations. But if you want to poke at it and tell me what's broken, I'd appreciate it: Reporails CLI: github.com/reporails/cli Or just use the levels as a mental model. That's the real value anyway. Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse CODE_BLOCK:
L0 Absent → No instruction file
L1 Basic → File exists, tracked
L2 Scoped → Project-specific constraints L3 Structured → External references, modular
L4 Abstracted → Path-scoped loading
L5 Maintained → Structural discipline
L6 Adaptive → Dynamic context, skills, MCP Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
L0 Absent → No instruction file
L1 Basic → File exists, tracked
L2 Scoped → Project-specific constraints L3 Structured → External references, modular
L4 Abstracted → Path-scoped loading
L5 Maintained → Structural discipline
L6 Adaptive → Dynamic context, skills, MCP CODE_BLOCK:
L0 Absent → No instruction file
L1 Basic → File exists, tracked
L2 Scoped → Project-specific constraints L3 Structured → External references, modular
L4 Abstracted → Path-scoped loading
L5 Maintained → Structural discipline
L6 Adaptive → Dynamic context, skills, MCP CODE_BLOCK:
your-project/
└── CLAUDE.md ← exists Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
your-project/
└── CLAUDE.md ← exists CODE_BLOCK:
your-project/
└── CLAUDE.md ← exists COMMAND_BLOCK:
# CLAUDE.md ## Project
E-commerce API, Node.js, PostgreSQL. ## Constraints
- MUST use TypeScript strict mode
- MUST NOT use `any` type - MUST run tests before committing
- NEVER modify migration files directly Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
# CLAUDE.md ## Project
E-commerce API, Node.js, PostgreSQL. ## Constraints
- MUST use TypeScript strict mode
- MUST NOT use `any` type - MUST run tests before committing
- NEVER modify migration files directly COMMAND_BLOCK:
# CLAUDE.md ## Project
E-commerce API, Node.js, PostgreSQL. ## Constraints
- MUST use TypeScript strict mode
- MUST NOT use `any` type - MUST run tests before committing
- NEVER modify migration files directly COMMAND_BLOCK:
# CLAUDE.md See @docs/architecture.md for system overview.
See @docs/api-conventions.md for API patterns. ## Constraints
... Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
# CLAUDE.md See @docs/architecture.md for system overview.
See @docs/api-conventions.md for API patterns. ## Constraints
... COMMAND_BLOCK:
# CLAUDE.md See @docs/architecture.md for system overview.
See @docs/api-conventions.md for API patterns. ## Constraints
... COMMAND_BLOCK:
your-project/
├── CLAUDE.md
└── .claude/ └── rules/ ├── api-rules.md # paths: src/api/** ├── frontend-rules.md # paths: src/components/** └── test-rules.md # paths: tests/** Enter fullscreen mode Exit fullscreen mode COMMAND_BLOCK:
your-project/
├── CLAUDE.md
└── .claude/ └── rules/ ├── api-rules.md # paths: src/api/** ├── frontend-rules.md # paths: src/components/** └── test-rules.md # paths: tests/** COMMAND_BLOCK:
your-project/
├── CLAUDE.md
└── .claude/ └── rules/ ├── api-rules.md # paths: src/api/** ├── frontend-rules.md # paths: src/components/** └── test-rules.md # paths: tests/** CODE_BLOCK:
your-project/
├── CLAUDE.md
├── .claude/
│ ├── rules/
│ └── skills/
│ ├── database-migrations/
│ │ └── SKILL.md
│ └── api-testing/
│ └── SKILL.md
└── mcp.json Enter fullscreen mode Exit fullscreen mode CODE_BLOCK:
your-project/
├── CLAUDE.md
├── .claude/
│ ├── rules/
│ └── skills/
│ ├── database-migrations/
│ │ └── SKILL.md
│ └── api-testing/
│ └── SKILL.md
└── mcp.json CODE_BLOCK:
your-project/
├── CLAUDE.md
├── .claude/
│ ├── rules/
│ └── skills/
│ ├── database-migrations/
│ │ └── SKILL.md
│ └── api-testing/
│ └── SKILL.md
└── mcp.json - A backbone file mapping the codebase, updated when things change
- Some way to track what's stale
- Regular reviews (however often makes sense for you) - Capability levels docs
how-totutorialguidedev.toaiserverrouterpostgresqlnodepythondatabasegitgithub