AI / GenAI  /  Claude Code

📄 Claude Code (CLAUDE.md) Guide 3 of 4 16 guides · updated 2026

Writing effective CLAUDE.md files — project memory, conventions, permissions, hooks, and the team practices that keep AI coding agents genuinely useful.

Coding Conventions & Style Guides in CLAUDE.md

Coding conventions are one of the easiest CLAUDE.md sections to get wrong in a specific way: restating what your linter and formatter already enforce mechanically, while leaving out the conventions that actually require human judgment — the ones no tool can auto-fix.


Skip What’s Already Enforced

<!-- Redundant if ESLint already enforces this -->
- Always use semicolons
- Use 2-space indentation
- No unused variables
<!-- Worth stating — these require judgment a linter can't automate -->
- Prefer composition over inheritance for shared behavior between components
- Error messages shown to users must never include raw exception text or stack traces
- New API endpoints must be added to `openapi.yaml` in the same PR

If a rule is fully enforced by tooling, the agent will encounter it as a lint error regardless of whether CLAUDE.md mentions it — restating it adds nothing. Reserve the file for conventions that are matters of judgment, not mechanically checkable rules.


State the “Why” When It’s Non-Obvious

A convention with an unstated rationale is easy to accidentally violate in an edge case the rule-writer didn’t anticipate; a convention with its reasoning attached is much easier to apply correctly to new situations.

<!-- Just the rule -->
- Don't use `Array.prototype.sort()` without a comparator function.
<!-- Rule plus reasoning — generalizes better -->
- Don't use `Array.prototype.sort()` without a comparator function — the default
sort coerces to strings, which silently misorders our numeric IDs. This applies
to any sort of numeric or mixed-type data, not just the specific case that
originally surfaced the bug.

The second version equips the agent to recognize other situations the same underlying issue applies to, not just the one example given.


Naming and Organization Conventions

## Naming
- React components: PascalCase, one component per file, filename matches
component name (`UserAvatar.tsx` exports `UserAvatar`)
- Hooks: camelCase prefixed with `use` (`useUserData`, not `getUserData`)
- Test files: colocated, `<name>.test.ts` next to `<name>.ts`
- Boolean variables/props: prefixed with `is`/`has`/`should`
(`isLoading`, not `loading`)

Naming conventions are a case where being explicit genuinely changes agent output — without guidance, an agent will pick a reasonable-but-possibly-inconsistent convention of its own, and consistency across a codebase compounds in value the larger it gets.


Error Handling and Defensive Patterns

## Error Handling
- User-facing errors go through `formatUserError()` — never surface raw error
messages or stack traces in UI-visible text
- Internal service errors should be logged with `logger.error()` including a
request ID, then re-thrown — don't swallow errors silently
- Prefer typed error classes (`ValidationError`, `NotFoundError`) over generic
`Error` when the error type needs to be distinguished downstream

Error-handling conventions are especially worth documenting because inconsistency here often isn’t caught by tests (a swallowed error might not cause a visible failure) but has real production consequences.


Testing Philosophy

## Testing Philosophy
- We favor integration tests over heavily-mocked unit tests for anything
touching the database — mocks have drifted from real schema before and
masked real bugs
- New features need at least one test covering the primary success path;
100% branch coverage is not required or expected
- Snapshot tests are avoided — they tend to be updated reflexively without
review rather than genuinely verified

This kind of philosophical guidance — not just mechanical style rules — is exactly the sort of context a new human contributor would only pick up after several code reviews, and exactly what CLAUDE.md can shortcut.


Common Mistakes

Documenting style choices a formatter (Prettier, Black, gofmt) already enforces automatically. These tools exist specifically so nobody — human or agent — needs to think about them; restating them in CLAUDE.md is pure redundancy.

Writing conventions as bare rules without examples. “Prefer composition over inheritance” is more useful with even a short code snippet showing what that looks like in this specific codebase’s idioms than as an abstract principle alone.

Conventions sections that contradict what the linter config actually enforces. If CLAUDE.md says “we use single quotes” but ESLint is configured for double quotes, the file is actively wrong — treat convention documentation as something that needs to stay synchronized with the actual enforced configuration, not just written once and assumed accurate.

Frequently Asked Questions

Should I document a full style guide, or link to an external one? If your team already has a comprehensive external style guide (a company-wide engineering handbook, for instance), link to it and use CLAUDE.md only for genuine deviations or project-specific additions — duplicating an entire external document into CLAUDE.md creates a second copy that will drift out of sync.

How do I handle conventions that are actively being changed/migrated? State the transition explicitly rather than presenting the old convention as current: “New code should use the Result<T, E> pattern for error handling; older code still uses exceptions and is being migrated incrementally — don’t convert existing exception-based code unless that’s the specific task.”

Is it worth documenting conventions the team disagrees about? Better to resolve the disagreement (even provisionally) and document the resolution than to leave it ambiguous — an unstated internal disagreement just means the agent’s behavior on that point becomes inconsistent and unpredictable across sessions.

Summary

The highest-value convention documentation is exactly the material a linter can’t enforce and a new hire would only learn through code review: naming philosophy, error-handling patterns, testing approach, and the reasoning behind non-obvious rules. Skip what tooling already guarantees, and where you do document a rule, attach its “why” — that’s what lets an agent apply it correctly to situations the original rule-writer never explicitly anticipated.