If you use Claude Code, you probably have a CLAUDE.md. But most CLAUDE.md files I've seen actually hurt output quality more than they help.
Here are the 7 most common anti-patterns — and what to do instead.
1. Writing generic instructions Claude ignores
Bad:
- Write clean, readable code
- Follow best practices
- Use meaningful variable names
Claude already tries to do these things. Generic instructions add noise without changing behavior.
Good:
- Never use `var` — always `const` or `let`
- All async functions must handle errors with try/catch — no unhandled promise rejections
- Variable names: `userId` not `id`, `userEmail` not `email`
Specific beats general every time.
2. No architecture rules (the most expensive mistake)
Without explicit architecture rules, Claude will write code wherever is convenient. That means business logic in route handlers, DB queries in components, and utils files that become dumping grounds.
Good (Next.js example):
## Architecture
- `app/` — routing and layouts only, no business logic
- `lib/services/` — all business logic
- `lib/db/` — all database queries, never in components
- `components/` — UI only, no data fetching except via hooks
One rule like this saves hours of refactoring.
3. Forgetting stack-specific gotchas
Every framework has footguns. Claude doesn't know which ones matter to you unless you tell it.
FastAPI example:
- Never use `async def` for CPU-bound operations — use `def` or offload to a thread pool
- Always validate with Pydantic v2 `model_validator` — never raw `dict` access
- DB sessions must use `async with AsyncSession() as session` — never hold sessions open
Next.js App Router example:
- Never use `useEffect` to fetch data — use Server Components or React Query
- Client components only for interactivity — never for data
- Protect routes in `middleware.ts` — never inside page components
4. No testing conventions
Without this, Claude writes tests that technically pass but test nothing meaningful. Or skips tests entirely.
Good:
## Testing
- Unit test business logic in `lib/services/`
- Integration tests for all API endpoints
- Never mock the database in integration tests — use a test DB
- Test file naming: `*.test.ts` colocated with source
- Minimum: happy path + one error case per function
5. Missing environment variable reference
Claude will invent env var names. Then your app breaks in production.
Good:
## Environment Variables
- `DATABASE_URL` — PostgreSQL connection string
- `STRIPE_SECRET_KEY` — never expose to client
- `STRIPE_WEBHOOK_SECRET` — used in `/api/webhooks/stripe` only
- `NEXT_PUBLIC_APP_URL` — only public var, safe for client
6. No error handling conventions
Claude's default error handling is inconsistent — sometimes throws, sometimes returns null, sometimes logs and swallows.
Good:
## Error Handling
- Never swallow errors silently
- Use `Result<T, E>` pattern for recoverable errors
- Throw for programmer errors (invalid state, unexpected data)
- Log at the boundary where the error is first caught — never re-log when wrapping
- User-facing errors: always return a user-safe message, log the real error
7. Writing your CLAUDE.md once and never updating it
Your CLAUDE.md should evolve with your project. Every time Claude makes a mistake that surprised you — add a rule.
That mistake means you found a gap. The next project benefits from it.
The most valuable CLAUDE.md files are the ones with comments like "never do X — we tried this in v2 and it caused Y."
The fix
If writing your CLAUDE.md from scratch sounds like work, I packaged up 25 of them — one for each major stack.
Each one already has specific conventions, architecture rules, anti-patterns, env var references, and testing conventions built in.
→ CLAUDE.md Starter Pack on Gumroad ($47) — or grab 3 free ones from the GitHub repo.
The pack has 5-star reviews from developers who are using it daily. At $100/hr, one saved hour covers it twice.
What's the worst CLAUDE.md anti-pattern you've seen? Drop it in the comments.
Top comments (0)