home / skills / ed3dai / ed3d-plugins / writing-claude-md-files

This skill helps you craft CLAUDE.md files that capture domain intent, contracts, and freshness dates across top-level and subdirectories.

npx playbooks add skill ed3dai/ed3d-plugins --skill writing-claude-md-files

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
8.0 KB
---
name: writing-claude-md-files
description: Use when creating or updating CLAUDE.md files for projects or subdirectories - covers top-level vs domain-level organization, capturing architectural intent and contracts, and mandatory freshness dates
user-invocable: false
---

# Writing CLAUDE.md Files

**REQUIRED BACKGROUND:** Read ed3d-extending-claude:writing-claude-directives for foundational guidance on token efficiency, compliance techniques, and directive structure.

## Core Principle

CLAUDE.md files bridge Claude's statelessness. They preserve context so humans don't re-explain architectural intent every session.

**Key distinction:**
- **Top-level**: HOW to work in this codebase (commands, conventions)
- **Subdirectory**: WHY this piece exists and what it PROMISES (contracts, intent)

## File Hierarchy

Claude automatically reads CLAUDE.md files from current directory up to root:

```
project/
├── CLAUDE.md                    # Project-wide: tech stack, commands, conventions
└── src/
    └── domains/
        ├── auth/
        │   ├── CLAUDE.md        # Auth domain: purpose, contracts, invariants
        │   └── oauth2/
        │       └── CLAUDE.md    # OAuth2 subdomain (rare, only when needed)
        └── billing/
            └── CLAUDE.md        # Billing domain: purpose, contracts, invariants
```

**Depth guideline:** Typically one level (domain). Occasionally two (subdomain like `auth/oauth2`). Rarely more.

## Top-Level CLAUDE.md

Focuses on project-wide WHAT and HOW.

### What to Include

| Section | Purpose |
|---------|---------|
| Tech Stack | Framework, language, key dependencies |
| Commands | Build, test, run commands |
| Project Structure | Directory overview with purposes |
| Conventions | Naming, patterns used project-wide |
| Boundaries | What Claude can/cannot edit |

### Template

```markdown
# [Project Name]

Last verified: [DATE - use `date +%Y-%m-%d`]

## Tech Stack
- Language: TypeScript 5.x
- Framework: Next.js 14
- Database: PostgreSQL
- Testing: Vitest

## Commands
- `npm run dev` - Start dev server
- `npm run test` - Run tests
- `npm run build` - Production build

## Project Structure
- `src/domains/` - Domain modules (auth, billing, etc.)
- `src/shared/` - Cross-cutting utilities
- `src/infrastructure/` - External adapters (DB, APIs)

## Conventions
- Functional Core / Imperative Shell pattern
- Domain modules are self-contained
- See domain CLAUDE.md files for domain-specific guidance

## Boundaries
- Safe to edit: `src/`
- Never touch: `migrations/` (immutable), `*.lock` files
```

### What NOT to Include

- Code style rules (use linters)
- Exhaustive command lists (reference package.json)
- Content that belongs in domain-level files
- Sensitive information (keys, credentials)

## Subdirectory CLAUDE.md (Domain-Level)

Focuses on WHY and CONTRACTS. The code shows WHAT; these files explain intent.

### What to Include

| Section | Purpose |
|---------|---------|
| Purpose | WHY this domain exists (not what it does) |
| Contracts | What this domain PROMISES to others |
| Dependencies | What it uses, what uses it, boundaries |
| Key Decisions | ADR-lite: decisions and rationale |
| Invariants | Things that must ALWAYS be true |
| Gotchas | Non-obvious traps |

### Template

```markdown
# [Domain Name]

Last verified: [DATE - use `date +%Y-%m-%d`]

## Purpose
[1-2 sentences: WHY this domain exists, what problem it solves]

## Contracts
- **Exposes**: [public interfaces - what callers can use]
- **Guarantees**: [promises this domain keeps]
- **Expects**: [what callers must provide]

## Dependencies
- **Uses**: [domains/services this depends on]
- **Used by**: [what depends on this domain]
- **Boundary**: [what should NOT be imported here]

## Key Decisions
- [Decision]: [Rationale]

## Invariants
- [Thing that must always be true]

## Key Files
- `index.ts` - Public exports
- `types.ts` - Domain types
- `service.ts` - Main service implementation

## Gotchas
- [Non-obvious thing that will bite you]
```

### Example: Auth Domain

```markdown
# Auth Domain

Last verified: 2025-12-17

## Purpose
Ensures user identity is verified exactly once at the system edge.
All downstream services trust the auth token without re-validating.

## Contracts
- **Exposes**: `validateToken(token) → User | null`, `createSession(credentials) → Token`
- **Guarantees**: Tokens expire after 24h. User objects always include roles.
- **Expects**: Valid JWT format. Database connection available.

## Dependencies
- **Uses**: Database (users table), Redis (session cache)
- **Used by**: All API routes, billing domain (user identity only)
- **Boundary**: Do NOT import from billing, notifications, or other domains

## Key Decisions
- JWT over session cookies: Stateless auth for horizontal scaling
- bcrypt cost 12: Legacy decision, migration to argon2 tracked in ADR-007

## Invariants
- Every user has exactly one primary email
- Deleted users are soft-deleted (is_deleted), never hard deleted
- User IDs are UUIDs, never sequential

## Key Files
- `service.ts` - AuthService implementation
- `tokens.ts` - JWT creation/validation
- `types.ts` - User, Token, Session types

## Gotchas
- Token validation returns null on invalid (doesn't throw)
- Never return raw password hashes in User objects
```

