Context Management
The context problem
Claude Code starts every session knowing nothing about your project. It can read files, but it doesn't know which files matter, what conventions you follow, or what mistakes to avoid. Without context, it makes generic decisions.
CLAUDE.md solves this. It's a file that Claude reads at the start of every session, containing project-specific instructions the model always follows.
Think of CLAUDE.md as a briefing document for a new team member who happens to be extremely capable but knows nothing about your project. What would you tell them on day one? Your tech stack, naming conventions, testing requirements, architecture decisions, things to avoid. That's your CLAUDE.md.
The hierarchy
CLAUDE.md files follow a precedence order. Higher levels override lower levels:
- Managed policy - organization-level rules (set by admins, cannot be overridden)
- Project CLAUDE.md -
./CLAUDE.mdor./.claude/CLAUDE.mdin your repo root - User CLAUDE.md -
~/.claude/CLAUDE.md(your personal global instructions)
Project-level is where you'll spend most of your time. It lives in your repo and gets committed to git, so the whole team shares the same context.
Writing a good CLAUDE.md
Keep it under 200 lines. Claude reads this on every session start, so brevity matters. Focus on what's unique about your project.
# My Project
## Tech Stack
- Next.js 15 with App Router
- TypeScript strict mode
- Tailwind CSS
- PostgreSQL with Drizzle ORM
## Conventions
- Use named exports, not default exports
- All components in src/components/
- API routes in src/app/api/
- Database queries go through src/lib/db/
## Testing
- Run tests: `npm test`
- Run type check: `npx tsc --noEmit`
- All new features need tests
## Things to avoid
- Never use `any` type
- Don't install new dependencies without asking
- Don't modify the database schema without discussionWhat to include:
- Tech stack - framework, language, database, key libraries
- Conventions - naming, file structure, patterns
- Commands - how to test, build, lint, deploy
- Constraints - what not to do, common mistakes, gotchas
What to leave out:
- Generic programming advice (Claude already knows)
- Full API documentation (too long, use @-imports instead)
- Content that changes frequently (use @-imports to reference live files)
@-imports
For context that lives in other files, use the @ import syntax:
# My Project
See @README.md for project overview.
See @docs/architecture.md for system design.
See @docs/api.md for API documentation.Claude will read the referenced files when it processes the CLAUDE.md. This keeps your CLAUDE.md short while still providing rich context.
Don't import everything. Each imported file uses context window space. Import only the files Claude needs for most tasks. For specialized context, let Claude read files on demand during the session.
Settings files
Claude Code has two settings files per project:
.claude/settings.json - shared settings, committed to git. Team-wide permissions, allowed commands, denied commands.
.claude/settings.local.json - personal settings, gitignored. Individual overrides, personal preferences, local API keys.
{
"permissions": {
"allow": ["Read", "Glob", "Grep", "Bash(npm test)"],
"deny": ["Bash(git push --force*)"]
}
}{
"permissions": {
"allow": ["Bash(npm run dev)"]
}
}Local settings merge with shared settings. If shared settings deny something, local settings cannot override that denial.
Path-specific rules
For large repos where different directories have different conventions, use .claude/rules/*.md files with paths: frontmatter:
---
paths:
- src/components/**
- src/app/**
---
Use React Server Components by default.
Only add "use client" when the component needs interactivity.
All components must have TypeScript props interfaces.---
paths:
- src/app/api/**
---
All API routes must validate input with Zod.
Always return proper HTTP status codes.
Include rate limiting headers.These rules activate only when Claude is working on files matching the paths. This keeps context focused and avoids loading irrelevant instructions.
Managing the context window
Claude Code has a 200K token context window. That's large but not infinite. During long sessions, the window fills up with conversation history, file contents, and command outputs.
/compact
When the context window gets full, use /compact to summarize the conversation:
> /compact
Claude condenses the conversation history into a summary, freeing up space. The summary preserves key decisions, current task state, and important file paths. Details of completed work are compressed.
Claude Code automatically compacts when the context window is nearly full. You don't have to manage this manually, but proactive compaction before a complex task gives Claude more room to work.
What gets compacted
- Completed tasks (decisions preserved, details compressed)
- File contents that were read but aren't actively being edited
- Command outputs that have been processed
What survives compaction
- Current task state and next steps
- File paths being actively modified
- Unresolved errors
- Your instructions from this session
- Key decisions and their rationale
Putting it all together
A well-configured project looks like this:
your-project/
CLAUDE.md # Project context
.claude/
settings.json # Shared permissions (committed)
settings.local.json # Personal overrides (gitignored)
rules/
frontend.md # Rules for frontend code
api.md # Rules for API code
This gives Claude the context it needs to make good decisions, the permissions to act safely, and path-specific rules for different parts of your codebase.
Create your project's CLAUDE.md
Pick a real project you work on and create a CLAUDE.md for it:
- Create a
CLAUDE.mdin the project root - Include: tech stack, conventions, commands, constraints
- Add 1-2
@imports for important documentation files - Keep it under 200 lines
- Start Claude Code and verify it reads your CLAUDE.md (ask "what do you know about this project?")
A minimal but effective CLAUDE.md:
# Project Name
## Stack
- Next.js 15, TypeScript, Tailwind, Prisma, PostgreSQL
## Commands
- `npm run dev` - start dev server
- `npm test` - run tests
- `npx tsc --noEmit` - type check
## Conventions
- Named exports only
- Components in src/components/
- Server Components by default, "use client" only when needed
## Don't
- Use `any` type
- Skip tests for new features
- Modify prisma/schema.prisma without discussion
See @README.md for project overview.After starting Claude Code, ask "what project is this?" - Claude should reference your CLAUDE.md content in its response. If it doesn't, check the file is in the project root and properly formatted.
Set up path-specific rules
If your project has distinct areas (frontend, backend, API, tests), create path-specific rules:
- Create
.claude/rules/directory - Add at least two rule files with
paths:frontmatter - Test by asking Claude to work on files in each path and verify it follows the right rules
---
paths:
- src/**/*.test.ts
- src/**/*.test.tsx
- tests/**
---
Use vitest for all tests.
Prefer integration tests over unit tests.
Mock external services, never mock internal modules.
Every test file needs at least one happy path and one error case.Verify by asking Claude to write a test - it should follow these conventions. Then ask it to write a component - these test rules should not be active.
CLAUDE.md is the single highest-leverage thing students will set up in this course. A good CLAUDE.md turns Claude from a generic coding assistant into a team member who knows your project. Encourage students to start small and iterate - they'll discover what Claude needs to know as they use it.