Practice — CLAUDE.md and Context Configuration (12 questions)
Diagnosing a Bloated CLAUDE.md
A teammate opens a PR adding this to the project's CLAUDE.md:
## Architecture
This project uses a microservices architecture. We have a
`user-service`, an `order-service`, and a `notification-service`,
each in its own directory under `services/`. Each service has its
own `package.json` and `Dockerfile`. Services communicate over
HTTP using REST APIs. We use Express.js for routing and Jest for
testing. Please write clean, well-tested code and follow best
practices for each service.
- Identify which parts of this addition are genuinely useful and which are filler. Explain your reasoning for each.
- Rewrite the section so it earns its place in the file, inventing plausible "surprising" facts about this hypothetical microservices repo (things a competent engineer would not guess from reading the code).
- Explain the mechanism by which this kind of addition, if left as-is, makes the rest of the CLAUDE.md file less effective — not just "wastes space," but actively degrades adherence to other rules.
Share this question
Resolving a Conflict Across the Memory Hierarchy
An engineer has this in ~/.claude/CLAUDE.md (their personal, user-scope
file, present on every project they work on):
Always use tabs for indentation.
The project they're currently working on has this in ./CLAUDE.md
(checked into git, shared with the team):
This project uses 2-space indentation everywhere. Prettier enforces
this on save; do not fight it.
- Explain exactly how these two files end up in the same context window, and in what order.
- Is there a defined winner between these two contradictory instructions? What actually happens when Claude encounters both?
- What should the engineer do to fix this, and why is that the correct fix rather than, say, deleting the project-level instruction?
- Now suppose the engineer instead put "always use tabs" in
CLAUDE.local.mdat the project root. Does that change the analysis, and does it change what's checked into git?
Share this question
What Survives Compaction
Midway through a long Claude Code session in a project with this layout:
repo/
├── CLAUDE.md
└── services/
└── payments/
└── CLAUDE.md
the engineer tells Claude, in chat (not in any file): "actually, don't
touch services/payments/legacy_gateway.py — it's frozen pending a
compliance review." A while later, the conversation grows long enough
that auto-compaction runs. Several turns after that, Claude edits
legacy_gateway.py anyway.
- Explain why the instruction was lost, tracing exactly what happened to it through compaction.
- Would the outcome have been different if the instruction had instead
been added to
repo/CLAUDE.md? Torepo/services/payments/CLAUDE.md? Explain the difference between these two, precisely. - Propose a concrete fix, and explain why it's more robust than simply "reminding Claude again."
Share this question
Choosing Between a CLAUDE.md Rule and a Hook
A team maintains four rules they want Claude Code to follow in their repo.
For each one, decide whether it belongs in CLAUDE.md, as a PreToolUse/
PostToolUse hook, in settings.json permissions, or some combination —
and justify the choice:
- "Prefer composition over deep inheritance hierarchies in the Python codebase."
- "Never allow a commit that includes a file matching
*.pemor*_key.json." - "Run
ruff formatafter every file edit so formatting stays consistent." - "Database migrations must be reviewed by a human before being
applied to staging — Claude should never run
alembic upgradeitself."
Share this question
Scoping a Permissions Block for a New Contractor
A contractor is being onboarded to work on the frontend of a repo for two weeks. The team wants Claude Code to run freely for common frontend tasks without constant approval prompts, but wants to avoid giving broad, unaudited trust given the contractor is temporary and the repo also contains backend and infra code the contractor shouldn't be touching.
A well-meaning teammate proposes this .claude/settings.local.json
for the contractor's checkout:
{
"permissions": {
"allow": [
"Bash(npm *)",
"Bash(git *)"
]
}
}
- Identify the specific risks in this configuration — what could go wrong that the proposer probably didn't intend?
- Rewrite the permissions block to achieve the actual goal (fast, unattended frontend workflow commands) without the risks you identified.
- Explain what role, if any,
permissions.denyshould play here in addition to a narrowerallowlist, and whydenyentries matter even whenallowis already scoped tightly.
Share this question
A CLAUDE.md That Survived a Refactor Badly
Six months ago, a team wrote this into their project's CLAUDE.md:
## Authentication
All authentication logic lives in `middleware/auth.py`. Token
validation happens there before any route handler runs. If you need
to change how tokens are validated, that's the only file to touch.
Since then, the team migrated from a monolithic middleware file to a
per-route dependency-injection pattern: token validation now happens
in auth/dependencies.py, injected individually into each FastAPI
route via Depends(get_current_user). Nobody updated the CLAUDE.md.
- Walk through what happens when a new contributor asks Claude Code to "add rate limiting to the token validation step," with this stale instruction still in place.
- Explain why this failure mode is more dangerous than simply having no instruction about authentication at all.
- Propose a process (not just "update the file") that would make this kind of staleness less likely to reach this point undetected.
Share this question
An Auto Memory Index That Grew Out of Control
Six weeks into a project, an engineer runs /memory, opens the auto
memory folder, and finds this at the top of MEMORY.md (truncated —
the real file is over 260 lines):
# Memory Index
- Build takes about 40 seconds on a clean checkout, faster with cache
- The staging Redis instance sometimes returns stale reads for ~2s
after a write, this bit us once during a demo, worth knowing
- User asked to always use arrow functions instead of function
declarations for one-off callbacks passed to .map()/.filter()
- Debugging the auth flow: the JWT issuer is `https://auth.internal`,
not the public domain, and if you get a "issuer mismatch" error
that's almost always why, also check clock skew between services,
also there's a known issue where...
- ... (256 more lines like this)
- Diagnose exactly what's gone wrong here, tying your answer to the
specific mechanics of how
MEMORY.mdis loaded. - Concretely, what should this file look like instead, and where should the detail that's currently crammed into it go?
- One of the four bullets shown is arguably misplaced system — not just poorly formatted. Identify it and explain where it actually belongs.
Share this question
Sorting Five Rules into Five Mechanisms
A platform team is setting up a new monorepo and has collected five things they want Claude Code to "know" or respect:
- "The repo uses Bazel;
bazel build //...is the only supported build entry point — don't suggestmakeor raw compiler invocations even if you find leftover Makefiles." - Claude discovered, mid-session, that a particular flaky CI job
needs
--test_timeout=120or it spuriously fails, and this isn't written down anywhere in the repo. - "Every file under
services/payments/**must NOT be edited without a second engineer's explicit sign-off in the PR — this is a compliance requirement, not a style preference." - Frontend-specific conventions (component structure, CSS
approach) that only matter to the ~15 engineers who ever touch
apps/web/**, out of 200 engineers in the monorepo. - One engineer's personal habit of wanting commit messages formatted a specific way, across every project they touch, not just this one.
For each, name the single best-fit mechanism (CLAUDE.md, a
.claude/rules/ file, auto memory, settings.json permissions, a
hook, or "personal ~/.claude/CLAUDE.md") and justify it against the
others that might seem plausible.
Share this question
When a Nested CLAUDE.md Actually Loads
A monorepo has this layout:
repo/
├── CLAUDE.md
└── services/
└── billing/
└── CLAUDE.md
An engineer runs cd repo && claude and, as their very first message in
the brand-new session, asks Claude to summarize the rules in
services/billing/CLAUDE.md — before Claude has read or edited any
file under services/billing/.
At the exact moment that first message is sent (before Claude acts on
it), is services/billing/CLAUDE.md already loaded into context?
Share this question
How Much of a Bloated MEMORY.md Actually Loads
An engineer's auto memory MEMORY.md has grown to 340 lines (roughly
30KB) after months of a long-running project. They want to know
exactly what happens at the start of the next brand-new session.
Which statement correctly describes how much of this file Claude Code loads into context at session start?
Share this question
What Exit Code 2 Does to a Hook's Tool Call
A team writes a PreToolUse hook meant to block any Bash call
containing rm -rf. During testing, a bug in the script's exit-code
handling causes it to exit with status code 2 on a totally harmless
command that doesn't match the dangerous pattern — and the script
prints nothing to stdout.
Given how Claude Code interprets hook exit codes, what happens to that harmless tool call?
Share this question
Where a Chat-Stated Preference Actually Gets Saved
Mid-session, an engineer types: "remember that we always use pnpm, not npm, in this repo" — with no further instruction about where that should be recorded.
Using Claude Code's default behavior (no explicit request to update CLAUDE.md), where does this preference actually end up?
Share this question