The definitive guide to teaching Claude Code your rules, conventions, and project context -- so it follows your standards every session with
The definitive guide to teaching Claude Code your rules, conventions, and project context -- so it follows your standards every session without being told twice.
Every time you start a new Claude Code session, Claude starts fresh. It does not remember your last conversation. It does not know your project uses Prettier with single quotes. It does not know your team runs pnpm instead of npm. It does not know that src/legacy/ should never be modified.
CLAUDE.md is how you solve this. It is a plain Markdown file that gets loaded into Claude's context at the start of every session. Think of it as a permanent onboarding document for an infinitely patient team member who reads it cover to cover before writing a single line of code.
Imagine hiring a senior developer. On their first day, you would not hand them a laptop and say "figure it out." You would:
That is exactly what CLAUDE.md does. Each session is day one for Claude. Your CLAUDE.md file is the onboarding packet that makes day one productive instead of wasteful.
CLAUDE.md files have become so common that Apple's engineering team accidentally shipped one inside an official app release -- a sign that large organizations are now using Claude Code heavily in their development workflows. This is a good reminder that CLAUDE.md files live in your project directory, get committed to git, and can end up anywhere your code goes. Set them up intentionally. We will cover what should and should not go in them throughout this guide.
Context loss between sessions remains one of the most-discussed frustrations in the Claude Code community. Developers routinely burn tokens re-explaining the same project context at the start of every session. CLAUDE.md is the direct answer to this problem, but only if it is maintained as a living document. A well-structured CLAUDE.md eliminates re-explanation almost entirely. A stale or vague one creates a false sense of security while solving nothing.
By the end of this guide, you will be able to:
Claude Code loads instructions from multiple locations in a specific order. Understanding this hierarchy is essential -- it determines which rules take effect and who sees them.
Priority (highest to lowest):
1. Managed Policy CLAUDE.md -- Organization-wide, cannot be overridden
2. Project CLAUDE.md -- Team-shared, committed to git
3. Project Rules (.claude/rules/) -- Modular, topic-specific, committed to git
4. User CLAUDE.md -- Personal, applies to all projects
5. Project Local (CLAUDE.local.md) -- Personal, this project only
6. Auto Memory -- Claude's own notes, per-project
Purpose: Organization-wide instructions enforced by IT or DevOps. These cannot be overridden by any other layer.
File locations:
/Library/Application Support/ClaudeCode/CLAUDE.md/etc/claude-code/CLAUDE.mdC:\Program Files\ClaudeCode\CLAUDE.mdWho uses this: Enterprise teams that need to enforce company-wide coding standards, security policies, or compliance requirements across every developer's machine.
Example content:
# Company Policy
- All code must pass security scanning before commit
- Never use dynamic code execution functions
- All API endpoints must include rate limiting
- Follow OWASP Top 10 guidelines for web applications
- Use approved open-source licenses only (MIT, Apache 2.0, BSD)
Git status: Not in any repository. Deployed via MDM, Ansible, or other configuration management.
Purpose: Team-shared instructions that travel with the project repository. This is the most commonly used layer.
File locations (either works, not both):
./CLAUDE.md (project root)./.claude/CLAUDE.md (inside .claude directory)Who uses this: Every team member working on the project. These rules are committed to version control and shared via git.
Example content:
# MyApp
A Next.js 14 e-commerce platform using TypeScript, Prisma, and PostgreSQL.
## Commands
- Build: `pnpm build`
- Test: `pnpm test`
- Lint: `pnpm lint`
- Dev server: `pnpm dev`
## Rules
- Use TypeScript strict mode everywhere
- Components go in src/components/ with PascalCase filenames
- API routes go in src/app/api/ following Next.js App Router conventions
- All database queries go through Prisma -- never write raw SQL
Git status: Committed to the repository.
Purpose: Modular, topic-specific instructions. Instead of one large CLAUDE.md, you can split rules into focused files.
File location: ./.claude/rules/*.md (supports subdirectories)
Directory structure example:
.claude/rules/
code-style.md # Formatting and naming conventions
testing.md # Test patterns and requirements
security.md # Security-related rules
git-conventions.md # Commit messages, branch naming
frontend/
react.md # React-specific patterns
styles.md # CSS/styling rules
backend/
api.md # API design rules
database.md # Database conventions
All .md files in .claude/rules/ are automatically loaded as project memory. They share the same priority as .claude/CLAUDE.md.
Git status: Committed to the repository.
Purpose: Your personal preferences that apply across every project you work on.
File location: ~/.claude/CLAUDE.md
Who uses this: Just you. This file is not in any repository. Use it for preferences that follow you everywhere.
Example content:
# Personal Preferences
- I prefer functional programming patterns over class-based approaches
- When writing commit messages, use conventional commits format
- Always explain your reasoning before making changes
- I use VS Code -- reference VS Code shortcuts when relevant
- When asked to refactor, preserve all existing behavior unless told otherwise
Git status: Not in any repository. Lives in your home directory.
Purpose: Your personal preferences for a specific project. Perfect for things your teammates do not need to see.
File location: ./CLAUDE.local.md (project root)
Who uses this: Just you. This file is automatically added to .gitignore by Claude Code.
Example content:
# My Local Settings
- My dev API key is in .env.local (already gitignored)
- I run the dev server on port 3001 because 3000 conflicts with another project
- My test database is at localhost:5433 (non-standard port)
- Skip the E2E tests when I say "run tests" -- they take 10 minutes.
Only run them when I explicitly ask.
Git status: Automatically gitignored. Never committed.
Purpose: Notes that Claude writes for itself based on what it learns during sessions. This is not a file you author -- Claude maintains it automatically.
File location: ~/.claude/projects/<project>/memory/
Directory structure:
~/.claude/projects/<project>/memory/
MEMORY.md # Main index -- first 200 lines loaded at startup
debugging.md # Notes about debugging patterns
api-conventions.md # API design decisions Claude observed
build-issues.md # Build problems and their solutions
How it works:
MEMORY.md are loaded into context at the start of every sessiondebugging.md) are read on demand, not at startup<project> path is derived from the git repository rootOpt-in/out:
export CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 # Force off
export CLAUDE_CODE_DISABLE_AUTO_MEMORY=0 # Force on
Git status: Not in any repository. Stored in your home directory under ~/.claude/.
Note on Managed Agents: Anthropic has added persistent memory capabilities to Claude Managed Agents (currently in public beta). This includes a "dreaming" process where agents consolidate and preserve context between sessions automatically. The dreaming mechanism lets long-running automated agents accumulate knowledge across runs without you needing to write or maintain memory files manually. If you are running Claude in agentic or automated workflows rather than interactive sessions, this changes the picture considerably. For standard interactive Claude Code sessions, the six-layer memory hierarchy above is what governs your experience.
Claude loads all memory files at the start of every session. The rule is: more specific instructions take precedence over broader ones.
1. Managed policy CLAUDE.md (loaded first, highest authority)
2. CLAUDE.md files from parent directories (recursive upward from cwd)
3. Project CLAUDE.md or .claude/CLAUDE.md
4. .claude/rules/*.md files
5. User ~/.claude/CLAUDE.md
6. CLAUDE.local.md
7. Auto memory (first 200 lines of MEMORY.md)
If your user CLAUDE.md says "use tabs" but your project CLAUDE.md says "use 2-space indentation," the project rule wins because it is more specific to the current context.
CLAUDE.md files in child directories (subdirectories below your working directory) are not loaded at startup. They are loaded on demand when Claude reads files in those subdirectories.
| File | Commit to Git? | Reason |
|---|---|---|
CLAUDE.md |
Yes | Team-shared project rules |
.claude/CLAUDE.md |
Yes | Team-shared project rules (alternate location) |
.claude/rules/*.md |
Yes | Team-shared modular rules |
CLAUDE.local.md |
No (auto-gitignored) | Personal project preferences |
~/.claude/CLAUDE.md |
N/A (not in repo) | Personal global preferences |
~/.claude/projects/*/memory/ |
N/A (not in repo) | Auto-generated by Claude |
When rules are not loading or Claude is ignoring your instructions, a few commands help you understand what is actually in context:
/context -- Shows what files are loaded and how much context they consume
/memory -- Opens your memory files for inspection and editing
/doctor -- Runs a full diagnostic: checks file locations, schema errors,
common misconfigurations
Run /doctor first. It catches the most common configuration problems -- wrong file locations, glob pattern syntax errors in hooks, settings being overridden by a higher-priority scope -- before you go digging through files manually. The official debug documentation at https://code.claude.com/docs/en/debug-your-config covers the full diagnostic workflow.
The /init command is the fastest way to bootstrap a CLAUDE.md for your project. When you run it inside Claude Code, Claude will:
package.json, pyproject.toml, Makefile, tsconfig.json, etc.# Inside Claude Code, just type:
> /init
Claude will generate a CLAUDE.md file in your project root (or .claude/CLAUDE.md depending on your project structure).
A typical /init output includes:
For a Next.js project, /init might generate:
# MyStore
E-commerce platform built with Next.js 14, TypeScript, and Prisma.
## Tech Stack
- Framework: Next.js 14 (App Router)
- Language: TypeScript (strict mode)
- Database: PostgreSQL via Prisma ORM
- Styling: Tailwind CSS
- Testing: Vitest + React Testing Library
- Package Manager: pnpm
## Commands
- Install: `pnpm install`
- Dev: `pnpm dev`
- Build: `pnpm build`
- Test: `pnpm test`
- Lint: `pnpm lint`
- Type check: `pnpm tsc --noEmit`
- Database migrate: `pnpm prisma migrate dev`
## Project Structure
- `src/app/` - Next.js App Router pages and API routes
- `src/components/` - React components
- `src/lib/` - Utility functions and shared logic
- `prisma/` - Database schema and migrations
- `public/` - Static assets
| Scenario | Recommendation |
|---|---|
| New project, getting started quickly | Use /init then customize |
| Existing project with established conventions | Manual creation for precision |
| You want a starting point to iterate on | Use /init as a first draft |
| Your team has a CLAUDE.md template | Start from the template |
| Simple script or small project | Manual -- /init might over-generate |
The generated file is always a starting point. After /init, you should:
/init infers, and inference can be wrongThe worst thing you can do is run /init and never touch the file again. The best CLAUDE.md files are living documents maintained over time.
A well-structured CLAUDE.md answers five fundamental questions. This framework comes from the same onboarding analogy -- these are the five things any new team member needs to know on day one.
Give Claude the 30-second pitch. What does this project do? What technologies does it use? What is the architecture?
Why it matters: Without this, Claude guesses. It might assume a different framework, a different architecture pattern, or a different target audience.
Good example:
# ShipTracker
Real-time cargo ship tracking platform. Users monitor vessel locations,
view route histories, and receive ETA notifications.
## Architecture
- Monorepo with apps/web (Next.js) and apps/api (Express)
- PostgreSQL for persistent data, Redis for real-time vessel positions
- WebSocket connections for live map updates
- AIS data ingested from MarineTraffic API every 30 seconds
Bad example:
# My Project
A web app.
List every command Claude might need. Build, test, lint, deploy, database migrations, code generation -- all of it. Claude will use these commands constantly, and getting them wrong wastes time.
Why it matters: Claude frequently needs to run your test suite, build your project, or check for lint errors. If it does not know the exact commands, it will guess (often wrong) or ask you every time.
Good example:
## Commands
### Development
- Install dependencies: `pnpm install`
- Start dev server: `pnpm dev` (runs on port 3000)
- Start API server: `pnpm --filter api dev` (runs on port 4000)
### Testing
- Run all tests: `pnpm test`
- Run single test file: `pnpm test -- path/to/file.test.ts`
- Run tests in watch mode: `pnpm test:watch`
- Run E2E tests: `pnpm test:e2e` (requires dev server running)
### Code Quality
- Lint: `pnpm lint`
- Type check: `pnpm tsc --noEmit`
- Format: `pnpm format`
### Database
- Generate migration: `pnpm prisma migrate dev --name <name>`
- Apply migrations: `pnpm prisma migrate deploy`
- Reset database: `pnpm prisma migrate reset`
- Open Prisma Studio: `pnpm prisma studio`
Bad example:
## Commands
- npm test
This is where you define coding standards, naming conventions, file organization, and any other patterns Claude should follow.
Why it matters: Without explicit rules, Claude falls back to general best practices. Those might not match your project. Your team uses named exports? Claude might use default exports. Your API returns snake_case? Claude might return camelCase.
Good example:
## Code Style
### TypeScript
- Use named exports, never default exports
- Prefer `interface` over `type` for object shapes
- Use `const` assertions for literal types
- All function parameters must be typed -- no implicit `any`
- Prefer early returns over nested conditionals
### React
- Functional components only -- no class components
- Use named function declarations, not arrow functions, for components
- Props interfaces go in the same file, named `{ComponentName}Props`
- State management: use Zustand for global state, useState for local
- Never use useEffect for data fetching -- use React Query
### API
- All endpoints return `{ data, error, meta }` envelope
- Use HTTP status codes correctly (201 for creation, 204 for deletion)
- Validate all inputs with Zod schemas
- Error responses include a machine-readable `code` field
### File Organization
- Components: `src/components/{ComponentName}/{ComponentName}.tsx`
- Tests: colocated as `{ComponentName}.test.tsx`
- Hooks: `src/hooks/use{HookName}.ts`
- Utils: `src/utils/{utilName}.ts`
Bad example:
## Rules
- Write clean code
- Follow best practices
Every project has landmines -- legacy code that looks wrong but works, workarounds for bugs in dependencies, files that must not be touched. Document them here.
Why it matters: Claude is eager to help. If it sees code that looks "wrong," it might try to fix it. If that code is a deliberate workaround, Claude just broke your app.
Good example:
## Gotchas
IMPORTANT: Do NOT modify anything in src/legacy/. This code is scheduled for
removal in Q3 but is still in production. It looks broken but works correctly.
IMPORTANT: The `formatCurrency()` function in src/utils/currency.ts has
intentional floating-point handling that looks like a bug. It compensates for
a rounding issue in Stripe's API. Do not "fix" it.
- The test database uses a non-standard port (5433) to avoid conflicts with
the production Postgres instance that some developers run locally.
- `pnpm install` must be run from the repo root, not from individual
packages. The workspace configuration requires it.
- The CI pipeline runs tests against Node 18, not Node 20. Some Node 20
features are not available.
- Environment variables prefixed with `NEXT_PUBLIC_` are exposed to the
browser. Never put secrets in them.
Bad example:
## Notes
- Be careful with the code
Define the collaboration model. How should Claude communicate changes? Should it explain before acting? Should it commit directly or wait for review?
Why it matters: Some developers want Claude to explain everything. Others want it to just make changes silently. Some want atomic commits. Others want a single big commit at the end. Spell it out.
Good example:
## Workflow
- Before making changes, briefly explain what you plan to do and why.
- Make changes in small, atomic steps. Commit after each logical change.
- Always run `pnpm lint` and `pnpm tsc --noEmit` after making changes.
- When creating commits, use conventional commit format:
`type(scope): description`
Types: feat, fix, refactor, test, docs, chore
- When I ask you to fix a bug, first write a failing test that reproduces it,
then fix the bug, then verify the test passes.
- If you are unsure about a change, ask. Do not guess.
- When refactoring, never change behavior. If I ask for a refactor that would
change behavior, flag it and ask for confirmation.
Here is a full CLAUDE.md that answers all five questions for a React project:
# TaskFlow
Project management SaaS built with Next.js 14, TypeScript, Prisma, and PostgreSQL.
Users create workspaces, invite team members, and manage tasks on Kanban boards.
## Commands
- Install: `pnpm install`
- Dev: `pnpm dev` (port 3000)
- Build: `pnpm build`
- Test: `pnpm test`
- Test single: `pnpm test -- path/to/file.test.ts`
- Lint: `pnpm lint`
- Type check: `pnpm tsc --noEmit`
- DB migrate: `pnpm prisma migrate dev --name <name>`
- DB seed: `pnpm prisma db seed`
## Code Style
- TypeScript strict mode everywhere
- Named exports only -- no default exports
- React: functional components with named function declarations
- Props: `interface {Name}Props` in same file
- State: Zustand for global, useState for local
- Data fetching: React Query, never useEffect
- API responses: `{ data, error, meta }` envelope
- All inputs validated with Zod
- File naming: PascalCase for components, camelCase for utils
## File Structure
- `src/app/` -- pages and API routes (App Router)
- `src/components/` -- shared components
- `src/features/` -- feature-specific components and logic
- `src/hooks/` -- custom hooks
- `src/lib/` -- utility functions, configs, constants
- `prisma/` -- schema and migrations
## Gotchas
IMPORTANT: The `src/lib/auth.ts` file uses a custom JWT implementation
because next-auth did not support our multi-tenant workspace model. Do not
replace it with next-auth.
- The `workspace_id` column in the tasks table has a trigger that auto-sets
it from the parent board. Never set it manually in application code.
- Tests use a separate test database. Run `pnpm db:test:reset` if tests
fail with schema errors.
## Workflow
- Explain changes briefly before making them
- Run `pnpm lint && pnpm tsc --noEmit` after every change
- Use conventional commits: `type(scope): description`
- When fixing bugs, write a failing test first
- Ask before modifying any file in `src/lib/auth.ts` or `prisma/schema.prisma`
# logparse
CLI tool for parsing, filtering, and analyzing structured log files.
Supports JSON, logfmt, and Common Log Format. Outputs to stdout, CSV, or JSON.
## Commands
- Install (dev): `pip install -e ".[dev]"`
- Run: `python -m logparse <logfile> [options]`
- Test: `pytest`
- Test single: `pytest tests/test_parsers.py::test_json_parser`
- Test with coverage: `pytest --cov=logparse --cov-report=term-missing`
- Lint: `ruff check .`
- Format: `ruff format .`
- Type check: `mypy logparse/`
## Code Style
- Python 3.11+ -- use modern syntax (match/case, type unions with |)
- Type hints on all function signatures -- no untyped public functions
- Docstrings: Google style on all public functions and classes
- Prefer dataclasses over plain dicts for structured data
- Use pathlib.Path, never os.path
- Imports: stdlib first, third-party second, local third (ruff handles sorting)
- Error handling: raise specific exceptions from logparse/exceptions.py
- Never use print() for output -- use the OutputWriter abstraction
## File Structure
- `logparse/` -- main package
- `logparse/parsers/` -- one parser per log format
- `logparse/formatters/` -- output formatters (csv, json, table)
- `logparse/cli.py` -- CLI entry point (Click)
- `tests/` -- mirrors the package structure
- `tests/fixtures/` -- sample log files for testing
## Gotchas
IMPORTANT: The Common Log Format parser in `logparse/parsers/clf.py`
handles a non-standard timestamp format used by legacy Apache configs.
The regex looks wrong but matches real-world data. Do not simplify it.
- The `--follow` flag uses inotify on Linux and kqueue on macOS. Tests
for this feature are skipped in CI (no filesystem events in containers).
- Some test fixtures contain intentionally malformed log lines. They are
there to test error handling -- do not "fix" them.
## Workflow
- Always run `pytest` and `ruff check .` after changes
- Type check with `mypy logparse/` before committing
- Write tests for all new parsers and formatters
- When adding a new parser, also add fixture files in tests/fixtures/
- Use conventional commits: `type: description`
The quality of your CLAUDE.md rules directly determines how well Claude follows them. Vague rules get vague compliance. Specific rules get specific compliance.
When a rule is critical and must never be violated, prefix it with IMPORTANT:. Claude Code treats this keyword with higher priority.
IMPORTANT: Never modify files in the src/generated/ directory. These files
are auto-generated by the GraphQL codegen tool and will be overwritten.
IMPORTANT: All API endpoints must validate input with Zod schemas before
processing. No exceptions.
Do not overuse IMPORTANT:. If everything is important, nothing is important. Reserve it for rules that, if broken, would cause real problems.
Every rule should be actionable. Claude should be able to read it and know exactly what to do (or not do).
Vague (bad):
- Write good tests
- Use proper error handling
- Follow coding standards
- Keep the code clean
Specific (good):
- Every new function must have at least one unit test
- Catch errors at the API boundary and return { error: { code, message } }
- Use 2-space indentation, single quotes, no semicolons
- Functions must be under 50 lines. If longer, extract helper functions.
Showing both sides makes rules unambiguous.
## Component Naming
Components use PascalCase with descriptive names.
Good:
- UserProfileCard.tsx
- PaymentMethodSelector.tsx
- OrderSummaryTable.tsx
Bad:
- userprofilecard.tsx (wrong case)
- Card.tsx (too generic)
- UPC.tsx (abbreviation)
## Error Handling
Good:
try {
const user = await getUser(id);
return { data: user };
} catch (error) {
logger.error('Failed to get user', { userId: id, error });
return { error: { code: 'USER_NOT_FOUND', message: 'User does not exist' } };
}
Bad:
try {
const user = await getUser(id);
return user;
} catch (e) {
console.log(e);
return null;
}
Good news: Claude's ability to follow instructions has improved dramatically. Recent research shows Claude Opus 4.7 can reliably follow around 500 instructions, up from roughly 150 in mid-2025. That sounds like a green light to stuff your CLAUDE.md with every rule you can think of. It is not.
Here is why: Claude's built-in system prompt already consumes roughly 50 of those available instruction slots. More importantly, every rule you add is context that is not available for reasoning about your actual code. A bloated CLAUDE.md makes Claude slower and more likely to miss things buried deep in the file. And most of those extra rules you are tempted to add? They cover behavior Claude does by default anyway.
The goal is not to write as many rules as the model can theoretically handle. The goal is to write the smallest number of high-signal rules that make Claude behave exactly the way you need for this specific project.
Guidelines for staying lean:
.claude/rules/ to keep the main CLAUDE.md shortHere is an insight worth knowing, especially if you are on Claude Opus 4.7 or newer: instructing Claude what to do works better than instructing it what not to do.
Why it matters: Negative framing requires the model to generate output, check it against the constraint, and regenerate if there is a violation. Positive framing allows continuous forward progress without those correction cycles. The result is fewer tokens consumed and more consistent compliance.
Negative (less efficient):
- Never use default exports
- Do not write class components
- Never use any types in TypeScript
- Do not use useEffect for data fetching
Positive (more efficient):
- Use named exports only
- Write functional components only
- Type all values explicitly with specific types
- Use React Query for all data fetching
The meaning is identical. The framing is not. On newer models especially, the positive version produces better results.
Abstract rules describe what you want. Concrete patterns show Claude exactly how to do it. When you give Claude a real code pattern to replicate rather than a principle to interpret, it produces more consistent output.
This is why the "include examples" advice matters so much. A rule like "use the standard error response format" requires interpretation. A rule that shows the format directly -- { error: { code: string, message: string } } -- does not. Whenever a rule can be illustrated with a code snippet, illustrate it.
CLAUDE.md is also your tool for suppressing behavioral patterns that are model-specific and not what you want. Claude Opus 4.7, for example, has a tendency toward "human-pacing" -- suggesting work breaks, splitting tasks into more phases than necessary, and adding wellness check-ins. If this is slowing you down:
## Workflow
- Assume 24/7 availability. Do not suggest work breaks or splitting work
across multiple days.
- Implement tasks fully in one pass. Do not propose phased approaches unless
I specifically request them.
- Skip wellness check-ins and time-estimate warnings.
If Claude is repeatedly doing something you do not want, there is almost always a CLAUDE.md entry that addresses it. Do not just correct it in conversation -- write the rule, commit it, and fix it permanently.
Read your CLAUDE.md from top to bottom. If it takes more than 60 seconds to read and understand, it is probably too long. A new team member should be able to skim it and start being productive.
If you need extensive documentation, use @imports (covered in Advanced Features) to reference external docs instead of inlining everything.
For each rule you write, verify:
For larger projects, one big CLAUDE.md can become unwieldy. The .claude/rules/ directory lets you split instructions into focused, topic-specific files.
your-project/
.claude/
CLAUDE.md # High-level project overview (keep short)
rules/
code-style.md # Formatting, naming, patterns
testing.md # Test conventions and requirements
git-conventions.md # Commit messages, branch naming
security.md # Security requirements
frontend/
react.md # React-specific patterns
styles.md # CSS and styling rules
backend/
api.md # API design rules
database.md # Database conventions
All .md files in .claude/rules/ are discovered recursively. Subdirectories are supported for better organization.
code-style.md, git-conventions.mdfrontend/, backend/, devops/# Code Style Rules
## TypeScript
- Use `interface` for object shapes, `type` for unions and intersections
- Prefer `const` over `let`. Never use `var`
- Use template literals over string concatenation
- Destructure function parameters when there are 3+ properties
## Naming
- Variables and functions: camelCase
- Types and interfaces: PascalCase
- Constants: SCREAMING_SNAKE_CASE
- Files: camelCase for utilities, PascalCase for components
- Database columns: snake_case
## Formatting
- 2-space indentation
- Single quotes for strings
- No semicolons (enforced by Prettier)
- Max line length: 100 characters
# Testing Conventions
## Structure
- Test files are colocated with source: `Button.test.tsx` next to `Button.tsx`
- Use `describe` blocks to group related tests
- Test names should describe the expected behavior:
`it('renders error message when form is invalid')`
## Patterns
- Use React Testing Library for component tests
- Query elements by role or text content, never by class name or test ID
- Use `userEvent` over `fireEvent` for user interactions
- Mock API calls with MSW (Mock Service Worker), not jest.fn()
- Each test should be independent -- no shared mutable state between tests
## Coverage
- All new code must have tests
- Bug fixes must include a regression test
- Aim for 80% branch coverage on critical paths (auth, payments, data mutations)
# Git Conventions
## Commit Messages
Format: `type(scope): description`
Types:
- feat: new feature
- fix: bug fix
- refactor: code restructuring without behavior change
- test: adding or updating tests
- docs: documentation changes
- chore: tooling, dependencies, config
Scope: the area of the codebase (auth, payments, ui, api, db)
Examples:
- `feat(auth): add password reset flow`
- `fix(payments): handle Stripe webhook retry correctly`
- `refactor(api): extract validation middleware`
## Branches
- Feature branches: `feature/TICKET-short-description`
- Bug fixes: `fix/TICKET-short-description`
- Always branch from `main`
Here is something that trips people up when they first discover rules files: splitting rules into .claude/rules/ files does not give you free context. Every .md file in .claude/rules/ is loaded into the same context budget as your main CLAUDE.md. Twenty rule files containing 50 lines each is the same context cost as one 1,000-line CLAUDE.md.
This does not mean rules files are pointless -- organization, path-scoping, and team ownership are all real benefits. But if you find yourself accumulating dozens of rule files, check the total line count across all of them. The same lean philosophy that applies to your main CLAUDE.md applies to the entire .claude/rules/ collection combined.
Use path-scoped frontmatter (covered in the next section) to limit which rules load for which files. That is where the real context savings come from.
Rules can be scoped to specific files using YAML frontmatter with a paths field. These conditional rules only load when Claude is working with files that match the specified glob patterns.
---
paths:
- "src/api/**/*.ts"
---
# API Development Rules
- All API endpoints must include input validation with Zod
- Use the standard error response format from src/lib/errors.ts
- Include OpenAPI documentation comments on every endpoint
- Rate limiting is required on all public endpoints
- Authentication middleware must be applied to all non-public routes
---
paths:
- "**/*.test.ts"
- "**/*.test.tsx"
- "**/*.spec.ts"
---
# Test File Rules
- Use describe/it blocks, not test()
- One assertion per test when possible
- Mock external services, never call real APIs in tests
- Use factories for test data, not inline object literals
Rules without a paths field are loaded unconditionally and apply to all files.
| Pattern | Matches |
|---|---|
**/*.ts |
All TypeScript files in any directory |
src/**/* |
All files under src/ |
*.md |
Markdown files in the project root only |
src/components/*.tsx |
React components in a specific directory |
src/**/*.{ts,tsx} |
Both .ts and .tsx files under src/ |
{src,lib}/**/*.ts |
TypeScript files in either src/ or lib/ |
The .claude/rules/ directory supports symlinks. This is useful for sharing common rules across multiple projects:
# Symlink a shared rules directory
ln -s ~/company-claude-rules/shared .claude/rules/shared
# Symlink an individual rule file
ln -s ~/company-claude-rules/security.md .claude/rules/security.md
You can also create personal rules at ~/.claude/rules/ that apply to all your projects:
~/.claude/rules/
preferences.md # Your personal coding preferences
workflows.md # Your preferred work patterns
User-level rules are loaded before project rules, giving project rules higher priority when they conflict.
| Content | Where to Put It |
|---|---|
| Project overview, architecture | Main CLAUDE.md |
| Build/test/run commands | Main CLAUDE.md |
| Key gotchas and warnings | Main CLAUDE.md |
| Language-specific coding standards | .claude/rules/code-style.md |
| Testing conventions | .claude/rules/testing.md |
| Git workflow rules | .claude/rules/git-conventions.md |
| API-only rules (path-scoped) | .claude/rules/api.md with frontmatter |
| Test-only rules (path-scoped) | .claude/rules/testing.md with frontmatter |
Rule of thumb: If it applies to everything, put it in CLAUDE.md. If it applies to a specific topic or file type, put it in a rules file. And use path-scoped frontmatter whenever possible to avoid loading rules Claude does not need for the current work.
CLAUDE.md files can import additional files using @path/to/file syntax. This keeps your CLAUDE.md lean while giving Claude access to detailed documentation.
# MyProject
See @README.md for project overview and @package.json for available commands.
## Additional Instructions
- Follow the API design guidelines in @docs/api-design.md
- Git workflow is documented at @docs/git-workflow.md
- Component patterns are described in @docs/component-patterns.md
Key details:
@anthropic-ai/claude-code)Example with home directory imports:
If you work across multiple git worktrees, CLAUDE.local.md only exists in one. Use a home-directory import so all worktrees share the same personal instructions:
# Individual Preferences
- @~/.claude/my-project-instructions.md
As covered in the Modular Rules section, rules files can include YAML frontmatter to scope them to specific file patterns. This is one of the most powerful features for large codebases.
Multiple patterns:
---
paths:
- "src/**/*.ts"
- "lib/**/*.ts"
- "tests/**/*.test.ts"
---
# TypeScript Rules
Use strict mode. Prefer interfaces over types for object shapes.
Brace expansion:
---
paths:
- "src/**/*.{ts,tsx}"
- "{src,lib}/**/*.ts"
---
Output styles are a distinct configuration layer from CLAUDE.md. Where CLAUDE.md tells Claude what to do and what to know, output styles tell Claude how to communicate -- adjusting its role, tone, and output format through system prompt adjustments.
Built-in output styles:
Custom output styles: You can create your own as Markdown files with YAML frontmatter, saved at three levels:
~/.claude/output-styles/your-style.md.claude/output-styles/your-style.mdExample custom style:
---
name: terse-coder
description: Minimal output, code first, explanations only when asked
---
# Terse Coder
- Lead with code. Explanation comes after, only if asked.
- No preamble. No "Great question!" or "Certainly!".
- Skip "Here is the updated file..." -- just show the diff.
- Use inline comments instead of separate explanations.
- When done, say done. That's it.
How to activate: Output styles take effect at the start of a new session. Configure them through /config inside Claude Code, or by editing .claude/settings.local.json directly.
Note the distinction: output styles belong in the settings/styles system, not in CLAUDE.md. If you find yourself writing instructions about Claude's communication style in your CLAUDE.md (be concise, lead with code, no preamble), consider moving those to a custom output style instead.
Auto memory is Claude's own notebook. Unlike CLAUDE.md files that contain instructions you write, auto memory contains notes Claude writes for itself.
What Claude remembers automatically:
Managing auto memory:
/memory to open the auto memory file in your editor~/.claude/projects/<project>/memory/How the directory structure works:
~/.claude/projects/<project>/memory/
MEMORY.md # Index file -- first 200 lines loaded at startup
debugging.md # Detailed debugging notes (loaded on demand)
api-conventions.md # API patterns (loaded on demand)
Claude keeps MEMORY.md concise by moving detailed notes into separate topic files that it reads on demand when needed.
Run /memory during a session to open a file selector showing all your memory files (both CLAUDE.md files and auto memory). You can select any file to open it in your system editor for direct editing.
This is useful for:
When rules are not loading, Claude is ignoring your instructions, or something is behaving unexpectedly, these commands help you understand what is actually in context:
/context -- Shows what files are loaded and how much context they consume
/memory -- Opens your memory files for inspection and editing
/skills -- Lists available skills Claude can invoke
/mcp -- Shows connected MCP server status
/doctor -- Runs a full diagnostic: checks file locations, schema validation,
common misconfigurations, settings overrides
Common issues and fixes:
| Problem | Likely Cause | Fix |
|---|---|---|
| Rules file not loading | Wrong directory location | Run /doctor to verify path |
| Path-scoped rules not activating | Glob pattern syntax error | Check frontmatter carefully |
| Settings being ignored | Override by higher-priority scope | Check which scope wins with /context |
| Hook not firing | Matcher syntax error | Run /doctor to check matcher |
| Instructions followed early, ignored later | Context window filling up | Compact or start a new session |
Run /doctor first. It catches the most common configuration problems before you go digging through files manually. The full documentation is at https://code.claude.com/docs/en/debug-your-config.
If you are building automated agents with the Claude Code Agent SDK, it inherits all the same filesystem-based features you use interactively: CLAUDE.md files, .claude/rules/ files, skills, and hooks. The settingSources option controls which configuration locations the SDK loads.
This means agent configurations you write as CLAUDE.md and rules files work identically whether Claude is running interactively in your terminal or headlessly inside an automated pipeline. The same instructions, the same rules, the same memory hierarchy.
These two configuration systems serve different purposes. Do not confuse them.
CLAUDE.md is for instructions and context:
settings.json is for system behavior:
Settings file locations:
~/.claude/settings.json # Personal, all projects
.claude/settings.json # Project, committed to git
.claude/settings.local.json # Personal project overrides, gitignored
Managed settings (enterprise):
macOS: /Library/Application Support/ClaudeCode/managed-settings.json
Linux/WSL: /etc/claude-code/managed-settings.json
Windows: C:\Program Files\ClaudeCode\managed-settings.json
Example settings.json:
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"allow": [
"Bash(pnpm test *)",
"Bash(pnpm lint)",
"Bash(pnpm build)",
"Bash(git status)",
"Bash(git diff *)"
],
"deny": [
"Bash(rm -rf *)",
"Bash(git push --force *)"
]
}
}
Rule of thumb: If it changes what Claude knows, it goes in CLAUDE.md. If it changes what Claude is allowed to do, it goes in settings.json. If it changes how Claude communicates, it goes in an output style.
One more thing: for truly critical rules that cannot be violated, settings.json permissions and hooks are more reliable than CLAUDE.md text. CLAUDE.md instructions can be missed or deprioritized, especially in long sessions as context fills up. Bash hooks and permission deny rules are enforced deterministically regardless of what else is in context. Use both: CLAUDE.md for guidance, settings.json for hard stops.
The project CLAUDE.md (either ./CLAUDE.md or ./.claude/CLAUDE.md) and all files in .claude/rules/ are designed to be committed to version control. This means every team member gets the same instructions automatically.
Workflow:
/init)Establish ground rules for how your team maintains the file:
## CLAUDE.md Maintenance
- Changes to CLAUDE.md require a PR review, just like code changes
- When you discover a new gotcha, add it immediately and commit
- Review CLAUDE.md quarterly to remove outdated rules
- If Claude repeatedly makes the same mistake, add a rule for it
- Tag CLAUDE.md changes with the `docs` type:
`docs: add API validation rule to CLAUDE.md`
The CLAUDE.md going stale is one of the most common failure modes teams run into. People update the codebase but forget to update the instructions. When that happens, Claude starts working from outdated context and the file becomes worse than useless -- it actively misleads. Treat it like a test: if the code changes, the documentation changes.
Different team members often care about different concerns. The rules directory lets you divide ownership:
.claude/rules/
code-style.md # Owned by: tech lead
testing.md # Owned by: QA engineer
security.md # Owned by: security team
api-design.md # Owned by: backend lead
accessibility.md # Owned by: frontend lead
deployment.md # Owned by: DevOps
Each file can be reviewed and maintained by the person most knowledgeable about that topic.
Inevitably, team members will have different preferences. Handle this with the hierarchy:
Team-shared rules go in project CLAUDE.md or .claude/rules/:
# These are team conventions -- everyone follows these
- Use Prettier for formatting (config in .prettierrc)
- Commit messages use conventional commits format
- Tests are required for all new features
Personal preferences go in CLAUDE.local.md:
# My personal preferences -- only I see these
- I prefer verbose explanations before code changes
- When I say "run tests," skip the E2E suite unless I specify
- I like to see the diff before you commit
CLAUDE.local.md is automatically gitignored. Use it for:
Example:
# Local Overrides
- My local API runs on port 4001 (team default is 4000)
- I use Docker for PostgreSQL: `docker compose up -d db`
- When running tests, use `--reporter=verbose` so I can see individual test names
- I prefer TypeScript errors shown inline, not in a separate panel
If you work across multiple machines -- desktop plus laptop, home office plus work office -- you will want your ~/.claude/CLAUDE.md and user-level rules synced. The simplest approach is to store them in a dotfiles git repository and symlink from the expected location:
# In your dotfiles repo
mkdir -p ~/.dotfiles/claude
cp ~/.claude/CLAUDE.md ~/.dotfiles/claude/CLAUDE.md
# Symlink back
ln -sf ~/.dotfiles/claude/CLAUDE.md ~/.claude/CLAUDE.md
Your user-level rules at ~/.claude/rules/ can be handled the same way. Commit your dotfiles repo and pull it on every machine you use.
Tag your CLAUDE.md at significant versions so you can track how your instructions evolve:
# After a major CLAUDE.md update
git tag claude-md-v2 -m "Added API validation rules and testing conventions"
When Claude does something wrong because of a missing or unclear rule:
This is the "fix the root cause" approach. Do not just correct Claude once and move on -- add the rule so it never happens again.
# Acme Dashboard
Internal business intelligence dashboard built with Next.js 14, TypeScript,
and Tremor for data visualization. Connects to a PostgreSQL analytics database
via Prisma.
## Commands
- Install: `pnpm install`
- Dev: `pnpm dev` (port 3000)
- Build: `pnpm build`
- Test: `pnpm test`
- Test single file: `pnpm test -- path/to/file.test.tsx`
- Lint: `pnpm lint`
- Type check: `pnpm tsc --noEmit`
- Storybook: `pnpm storybook` (port 6006)
- DB migrate: `pnpm prisma migrate dev --name <name>`
- DB seed: `pnpm prisma db seed`
## Architecture
- `src/app/` -- Next.js App Router (pages, layouts, API routes)
- `src/components/` -- shared UI components
- `src/features/` -- feature modules (each has components/, hooks/, utils/)
- `src/lib/` -- shared utilities, database client, auth helpers
- `prisma/` -- schema and migrations
## Code Style
- TypeScript strict mode, no `any` types
- Named exports only
- React: functional components with named function declarations
- Props: `interface {Name}Props` in same file, above the component
- Hooks: `use{Name}` in `src/hooks/` or feature-specific `hooks/` directory
- State: Zustand stores in `src/stores/`, local state with useState
- Data fetching: React Query, never useEffect
- Styling: Tailwind CSS utility classes, no inline styles, no CSS modules
- Charts: Tremor components, custom charts use Recharts
## API Routes
- All routes return `{ data, error }` envelope
- Input validation: Zod schemas in `src/lib/validators/`
- Auth: check session with `getServerSession()` at the top of every route
- Error format: `{ error: { code: string, message: string } }`
## Testing
- Framework: Vitest + React Testing Library
- Colocated tests: `Component.test.tsx` next to `Component.tsx`
- Query by role or text, never by test ID
- Mock API responses with MSW handlers in `src/mocks/`
- Database tests use a separate test database (see .env.test)
## Gotchas
IMPORTANT: Do not modify `src/lib/legacy-auth.ts`. It handles SSO for
clients still on the legacy auth system. Replacement is planned for Q3.
IMPORTANT: The `analytics_events` table uses partitioning by month. Always
include a date range filter in queries to avoid full table scans.
- Tremor components have limited customization. If you need something custom,
use Recharts directly instead of fighting Tremor's API.
- The `seed.ts` file generates deterministic fake data. If you change the
seed, snapshot tests will fail.
- CI runs on Node 18. Do not use Node 20+ features.
## Workflow
- Explain planned changes before implementing
- Run `pnpm lint && pnpm tsc --noEmit` after every change
- Conventional commits: `type(scope): description`
- When fixing bugs, write a failing test first
# deployer
CLI tool for deploying applications to Kubernetes clusters. Reads deploy
manifests from YAML files, validates them, and applies them using kubectl.
## Commands
- Install: `pip install -e ".[dev]"`
- Run: `python -m deployer <manifest.yaml> [options]`
- Test: `pytest`
- Test verbose: `pytest -v`
- Test single: `pytest tests/test_validators.py -k test_name`
- Coverage: `pytest --cov=deployer --cov-report=term-missing`
- Lint: `ruff check .`
- Format: `ruff format .`
- Type check: `mypy deployer/`
- Build: `python -m build`
## Architecture
- `deployer/` -- main package
- `cli.py` -- Click-based CLI entry point
- `manifest.py` -- YAML manifest parsing and validation
- `k8s/` -- Kubernetes client wrappers
- `validators/` -- manifest validation rules
- `formatters/` -- output formatters (table, json, yaml)
- `exceptions.py` -- custom exception hierarchy
- `tests/` -- mirrors package structure
- `fixtures/` -- sample YAML manifests for testing
- `conftest.py` -- shared fixtures and mocks
## Code Style
- Python 3.11+ -- use modern syntax (match/case, `X | Y` unions, `Self`)
- Type hints on all function signatures
- Google-style docstrings on all public functions and classes
- dataclasses for structured data, never plain dicts for domain objects
- pathlib.Path everywhere, never os.path
- Use specific exceptions from `deployer/exceptions.py`
- No print() -- use `click.echo()` for CLI output, `logging` for debug
- Prefer composition over inheritance
- Limit function length to 40 lines
## Testing
- pytest with fixtures defined in conftest.py
- Use `tmp_path` fixture for file operations
- Mock kubectl calls -- never invoke real kubectl in tests
- Factory functions for test data in `tests/factories.py`
- Parametrize tests when testing multiple input variations
- All new validators must have both valid and invalid test cases
## Gotchas
IMPORTANT: The kubectl wrapper in `deployer/k8s/client.py` uses subprocess,
not the Python kubernetes library. This is intentional -- the Python library
has version compatibility issues with newer cluster versions.
- Some YAML fixtures in `tests/fixtures/` are intentionally invalid (they
test error handling). Do not fix them.
- The `--dry-run` flag must ALWAYS work without a real cluster connection.
Tests for dry-run mode should never mock a cluster.
- The manifest schema in `deployer/manifest.py` supports both v1 and v2
formats. Both must be maintained until v1 deprecation in Q4.
## Workflow
- Run `pytest && ruff check . && mypy deployer/` after every change
- Write tests for all new validators and formatters
- Use conventional commits: `type: description`
- If adding a new CLI option, update both the `--help` text and README.md
# FitLog
Fitness tracking mobile app built with React Native (Expo), TypeScript,
and Firebase. Available on iOS and Android. Users log workouts, track
progress, and follow training programs.
## Commands
- Install: `npx expo install`
- Start: `npx expo start`
- iOS: `npx expo run:ios`
- Android: `npx expo run:android`
- Test: `jest`
- Test single: `jest path/to/file.test.tsx`
- Lint: `npx eslint .`
- Type check: `npx tsc --noEmit`
- EAS build (dev): `eas build --profile development`
- EAS build (prod): `eas build --profile production`
## Architecture
- `app/` -- Expo Router file-based routing
- `(tabs)/` -- main tab navigation
- `(auth)/` -- authentication flow
- `workout/` -- workout logging screens
- `components/` -- shared UI components
- `features/` -- feature-specific logic (hooks, utils, types)
- `services/` -- Firebase services, API clients
- `stores/` -- Zustand state stores
- `constants/` -- app-wide constants, theme, config
## Code Style
- TypeScript strict mode
- Functional components with named function declarations
- Props interface: `{Name}Props` in same file
- Navigation: Expo Router, never React Navigation directly
- State: Zustand for global state, useState for component state
- Async storage: use the `useStorage` hook from `hooks/useStorage.ts`
- Styling: StyleSheet.create() at bottom of component file
- Colors, spacing, fonts: always use constants from `constants/theme.ts`
- Animations: Reanimated 3 for gesture-based, LayoutAnimation for simple
## Firebase Rules
- Auth: Firebase Auth with email/password and Google Sign-In
- Database: Firestore with the following collections:
- `users/{uid}` -- user profile
- `users/{uid}/workouts/{id}` -- workout logs
- `users/{uid}/programs/{id}` -- training programs
- `exercises` -- global exercise database (read-only for users)
- Storage: Firebase Storage for profile photos only
- All Firestore reads/writes go through `services/firestore.ts`
## Testing
- Jest + React Native Testing Library
- Test files colocated: `Component.test.tsx`
- Mock Firebase with `__mocks__/firebase/` directory
- Use `renderWithProviders()` from `tests/utils.tsx` for components
that need navigation or store context
- Snapshot tests only for static UI components (not interactive ones)
## Gotchas
IMPORTANT: Never import directly from `firebase/firestore`. Always use
the wrapper functions in `services/firestore.ts` which handle offline
persistence and error logging.
IMPORTANT: The `exercises` collection is seeded from a CSV file during
deployment. Do not write to it from the app. It is read-only.
- Expo SDK upgrades require careful testing on both platforms. Do not
upgrade the SDK without explicit instruction.
- The workout timer uses `react-native-background-timer` for background
execution. It behaves differently on iOS and Android -- test both.
- Push notifications use Expo Notifications, not Firebase Cloud Messaging
directly. The FCM token is bridged through Expo's API.
- The `useWorkoutTimer` hook has a known race condition when the app
backgrounds and foregrounds rapidly. There is a workaround in place --
do not refactor the timer logic without understanding the issue.
## Workflow
- Test on both iOS and Android when making UI changes
- Run `jest && npx tsc --noEmit` after every change
- Use conventional commits: `type(scope): description`
Scopes: workout, auth, profile, programs, ui
- When adding a new screen, create the route file in app/ first,
then build the screen component in the feature directory
Run through this checklist after creating or updating your CLAUDE.md.
.claude/rules/*.md files is also reasonableCLAUDE.md or .claude/CLAUDE.md is committed to version control.claude/rules/*.md are committed to version controlCLAUDE.local.md is in .gitignore (auto-handled by Claude Code)~/.claude/CLAUDE.md contains only cross-project personal preferences/init to generate a starter CLAUDE.mdTake an existing project and write a CLAUDE.md from scratch using only the 5-Question Framework:
Take a CLAUDE.md that is over 150 lines and refactor it into modular rules:
.claude/rules/ directorypaths to at least one fileCLAUDE.local.md~/.claude/CLAUDE.md.claude/rules/ directory in your project---
paths:
- "src/api/**/*.ts"
---
# API-specific rules here
---
paths:
- "**/*.test.ts"
- "**/*.test.tsx"
---
# Testing-specific rules here
Follow the API design guidelines in @docs/api-design.md
/doctor and read the output carefully/context to see what is actually loaded and how much context it consumesBoris Cherny is an engineer at Anthropic who works on Claude Code. His publicly documented workflow includes several insights about CLAUDE.md usage.
Your project CLAUDE.md should be committed and shared like any other source file. Every Claude Code instance across the team reads the same instructions. This creates consistency -- Claude follows the same rules whether your frontend developer or your backend developer is using it.
When Claude does something wrong, do not just correct it in conversation and move on. Add a rule to CLAUDE.md immediately. If Claude used npm instead of pnpm, add: "Use pnpm, not npm, for all package management commands." Commit the change. Now every future session (for you and your team) gets it right.
Beyond coding standards, CLAUDE.md is excellent for current project context that multiple Claude sessions need:
## Current Sprint Context
- Working on: User Authentication (Sprint 14)
- API base URL: /api/v2
- Database: PostgreSQL with Prisma ORM
- Active feature flags: ENABLE_SSO, ENABLE_MFA
Boris runs multiple parallel Claude sessions. Every token in CLAUDE.md is loaded into every session. A 500-line CLAUDE.md consumed across 5 sessions is 2,500 lines of context overhead. Keep the main file focused and use @imports or .claude/rules/ for detailed documentation.
When you make significant changes to your CLAUDE.md, tag the commit. This lets you track how your instructions evolve over time and roll back if a rule causes problems.
Instead of copying your API documentation into CLAUDE.md, reference it:
See @docs/API_REFERENCE.md for endpoint specifications.
See @docs/DATABASE_SCHEMA.md for table definitions.
This prevents CLAUDE.md from becoming a maintenance burden where changes need to be made in two places.
If you find yourself giving Claude the same instructions repeatedly (like a specific commit-push-PR workflow), create a custom slash command instead of putting it in CLAUDE.md. CLAUDE.md is for persistent context and rules, not for scripting workflows.
Problem: A 500+ line CLAUDE.md that covers every possible scenario.
Why it fails: Every line consumes context window. Claude may miss important rules buried in a wall of text. Contradictions become likely as the file grows. And while Claude can now follow significantly more instructions than it could a year ago, that capacity is shared with everything else in context -- the more you write, the less room there is for reasoning about your actual code.
Fix: Keep the main file under 200 lines. Use .claude/rules/ for detailed topic-specific rules. Use @imports for reference documentation. And use path-scoped frontmatter so rules only load when they are actually relevant.
Problem:
- Write clean code
- Follow best practices
- Make sure the code works
- Use proper error handling
Why it fails: These are not actionable. Claude already tries to write working code. You have not told it anything useful.
Fix: Be specific:
- Functions must be under 50 lines
- All errors must be caught at the API boundary and returned as { error: { code, message } }
- No any types in TypeScript
- All async functions must have try/catch blocks
Problem:
- Write syntactically valid code
- Use proper variable names
- Import dependencies before using them
- Do not write code with bugs
Why it fails: Claude does these things by default. You are wasting context on things that do not need to be said.
Fix: Only include rules that make YOUR project different from generic best practices.
Problem:
- Always use arrow functions for components
...
(200 lines later)
...
- Use named function declarations for components
Why it fails: Claude picks one randomly, or worse, alternates between the two inconsistently.
Fix: Review for contradictions periodically. Use the Self-Check Checklist.
Problem: Rules that reference files, patterns, or tools that no longer exist in the project.
Why it fails: Claude tries to follow the instruction and either fails or creates confusion. "Use the formatDate() helper from src/utils/dates.ts" -- but that file was deleted three months ago.
Fix: Review CLAUDE.md when you make significant changes to the project. Treat it like a living document.
Problem:
- Allow Claude to run `npm test` without asking
- Block Claude from using `rm -rf`
Why it fails: Permission rules belong in settings.json, not CLAUDE.md. CLAUDE.md is for instructions and context, not system configuration.
Fix: Use settings.json for permissions:
{
"permissions": {
"allow": ["Bash(npm test *)"],
"deny": ["Bash(rm -rf *)"]
}
}
Problem: Committing your personal preferences to the shared project CLAUDE.md.
- I like verbose explanations before code changes
- Skip E2E tests when I say "run tests"
- My dev server runs on port 3001
Why it fails: Your teammates now get your personal preferences in their sessions.
Fix: Personal preferences go in CLAUDE.local.md (project-specific, gitignored) or ~/.claude/CLAUDE.md (global, all projects).
Problem: Pasting your entire README, API docs, and architecture docs into CLAUDE.md.
Why it fails: Massive context consumption. Claude spends tokens processing documentation it may not need for the current task.
Fix: Use @imports to reference external docs. Keep CLAUDE.md focused on rules and conventions. Claude can read referenced files on demand when it needs them.
Problem: Running /init, committing the generated file, and never touching it again.
Why it fails: /init generates a reasonable starting point, but it cannot know your team's conventions, your project's gotchas, or your workflow preferences. The file becomes stale quickly.
Fix: Treat /init as a first draft. Customize immediately. Update continuously as you discover what Claude gets wrong.
Problem: Accidentally including sensitive information in your project CLAUDE.md.
# MyApp Config
- Database: postgresql://admin:MyP@[email protected]/db
- API key is sk_live_abc123xyz
- Admin panel credentials: user=admin pass=hunter2
Why it fails: Your project CLAUDE.md is committed to git and shared with the entire team. Credentials, API keys, and connection strings with embedded passwords have no business being there. Developers auditing their Claude Code setups have found sensitive tokens, paths, and credentials embedded in committed CLAUDE.md files. Audit yours now.
Fix: Reference where credentials live, not the credentials themselves:
# MyApp Config
- Database credentials are in .env (gitignored)
- API keys are in 1Password under 'MyApp Production'
- Local dev credentials are in .env.local (gitignored)
Memory Management: https://code.claude.com/docs/en/memory
Covers the full memory hierarchy, auto memory, CLAUDE.md imports, /memory command, and modular rules with .claude/rules/.
Settings Configuration: https://code.claude.com/docs/en/settings Covers settings.json structure, permission rules, environment variables, hooks, MCP servers, and managed enterprise settings.
Best Practices: https://code.claude.com/docs/en/best-practices General guidance on prompting, planning, verification, and effective Claude Code usage.
Explore the .claude Directory: https://code.claude.com/docs/en/claude-directory
Comprehensive reference for everything that lives in .claude/ -- CLAUDE.md, settings, skills, rules, subagents, and MCP configuration.
Debug Your Configuration: https://code.claude.com/docs/en/debug-your-config
How to diagnose configuration problems using /doctor, /context, and related commands. Covers common issues with file locations, glob patterns, settings overrides, and hook matchers.
Output Styles: https://code.claude.com/docs/en/output-styles
Built-in output styles (Proactive, Explanatory, Learning), creating custom styles with Markdown frontmatter, and configuring them via /config or settings files.
Glossary: https://code.claude.com/docs/en/glossary Definitions for Claude Code-specific terminology: auto memory, hooks, skills, compaction, checkpointing, agent teams, and more.
Agent SDK Features: https://code.claude.com/docs/en/agent-sdk/claude-code-features How the Claude Code Agent SDK inherits CLAUDE.md, rules files, skills, and hooks for automated/agentic workflows.
| Topic | Documentation URL |
|---|---|
| Memory & CLAUDE.md | https://code.claude.com/docs/en/memory |
| Settings & Permissions | https://code.claude.com/docs/en/settings |
| Best Practices | https://code.claude.com/docs/en/best-practices |
| .claude Directory Reference | https://code.claude.com/docs/en/claude-directory |
| Debug Configuration | https://code.claude.com/docs/en/debug-your-config |
| Output Styles | https://code.claude.com/docs/en/output-styles |
| Glossary | https://code.claude.com/docs/en/glossary |
| Sub-Agents | https://code.claude.com/docs/en/sub-agents |
| Hooks | https://code.claude.com/docs/en/hooks |
| MCP Servers | https://code.claude.com/docs/en/mcp |
| Common Workflows | https://code.claude.com/docs/en/common-workflows |
| Agent SDK Features | https://code.claude.com/docs/en/agent-sdk/claude-code-features |
| Full Documentation Index | https://code.claude.com/docs/llms.txt |
Managing CLAUDE.md files by hand works for small projects, but as codebases grow, keeping the main CLAUDE.md and all the .claude/rules/ files accurate, complete, and in sync becomes a real maintenance burden. The claude-md skill automates the entire process.
A Claude Code skill file that turns Claude into a CLAUDE.md configuration expert. Once installed, it activates automatically whenever you mention CLAUDE.md, .claude/rules/, project configuration for Claude, or say things like "set up Claude for this project" or "my CLAUDE.md is too long."
Every invocation runs a full 5-step pipeline:
Assess — Scans your project to understand what exists: current CLAUDE.md content, existing rule files in .claude/rules/, tech stack from your package manifest, and directory structure.
Create or Update CLAUDE.md — If no CLAUDE.md exists, builds one from scratch using a 5-question framework (What is this project? How do you run things? What are your rules? What trips you up? How do we work?). If one exists, audits it for stale references, missing commands, vague rules, and anti-patterns -- then fixes them.
Recursive Folder Discovery — Maps your entire source tree, identifies every directory with distinct coding conventions, and spawns parallel subagents to read the actual source files and write .claude/rules/ files with specific, actionable rules derived from what's really in the code. Existing rule files are checked for staleness and updated or deleted as needed.
Wire @imports — Ensures every rule file in .claude/rules/ has a corresponding @import line in the main CLAUDE.md. A rule file without an import is invisible to Claude.
Verify — Reads everything back, confirms counts match, and presents a summary table of what was created, updated, or deleted.
Install the skill file, then just tell Claude what you need:
.claude/rules/ filesThe skill handles the 6-layer memory hierarchy (managed policies, project CLAUDE.md, modular rules, global preferences, local overrides, auto-generated notes), knows when to use CLAUDE.local.md vs committed files, and follows the principle that 20 precise rules outperform 100 vague ones.
.claude/rules/ files — reads your actual source code to derive rulesTo install:
# Create the skill directory
mkdir -p ~/.claude/skills/claude-md
# Move the downloaded file
mv ~/Downloads/claude-md-skill.md ~/.claude/skills/claude-md/SKILL.md
The skill activates automatically in Claude Code sessions when relevant topics come up. No additional configuration needed.
Last Updated: 2026-05-18 Compiled from official Anthropic documentation, Boris Cherny's published workflow, and community best practices
New techniques, real-world patterns, and Claude updates — delivered as the guides evolve.