How do you learn new things as a developer?
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.
However
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.
Emergence of capability levels
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.
What I found?
A starting point and Six levels. L1 to L6.
L0 Absent → No instruction file (The starting point)
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
Here's what each one means in practice.
L0: Absent
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.
L1: Basic
your-project/
└── CLAUDE.md ← exists
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.
L2: Scoped
# 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
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.
L3: Structured
# CLAUDE.md
See @docs/architecture.md for system overview.
See @docs/api-conventions.md for API patterns.
## Constraints
...
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.
L4: Abstracted
your-project/
├── CLAUDE.md
└── .claude/
└── rules/
├── api-rules.md # paths: src/api/**
├── frontend-rules.md # paths: src/components/**
└── test-rules.md # paths: tests/**
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.
L5: Maintained
L4 with discipline.
Same structure, but with habits to keep it current:
- 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)
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.
L6: Adaptive
your-project/
├── CLAUDE.md
├── .claude/
│ ├── rules/
│ └── skills/
│ ├── database-migrations/
│ │ └── SKILL.md
│ └── api-testing/
│ └── SKILL.md
└── mcp.json
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.
Quick self-check
Where do you land?
| Question | If yes... |
|---|---|
| Do you have any instruction file? | At least L1 |
| Does it have explicit constraints (MUST/MUST NOT)? | At least L2 |
| Do you use @imports or multiple files? | At least L3 |
| Do different paths load different rules? | At least L4 |
| Do you actively maintain the structure? | At least L5 |
| Do you use skills or MCP? | L6 |
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.
Why bother with levels?
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.
What I'm building
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.
Top comments (0)