## Freshness Dates: MANDATORY

Every CLAUDE.md MUST include a "Last verified" date.

**CRITICAL:** Use Bash to get the actual date. Do NOT hallucinate dates.

```bash
date +%Y-%m-%d
```

Include in file:
```markdown
Last verified: 2025-12-17
```

**Why mandatory:** Stale CLAUDE.md files are worse than none. The date signals when contracts were last confirmed accurate.

## Referencing Files

You can reference key files in CLAUDE.md:

```markdown
## Key Files
- `index.ts` - Public exports
- `service.ts` - Main implementation
```

**Do NOT use @ syntax** (e.g., `@./service.ts`). This force-loads files into context, burning tokens. Just name the files; Claude can read them when needed.

## Heuristics: Top-Level vs Subdirectory

| Question | Top-level | Subdirectory |
|----------|-----------|--------------|
| Applies project-wide? | ✓ | |
| New engineer needs on day 1? | ✓ | |
| About commands/conventions? | ✓ | |
| About WHY a component exists? | | ✓ |
| About contracts between parts? | | ✓ |
| Changes when the domain changes? | | ✓ |

**Rule of thumb:**
- Top-level = "How to work here"
- Subdirectory = "Why this exists and what it promises"

## When to Create Subdirectory CLAUDE.md

Create when:
- Domain has non-obvious contracts with other parts
- Architectural decisions affect how code should evolve
- Invariants exist that aren't obvious from code
- New sessions consistently need the same context re-explained

Don't create for:
- Trivial utility folders
- Implementation details that change frequently
- Content better captured in code comments

## Updating CLAUDE.md Files

When updating any CLAUDE.md:

1. **Update the freshness date** using Bash `date +%Y-%m-%d`
2. **Verify contracts still hold** - read the code, check invariants
3. **Remove stale content** - better short and accurate than long and wrong
4. **Keep token-efficient** - <300 lines top-level, <100 lines subdirectory

## Common Mistakes

| Mistake | Fix |
|---------|-----|
| Describing WHAT code does | Focus on WHY it exists, contracts it keeps |
| Missing freshness date | Always include, always use Bash for real date |
| Using @ to reference files | Just name files, let Claude read on demand |
| Too much detail | Subdirectory files should be <100 lines |
| Duplicating parent content | Subdirectory inherits parent; don't repeat |
| Stale contracts | Update when domain changes; verify dates |

## Checklist

**Top-level:**
- [ ] Tech stack listed
- [ ] Key commands documented
- [ ] Project structure overview
- [ ] Freshness date (from `date +%Y-%m-%d`)

**Subdirectory:**
- [ ] Purpose explains WHY (not what)
- [ ] Contracts: exposes, guarantees, expects
- [ ] Dependencies and boundaries clear
- [ ] Key decisions with rationale
- [ ] Invariants documented
- [ ] Freshness date (from `date +%Y-%m-%d`)
- [ ] Under 100 lines

Overview

This skill helps create and maintain CLAUDE.md files for projects and subdirectories. It codifies where to put project-wide HOW/commands versus domain-level WHY/contracts, and enforces mandatory freshness dates so Claude sessions have reliable context.

How this skill works

The skill provides templates and guidelines for top-level and domain-level CLAUDE.md files, including required sections, line-length heuristics, and file hierarchy recommendations. It enforces a mandatory "Last verified" date (obtained via `date +%Y-%m-%d`) and checks that domain files focus on intent, contracts, invariants, and boundaries rather than implementation details.

When to use it

  • When adding or updating a project-wide CLAUDE.md to capture tech stack, commands, and conventions.
  • When a domain/subdirectory has non-obvious contracts, invariants, or architectural decisions to communicate.
  • When onboarding new engineers who need persistent context without re-explaining intent each session.
  • When a CLAUDE.md is stale and needs verification of promises and guarantees.
  • When you want to limit Claude edits to safe areas by declaring boundaries and edit rules.

Best practices

  • Top-level files: focus on HOW (commands, tech stack, project structure), keep under ~300 lines.
  • Domain files: focus on WHY and CONTRACTS (exposes, guarantees, expects), keep under ~100 lines.
  • Always include a real freshness date using bash: `date +%Y-%m-%d` and update it when contracts change.
  • Name key files rather than using @ syntax; avoid force-loading files into context.
  • Remove stale content; prefer short, accurate guidance over exhaustive detail.

Example use cases

  • Create a root CLAUDE.md that lists build/test commands, tech stack, and safe-to-edit paths.
  • Add a domain CLAUDE.md for auth that documents token guarantees, invariants, and boundaries.
  • Update a billing domain CLAUDE.md after an API contract changes and bump the Last verified date.
  • Decide not to create CLAUDE.md for small utility folders to avoid unnecessary maintenance.

FAQ

What must every CLAUDE.md include?

Every CLAUDE.md must include a "Last verified" date produced by `date +%Y-%m-%d`.

Should I list every command and configuration?

No. Top-level files should cover the essential commands; reference package.json or configs for exhaustive lists.