Updated Jul 22, 2026

02 - Context and CLAUDE.md

📋 Jump to Takeaways

🎁 Two engineers give Claude the same task on the same repo. One gets code that fits the codebase, the other gets a confident mess. The difference isn't the prompt, it's what Claude already knew before they typed it.

Claude Code is only as good as the context it has. Give it nothing and it guesses your conventions, your build commands, your architecture. Give it the right context and it stops guessing. This lesson is about controlling what Claude knows.

Context Determines Output

The model doesn't know your project. It knows patterns from training. When you ask for "a new endpoint," it invents one that looks plausible, not one that matches how your team writes endpoints.

Watch what happens without context:

You: Add a health check endpoint.
Claude: (writes an Express route, but your repo uses Fastify)
        (returns { status: "ok" }, but your API wraps everything in { data })
        (skips the auth middleware every other route uses)

Nothing there is wrong in the abstract. It's just wrong for you. The fix isn't a longer prompt every time. It's giving Claude persistent context it reads on its own.

CLAUDE.md as Project Memory

CLAUDE.md is a file at your repo root that Claude Code loads automatically at the start of every session. It's project memory: the stuff you'd tell a new hire on day one so they stop asking.

Put the things Claude can't infer and keeps getting wrong:

# Project: Payments API

## Commands
- Build: `make build`
- Test: `make test` (never `npm test`, it skips integration tests)
- Lint: `make lint` (must pass before commit)

## Conventions
- Framework is Fastify, not Express.
- All responses wrap data: `{ data: ... }` or `{ error: ... }`.
- Every route goes through `authPlugin`. No exceptions.

## Gotchas
- `db.query` is synchronous in tests, async in prod. Use the repo layer.

Keep it short and factual. It's not documentation for humans, it's a briefing for an agent. Commands, conventions, architecture notes, and the traps that bite people. Skip anything Claude can read from the code itself.

File References with @

CLAUDE.md is always-on context. Sometimes you want to pull in a specific file just for the task at hand. Reference it with @ and Claude reads it into context on demand.

Refactor the retry logic in @src/lib/http-client.ts to use
the backoff helper in @src/lib/backoff.ts. Match the style
of @src/lib/rate-limiter.ts.

Now Claude has the exact files instead of searching for them or guessing their contents. Use @ when the task depends on specific code. It beats pasting the file, and it beats hoping Claude finds it.

Context Budget

More context isn't better. Everything you load competes for the model's attention, and a giant CLAUDE.md full of history and edge cases dilutes the signal.

Be selective:

# Good CLAUDE.md: 30 lines of what matters
Commands, conventions, three real gotchas.

# Bad CLAUDE.md: 400 lines
Every architecture decision since 2022, full API docs,
a changelog, and "we value clean code" fluff.

Include what changes the output. Cut what doesn't. If a line wouldn't change a single thing Claude writes, it's noise. Same with @ references, pull in the three files that matter, not the whole src/ tree.

Memory Precedence

Claude Code reads memory from more than one place, and they stack. It walks up the directory tree from where you launched and loads every CLAUDE.md it finds. Knowing the order lets you keep personal notes out of your teammates' way.

~/.claude/CLAUDE.md      # global: applies to every project you work on
workspace/CLAUDE.md      # workspace: shared rules across multiple projects
workspace/my-app/CLAUDE.md    # project: specific to this repo
workspace/my-app/CLAUDE.local.md  # personal notes, gitignored

The most specific file wins when rules contradict. Project overrides workspace, workspace overrides global. Non-contradicting instructions from all levels combine.

Put team conventions in ./CLAUDE.md so everyone gets them. Put your own preferences (your shortcuts, your scratch commands) in the global file or CLAUDE.local.md. The local file is gitignored by convention, so your notes don't end up in a pull request.

Workspace-Level CLAUDE.md

If you manage multiple projects under one parent directory, a CLAUDE.md at that workspace root is a good place for cross-project rules: model selection preferences, formatting standards, or "always do X" instructions that apply everywhere.

workspace/
├── CLAUDE.md           ← shared: model prefs, general rules
├── payments-api/
│   └── CLAUDE.md       ← Fastify conventions, test commands
├── dashboard/
│   └── CLAUDE.md       ← React patterns, deploy steps

There's one critical rule: CLAUDE.md loading is based on where you launch Claude, not where it later reads or writes files. If you run claude from workspace/, only workspace/CLAUDE.md loads. The project-level files inside payments-api/ or dashboard/ are invisible, even if Claude edits files in those directories during the session.

This gives you two workflows:

Focused work:    cd workspace/payments-api && claude
                 → loads workspace/ + payments-api/ CLAUDE.md

Cross-project:   cd workspace && claude
                 → loads workspace/ CLAUDE.md only
                 → reference project rules with @payments-api/CLAUDE.md
                   if needed, or mention them in the prompt

If you often cross-reference projects from the workspace root, put the critical shared context in the workspace-level file and use @ references to pull in project-specific rules when a task needs them.

Keeping CLAUDE.md Fresh

A stale CLAUDE.md is worse than none. If it says the test command is make test but the team switched to just test, Claude confidently runs the wrong thing every session.

Treat it like code:

When conventions change:
- Update CLAUDE.md in the same PR that changes the convention.
- Delete gotchas that no longer apply.
- If Claude keeps making the same mistake, that's a missing line.

The best signal for what belongs in CLAUDE.md is your own frustration. Every time you correct Claude on the same thing twice, that correction is a line you should have written down.

Key Takeaways

  • Claude's output quality is bounded by its context. Without context it guesses your conventions
  • CLAUDE.md at the repo root is loaded automatically every session. It's project memory, not human docs
  • Put commands, conventions, architecture notes, and gotchas in CLAUDE.md. Keep it short and factual
  • Reference specific files on demand with @path/to/file instead of pasting or hoping Claude finds them
  • More context isn't better. Include what changes the output, cut the rest, both in CLAUDE.md and @ refs
  • Memory stacks by walking up the tree: global ~/.claude/CLAUDE.md → workspace CLAUDE.md → project CLAUDE.md → personal CLAUDE.local.md. Most specific wins on contradiction
  • A workspace-level CLAUDE.md is ideal for cross-project rules (model prefs, shared standards). But loading is based on launch directory, not where files are later accessed
  • If you launch from a workspace root and cross-reference projects, use @ includes to pull in project-level rules as needed
  • Update CLAUDE.md when conventions change. Correcting Claude twice on the same thing means a line is missing

🎁 You've given Claude perfect context, but it still built the wrong thing. What if the problem isn't what Claude knows, but how you asked, describing the steps instead of the outcome you actually wanted?

📝 Ready to test your knowledge?

Answer the quiz below to mark this lesson complete.

Spot something off? Report an issue
© 2026 ByteLearn.dev. Free courses for developers. · Privacy