Back to Learn
Best Practices
12 min read

Writing Effective Claude Rules: A Complete Guide

clauderules.net

The Anatomy of a Bad Rule

Most developers write their first CLAUDE.md rules like this:

CLAUDE.md
## Rules
- Write clean code
- Follow best practices
- Be concise

These are useless. Claude already tries to write clean code. "Best practices" is undefined. "Be concise" is subjective. These rules consume tokens without changing Claude's behavior.

Specificity: The First Principle

Every rule should answer: what specifically should change about Claude's default behavior? Compare the example below against real TypeScript CLAUDE.md rules to see how teams encode strict-mode flags concretely.

CLAUDE.md
# Bad
- Use TypeScript properly

# Good
- Enable TypeScript strict mode with noUncheckedIndexedAccess and exactOptionalPropertyTypes
- Never use `any` — use `unknown` and narrow with type guards
- Prefer interface over type for object shapes
- Use `as const` for enum-like objects

Explain the Why

Rules with rationale are more effective than bare commands. Claude can apply a rule more consistently — and adapt it to novel situations — when it understands the intent.

CLAUDE.md
## Error Handling
Always use typed error results instead of throwing:

```ts
// Preferred pattern — avoids untyped thrown errors
type Result<T> = { ok: true; value: T } | { ok: false; error: string }
```

Why: Our API routes need predictable error shapes for the frontend client.
Throwing errors produces inconsistent HTTP responses.

Constraints Over Permissions

Claude makes sensible default choices. Your rules are most valuable when they constrain Claude away from valid-but-wrong choices for your project.

CLAUDE.md
## Constraints
- NEVER install new npm packages without asking first
- NEVER modify prisma/schema.prisma without running `prisma db push` after
- NEVER use relative imports — always use the @ alias
- NEVER add console.log to production code (use the logger in lib/logger.ts)

Ordering Your Rules

Structure your CLAUDE.md from most-to-least important:

  1. Critical constraints — things that will break the build or cause security issues
  2. Tech stack — framework, libraries, versions
  3. Code style — naming, patterns, idioms
  4. File structure — where things live
  5. Commands — how to run and build the project
  6. Domain context — business logic rules

Code Examples as Rules

The most effective rules show Claude a pattern, not just a principle. Include short before/after examples for your most important conventions. The route-handler example below is taken from community Next.js CLAUDE.md rules.

CLAUDE.md
## API Route Pattern

Always use this structure for API routes:

```ts
export async function GET(req: NextRequest) {
  try {
    // ... implementation
    return NextResponse.json(data)
  } catch (error) {
    console.error('[GET /api/route]', error)
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 })
  }
}
```

Don't forget: validate input with Zod before processing.

Keeping Rules Current

Stale rules cause confusion. When you upgrade a library, change an architectural pattern, or drop a tool, update CLAUDE.md immediately.

A monthly CLAUDE.md review is a healthy habit. Ask: does every rule still apply? Have we introduced new patterns that should be documented? Remove anything that's no longer true.

Frequently asked questions

What makes a CLAUDE.md rule ineffective?+

Vague, generic rules like "write clean code", "follow best practices", and "be concise" are essentially useless. Claude already tries to write clean code, "best practices" is undefined, and "be concise" is subjective — these rules consume tokens without changing Claude's behavior. Effective rules are specific. Instead of "use TypeScript properly", write something like "Enable strict mode with noUncheckedIndexedAccess and exactOptionalPropertyTypes; never use any — use unknown and narrow with type guards." Every rule should answer: what specifically should change about Claude's default behavior?

Why should I include the rationale (why) for each rule?+

Rules with rationale are more effective than bare commands because Claude can apply a rule more consistently — and adapt it to novel situations — when it understands the intent. For example, a rule that says "always use typed Result<T> error returns instead of throwing" plus "Why: our API routes need predictable error shapes for the frontend client; throwing produces inconsistent HTTP responses" gives Claude enough context to make the right call in cases the rule didn't explicitly cover. Bare commands without the why often miss edge cases.

How should I order rules in my CLAUDE.md file?+

Order rules from most-to-least important so the most consequential constraints get the most attention. A useful structure: critical constraints first (anything that breaks the build or causes security issues), then tech stack with versions, then code style and naming conventions, then file structure, then build and run commands, and finally domain-specific business logic context. Putting "NEVER commit .env files" near the top alongside the tech stack signals that breaking that rule has serious consequences, while routine code-style preferences sit lower in the document.

Is it better to specify what NOT to do or what TO do?+

Constraints — what NOT to do — tend to be more valuable than permissions. Claude makes sensible default choices on its own, so your rules add the most value when they steer Claude away from valid-but-wrong choices for your project. Examples that work well: "NEVER install new npm packages without asking first", "NEVER modify prisma/schema.prisma without running prisma db push after", "NEVER use relative imports — always use the @ alias", "NEVER add console.log to production code; use the logger in lib/logger.ts." These prevent the specific failure modes you've already encountered.

How often should I review and update my CLAUDE.md rules?+

A monthly CLAUDE.md review is a healthy habit. When you upgrade a library, change an architectural pattern, or drop a tool, update CLAUDE.md immediately — stale rules cause confusion and a stale CLAUDE.md is actually worse than none, because it teaches Claude outdated patterns. During the review ask: does every rule still apply, have we introduced new patterns that should be documented, and is anything obsolete? Remove anything that's no longer true; keep the document lean and current.

Why are code examples more effective than principles alone?+

The most effective rules show Claude a pattern, not just a principle. Including a short before/after example for your most important conventions gives Claude something concrete to mimic. For instance, instead of just saying "use this structure for API routes", include a 10-line code block that shows the exact try/catch shape, the JSON response format, and a "validate input with Zod before processing" reminder. Pattern-based examples generalize well — Claude can replicate the structure across many similar cases.

Get the Claude Code Starter Pack

Top CLAUDE.md rules for Next.js, TypeScript, Python, Go, and React — delivered free to your inbox.