How to front-load the right context so Claude produces correct output from message one.
Claude starts every session with zero knowledge of your project beyond what's in CLAUDE.md. Context loading is the practice of giving Claude the right information before it starts working — so the first response is already oriented, not a miss that needs correction.
⬡ What you'll build
Automatically loaded:
Not loaded — Claude must read them:
Never loaded:
This gap between what Claude knows and what it needs is where most session failures originate.
The baseline. CLAUDE.md covers project-level context. /init makes Claude confirm it's loaded:
This confirms Claude absorbed the briefing correctly. If the output is wrong, your CLAUDE.md needs updating before you start working.
For tasks with specific file dependencies, tell Claude to read them before the task:
Before we start, read these files:
- app/api/auth/route.ts
- lib/auth.ts
- middleware.ts
Then tell me what you understand about the current auth flow.This does two things: loads the files into Claude's context, and surfaces any misunderstandings before work begins. If Claude's summary of the auth flow is wrong, correct it before asking Claude to change anything.
For continuing work from a previous session or resuming after a gap, declare the current state explicitly:
Current state:
- Feature branch: feat/user-dashboard (based on main, not merged)
- What's complete: UserDashboard component, the data fetching hook
- What's broken: the stats cards don't update when filters change
- What we haven't done: mobile responsive layout, tests
- Active files: app/dashboard/page.tsx, components/dashboard/, hooks/useUserStats.ts
Today: fix the filter→stats reactivity bug.This eliminates the "re-establishing context" tax at the start of every session.
When debugging, lead with the error — not an explanation of what you were trying to do:
Build failure. Full error:
Type error: Type 'string | undefined' is not assignable to parameter of type 'string'.
45 | const user = await getUser(session.userId)
| ^^^^^^^^^^^^^^
at app/api/profile/route.ts:45:30
Context:
- session.userId comes from: lib/auth.ts:parseSession() → returns SessionData | null
- getUser is at: lib/db.ts:getUser(id: string)
- This worked before we switched session handling last week
Diagnose what's wrong. Don't fix yet — explain first.Claude reads the full error, finds the file, understands the type mismatch, explains the root cause. Then you decide whether the fix is correct before Claude changes anything.
For tasks that will run many tool calls, declare the full scope upfront:
Full scope of today's work:
- We're adding email verification to the registration flow
- Files in scope: app/api/auth/register/route.ts, lib/email.ts (new), app/verify-email/page.tsx (new)
- Files NOT in scope: anything else in app/api/auth/, any existing user schema
- Done when: registration sends a verification email, /verify-email validates the token, TypeScript passes
Read the current register route first, then outline your implementation plan.This prevents scope creep — Claude improving adjacent files you didn't ask it to touch.
The context window has a limit. In Claude Code it's 200k tokens — large, but not infinite. Long sessions with many file reads and responses can fill it.
Signs you're running low:
When context is getting full — use /compact:
/compact summarizes the conversation into a dense summary and discards the verbose history. The summary is kept; the raw conversation is discarded. Run it proactively — don't wait until Claude degrades.
| Task type | Load first | Strategy |
|---|---|---|
| Debugging | Full error output → relevant files | Error-first + file reads |
| New feature | Spec → adjacent existing files | Scope declaration + file reads |
| Refactoring | Files being refactored → tests | File reads + state declaration |
| Code review | Git diff → related files | Paste diff directly into prompt |
| Continuing work | Current state → files in progress | State declaration + /init |
Failure Pattern — Jumping straight to the task
✕ Before (broken pattern)
Fix the performance issue with the dashboard.
✓ After (production pattern)
Context: the dashboard at app/dashboard/page.tsx loads UserStats and ActivityFeed components. Both make separate API calls on mount. Users report 3-4 second load times. Current state: no caching, no loading states, API calls are sequential (ActivityFeed waits for UserStats to finish). Read app/dashboard/page.tsx and the two component files. Then propose a fix — probably parallel data fetching and a skeleton loading state.
Lesson: Without context, Claude has to read everything and guess at the problem. With context front-loaded, Claude reads the right files and proposes a targeted fix.
Your context loading is effective when: