Poison.md — Anti-Patterns That Wreck Sessions
Contradictory rules, context overload, vague constraints. Anti-patterns that degrade output and how to recognize them in your own config.
A bad CLAUDE.md is worse than no CLAUDE.md at all.
That sounds dramatic. It's not. When your config file is clean, Claude Code follows it reliably. When it's bloated, contradictory, or vague, something worse happens. The bad parts don't just get ignored. They poison the good parts too. Your carefully written coding standards get half-followed because they're buried under 400 lines of rambling context that Claude is also trying to obey.
Contradictory Rules
The most destructive anti-pattern. When two rules conflict, Claude picks one arbitrarily. You get inconsistent behavior and no idea why.
## Code Style
- Always use functional components with arrow functions
- Prefer class-based components for complex state management
## Testing
- Write unit tests for every function
- Only write tests when explicitly askedBoth pairs contradict themselves. Claude can't "always use functional components" and also "prefer class-based components." It can't "write tests for every function" and also "only write tests when asked." So it guesses. Sometimes you get one behavior, sometimes the other. Maddening.
This gets worse when contradictions span multiple files. Your user-level file says "use tabs." Your project-level file says "use 2-space indentation." Your local file says nothing about formatting. Claude sees all three and picks. You might not even realize the conflict exists because the files live in different locations.
Fix: Search all your CLAUDE.md files for the same topic. If two files give different guidance for the same behavior, pick one and delete the other. One answer per topic. No exceptions.
Bloated Files
Target under 200 lines per CLAUDE.md file. This isn't about aesthetics.
## API Documentation
The user authentication endpoint accepts POST requests to /api/auth/login
with a JSON body containing email and password fields. The response includes
a JWT token that expires after 24 hours. The refresh token endpoint is at
/api/auth/refresh and accepts the expired token in the Authorization header...
[300 more lines of API docs]This is terrible. Claude can figure out your API structure by reading your code. You've burned 300 lines of context on information that adds zero value. Meanwhile, your actual important rules (the build command, the commit conventions, the architectural decisions) are drowning in noise.
What belongs in CLAUDE.md: Bash commands Claude can't guess, code style rules that differ from defaults, testing instructions, repo etiquette, architectural decisions, dev environment quirks, common gotchas.
What doesn't belong: Anything Claude can figure out by reading code. Standard language conventions. Detailed API docs. Information that changes frequently. File-by-file descriptions. Self-evident stuff like "write clean code."
For each line, ask: "Would removing this cause Claude to make mistakes?" No? Delete it.
Vague Constraints
Vague instructions produce vague compliance. Or nothing at all.
## Guidelines
- Write good code
- Follow best practices
- Keep things organized
- Be careful with error handlingNone of this means anything. "Write good code" isn't an instruction, it's a wish. Claude already tries to write good code. You've wasted four lines of context on instructions that change nothing.
Compare:
## Error Handling
- Wrap all database calls in try/catch blocks
- Log errors with structured JSON (level, message, context)
- Return typed error responses, never raw exception messages
- Use early returns for validation failures before the main logicNow Claude knows exactly what "careful error handling" means in your project. Specific beats vague every single time.
Instruction Bleeding
Without clear markdown boundaries, directives bleed into adjacent sections. Claude reads your CLAUDE.md as continuous context, so a rule in one section can influence behavior in a completely unrelated area.
## Database
Use raw SQL for all queries, never use an ORM.
Always validate inputs before passing to queries.
Frontend components should use server-side rendering.
API routes must return JSON with consistent error shapes.The frontend and API rules are jammed under the "Database" heading. Claude might apply "always validate inputs" only to database code when you meant it for everything. Or it might apply "use raw SQL" more broadly than intended.
Fix: Clear markdown headers. One topic per section. Global rules go in a "General" or "All Code" section, not buried under something specific.
Recognizing Poisoned Config
These are the signals:
- Claude keeps doing something you explicitly told it not to do. File is probably too long and the rule is getting buried.
- Claude asks questions already answered in CLAUDE.md. Phrasing is ambiguous or the file is too big for the instruction to register.
- Behavior is inconsistent across sessions. Contradictory rules. Claude picks different ones each time.
- Some rules followed perfectly, others ignored entirely. The ignored rules are either too vague or conflicting with something else.
When you spot any of these, don't add more instructions. That makes the problem worse.
The Audit
Open every CLAUDE.md file that applies to your project. Your user-level file at ~/.claude/CLAUDE.md, your project file, and any local overrides. Read them all together as one document. Look for:
- Any two rules that give conflicting guidance
- Any instruction that Claude already follows without being told
- Any section longer than 20 lines that could be an
@pathimport instead - Any vague instruction you could replace with a specific one
- Any information that changes frequently and will become stale
Delete everything that fails this audit. You'll almost certainly end up with a shorter file. That's the point.
Prevention
Know what Claude Code already does well by default. You don't need to tell it to "write clean code" or "use descriptive variable names." Adding instructions for built-in behaviors wastes context and crowds out the instructions that actually matter.
Front-load your most important rules. Build commands, critical architectural decisions, hard constraints. Top of the file.
Use a modular approach. Keep the root file lean and use @path imports to reference detailed docs only when needed. A 50-line root file with three targeted imports beats a 400-line monolith every time.
What to Remember
Contradictory rules make Claude guess. Search all your CLAUDE.md files for conflicts on the same topic and kill them. Bloated files poison everything else, so target under 200 lines and cut anything Claude already does without being told.
"Write good code" isn't an instruction. Replace vague rules with specific, actionable ones. And when Claude ignores a rule or behaves inconsistently, the problem is almost always in your config, not in Claude. Audit, find conflicts, prune.
Mastering Claude Code
Lesson 67 of 70