Video coming soon
Understand the CLAUDE.md memory hierarchy, generate your first project memory with /init and encode the conventions that matter most.
In Section 2, we saw what happens when Claude has zero context about your project. It builds features that work but don't belong. In this lesson, we fix that by giving Claude persistent memory through CLAUDE.md.
Every time you start a new Claude Code session, Claude begins with a blank slate. It doesn't know your project. So what does it do? It reads your files. It scans your codebase to understand the structure, the patterns, the tech stack. Every single session, it's doing this discovery work from scratch.
That costs tokens. It costs time. And it still doesn't capture the decisions behind your code, why you chose named exports, why you use skeleton loaders, why certain values are what they are.
When you give Claude a CLAUDE.md, you're front-loading that understanding. Instead of spending the first chunk of every session reading through your source files to figure out what matters, Claude gets a concise summary of your project's conventions, architecture and standards loaded instantly at startup.
Claude will still read files and explore your codebase when it needs to. That doesn't go away. But the difference is what it's reading for. Without CLAUDE.md, it's scanning to understand the basics: what framework is this, how are things structured, what patterns are in use. With CLAUDE.md, it already knows all of that. When it reads files now, it's focused on the specific task, not on figuring out your project from scratch.
The result: faster sessions, fewer tokens burned on discovery and more consistent output because Claude isn't guessing at your conventions from code alone.
Claude Code reads configuration files from multiple locations, loaded in a specific order. Think of it as layers, where more specific scopes override broader ones:
1. Project-level memory: ./CLAUDE.md (your project root)
Rules specific to this codebase. Tech stack, architecture decisions, naming conventions, component patterns. This is what gets committed to git and shared with your team. This is where we'll focus in this section.
2. Directory-level memory: ./some-folder/CLAUDE.md
Rules that only apply when Claude is working in a specific part of your project. These aren't loaded at startup. Claude only loads a directory-level CLAUDE.md when it reads files in that folder. This is a good strategy for managing context: instead of putting everything into the root file and loading it all upfront, you can place specialised rules where they're relevant and let Claude pick them up dynamically. Useful for monorepos or projects where different areas have different conventions.
3. User-level memory: ~/.claude/CLAUDE.md
Rules that apply to everything you do, across all your projects. We'll set this up in Section 4 when we teach Claude about you, your preferences, your standards, your workflow. We'll also explore claude.json in a later section, which is a separate file that Claude Code uses to manage its own state.
4. Rules: .claude/rules/*.md
Modular markdown files that let you split instructions by topic (e.g., testing.md, code-style.md, security.md). By default, rules load at session start like CLAUDE.md. But rules can also include a paths frontmatter with glob patterns, which makes them load dynamically only when Claude works with matching files. This keeps your context lean by loading rules only when they're relevant. We'll set these up in the next lesson.
When you start a session, Claude loads the project-level and user-level files immediately, along with any rules that don't have path restrictions. Directory-level files and path-scoped rules load on demand.
Key insight: Project-level
CLAUDE.mdis the most important one. It's where the majority of your conventions live, and it's what makes Claude behave like a teammate instead of a stranger.
Before we generate anything, let's look at what a well-structured CLAUDE.md looks like. Here's a template you can use for any project:
# Project Context for AI Agents
_Focus on non-obvious rules that would cause incorrect output if missed._
## Tech Stack & Versions
| Technology | Version | Constraint |
|---|---|---|
| [Framework] | [version] | [critical note or what NOT to do] |
## Commands
| Command | Purpose |
|---|---|
| `[cmd]` | [what it does] |
## Implementation Rules
### [Language] Rules
- **[Rule]:** [why, or what to do instead]
### [Framework] Rules
- **[Rule]:** [why, or what to do instead]
### Component Conventions
- [How components are structured, exported, styled]
### Design System
- [What component library to use, how to install, token system]
### Loading & State Patterns
- [What loading pattern to use and why]
### Testing
- [Framework, pattern, coverage expectations]
## Code Quality
- [Naming conventions]
- [File organisation]
- [Constants and configuration approach]
## Anti-Patterns (NEVER do these)
- Never [specific thing]: [what to do instead]
- Never [specific thing]: [what to do instead]A few things to notice about this structure:
**Rule:** explanation). Each rule is self-contained and unambiguous..ts. Focus on decisions Claude would get wrong without guidance.This template is a form of prompt engineering. You're designing instructions that an AI will follow across many sessions. The same principles apply: be specific, be structured and make every line count.
Now let's put this into practice. Open the AI Prompt Library project and start a session:
cd ai-prompt-library
claudeWe'll use the /init command and give it our conventions at the same time. /init scans your codebase to detect the tech stack, build commands and file structure. By adding our prompt alongside it, Claude combines what it discovers with the standards we specify, all in one step.
Run /init with this prompt:
/init
Scan the codebase and generate a CLAUDE.md following this structure. Use tables for reference data, bold-dash format for rules and include an anti-patterns section at the end.
Include these project conventions:
**Component conventions:**
- Named exports for all components and utilities. Default exports only for Next.js page/layout files.
- Always use `cn()` from `lib/utils.ts` for conditional and dynamic class names. Never use template literals or inline ternaries for combining Tailwind classes.
- Components go in `components/` organised by domain. Shared UI primitives go in `components/ui/`.
**Design system:**
- Use shadcn/ui as our component library. If a shadcn component exists for what you're building (Card, Button, Skeleton, etc.), install and use it rather than hand-rolling with raw Tailwind. Install with `bunx shadcn@latest add <component>`.
- Never hardcode colour values like `bg-zinc-900` or `text-zinc-400`. Use semantic tokens from CSS variables: `bg-card`, `text-muted-foreground`, `border-border`.
**Loading patterns:**
- Use skeleton loaders for loading states, not spinners. Use the shadcn Skeleton component matching the layout of what's loading.
**Testing:**
- Every new feature needs tests. Follow the AAA pattern (Arrange, Act, Assert) with descriptive names: `"should [action] when [condition]"`.
**Code quality:**
- No magic numbers. Extract values like page sizes, delays and thresholds into named constants with a comment explaining the rationale.
- Centralise configuration values rather than scattering them across components.
**Anti-patterns (never do these):**
- Never hand-roll UI that shadcn/ui provides
- Never use raw colour values in components
- Never skip tests for a new feature
- Never use `export default` for non-page components
Claude will scan the project, detect what it can (Next.js 16, TypeScript, Tailwind v4, Biome, the cn() utility), and merge that with your conventions into a structured CLAUDE.md.
Review the result. You should see a file that combines what Claude discovered about your codebase with the standards you specified, all formatted with tables, clear rules and an anti-patterns section. If anything is missing or needs adjustment, just tell Claude to update it.
Note: Your output might look slightly different from what we show in the video. That's fine. The structure and conventions are what matter, not the exact wording.
Notice how each convention in the prompt maps directly to a gap from Section 2:
| Section 2 Gap | Convention We Added |
|---|---|
| Hand-rolled spinner | Skeleton loaders, shadcn Skeleton component |
| Zero tests | Tests required, AAA pattern |
| No design system | shadcn/ui first, install when needed |
| Default exports | Named exports for components |
| Hardcoded colours | Semantic tokens only |
Didn't use cn() | Always use cn(), never template literals |
| Magic numbers | Named constants with rationale |
Every problem from the baseline now has a corresponding rule. Claude doesn't have to guess anymore.
Claude Code gives you two commands to verify your setup.
/memory shows all the CLAUDE.md files and imported references currently active. It's useful for debugging when Claude doesn't seem to follow a convention. Check if the relevant file is actually loaded.
/status gives you a full overview of your session: the model you're running, your login, connected MCP servers and critically, every memory file that's loaded. Here's what it looks like:
Version: 2.1.50
Model: Default Opus 4.6
Memory: user (~/.claude/CLAUDE.md), project (CLAUDE.md)
MCP servers: context7 ✔, deepwiki ✔
The Memory line is the one to check. It lists every file that's influencing Claude's behaviour in this session: user-level, project-level and any @ imported files. If you've added a rule or a CLAUDE.md file and it's not showing up here, Claude isn't reading it.
Before moving on, commit your new CLAUDE.md:
git add CLAUDE.md
git commit -m "feat: add project conventions to CLAUDE.md"In the next lesson, we'll look at how to scale this approach when your conventions grow beyond what a single file can cleanly hold.