Skip to content

Memory System — Real-World Examples

Memory is how Claude retains knowledge across sessions. Without it, every session starts from zero. With it, Claude knows your project’s quirks, your preferences, and what it has already learned.


SystemWritten byRead byLocation
CLAUDE.mdYouClaude (every session)./CLAUDE.md or ./.claude/CLAUDE.md
Auto MemoryClaudeClaude (every session)~/.claude/projects/<hash>/memory/

Think of CLAUDE.md as the onboarding doc and auto memory as Claude’s personal notes.


CLAUDE.md:

# Payments API
## What this is
REST API for processing payments. Node 20 + TypeScript + Express + PostgreSQL.
Deployed to AWS Lambda via Serverless Framework.
## Commands
- Install: `npm install`
- Dev: `npm run dev` (starts on port 3001)
- Test: `npm test` (Vitest)
- Test (single file): `npx vitest run tests/services/payment.test.ts`
- Lint: `npm run lint` (ESLint + Prettier)
- Type check: `npx tsc --noEmit`
- Build: `npm run build`
- Deploy staging: `npm run deploy:staging`
- Deploy prod: `npm run deploy:prod`
## Hard rules
- NEVER commit directly to main
- NEVER edit files in prisma/migrations/ (they are immutable)
- NEVER commit .env files
- ALWAYS run lint + test before committing
- ALWAYS use pnpm, not npm
## Architecture
- `src/handlers/` — Lambda/Express route handlers (thin layer, no business logic)
- `src/services/` — All business logic
- `src/repositories/` — All database access (Prisma)
- `src/validators/` — Zod schemas for all input
- `src/middleware/` — Auth, rate limiting, logging
- `src/types/` — Shared TypeScript types
- `prisma/` — Schema and migrations
- `tests/` — Mirrors src/ structure
## Patterns
- Error handling: throw `new AppError('message', 400)` — see src/types/errors.ts
- All DB access goes through repositories, never direct Prisma in services
- Validate all user input with Zod before any service call
- Use `asyncHandler()` wrapper for all async route handlers
## Environment
- Local DB: postgresql://localhost:5432/payments_dev
- Test DB: postgresql://localhost:5432/payments_test (set in .env.test)
- Redis (local): redis://localhost:6379
## Common pitfalls
- Tests use a separate DB — check .env.test before debugging DB issues
- Port 3001 conflicts: `lsof -i :3001 | awk 'NR>1{print $2}' | xargs kill`
- Prisma client out of date: run `npx prisma generate`
- Migration pending: run `npx prisma migrate dev`

CLAUDE.md:

# Dashboard App
## What this is
Next.js 14 dashboard. App Router, TypeScript, Tailwind CSS, shadcn/ui components.
## Commands
- Dev: `npm run dev` (port 3000)
- Build: `npm run build`
- Test: `npm test` (Jest + React Testing Library)
- Test e2e: `npm run test:e2e` (Playwright)
- Lint: `npm run lint`
- Storybook: `npm run storybook`
## Rules
- Use App Router, not Pages Router
- All components in `src/components/` must have a Storybook story
- Use `cn()` utility for conditional classNames (from src/lib/utils.ts)
- Prefer shadcn/ui components over custom ones
- Fetch data in Server Components; interactive state in Client Components
- Never use `useEffect` for data fetching — use Server Components or SWR
## Directory structure
- `src/app/` — Next.js App Router pages and layouts
- `src/components/ui/` — shadcn/ui components (DO NOT modify)
- `src/components/` — App-specific components
- `src/hooks/` — Custom React hooks
- `src/lib/` — Utilities and helpers
- `src/server/` — Server-only code (DB, auth)
## Component patterns
- Client components: add 'use client' at top
- Server components: no directive needed (default)
- Data fetching: async function directly in Server Component
- Forms: use react-hook-form + zodResolver
## Styling
- Use Tailwind classes only — no inline styles, no CSS modules
- Dark mode: use `dark:` prefix (already configured)
- Responsive: mobile-first (`sm:`, `md:`, `lg:` breakpoints)

CLAUDE.md:

# ETL Pipeline
## What this is
Python data pipeline. Extracts from Salesforce, transforms, loads to BigQuery.
Runs on Cloud Run via Cloud Scheduler.
## Commands
- Setup: `pip install -e ".[dev]"`
- Run: `python -m pipeline.main`
- Test: `pytest tests/ -v`
- Type check: `mypy src/`
- Lint: `ruff check src/ && black --check src/`
- Format: `black src/ && ruff --fix src/`
## Rules
- All BigQuery writes must be idempotent (use INSERT ... ON CONFLICT or MERGE)
- Log every row count at each pipeline stage using the logger in src/utils/logging.py
- Never hardcode credentials — use Secret Manager via src/utils/secrets.py
- All transformations must have unit tests with sample data
## Project structure
- `src/pipeline/` — Main pipeline logic
- `src/extractors/` — Data source connectors (Salesforce, HubSpot, etc.)
- `src/transformers/` — Data transformation functions
- `src/loaders/` — BigQuery and GCS writers
- `src/utils/` — Shared utilities
- `tests/` — Unit and integration tests
- `fixtures/` — Sample data for tests
## Environment variables
- GOOGLE_CLOUD_PROJECT — GCP project ID
- SALESFORCE_INSTANCE — e.g. https://mycompany.salesforce.com
- Credentials: loaded from Secret Manager (see src/utils/secrets.py)

Instead of duplicating content, import from other files:

# My Project CLAUDE.md
## Architecture
@docs/ARCHITECTURE.md
## API Reference
@docs/api-reference.md
## Deployment Guide
@docs/deployment.md

docs/ARCHITECTURE.md is included verbatim at session start. If it changes, Claude sees the latest version.

Import home directory files:

## My Personal Preferences
@~/.claude/my-style.md

~/.claude/my-style.md:

# My Coding Preferences
- Always explain your reasoning before making large changes
- Prefer explicit code over clever abstractions
- When naming variables, choose clarity over brevity
- Ask before refactoring more than 3 files at once

Part 3: Path-Scoped Rules — Real Examples

Section titled “Part 3: Path-Scoped Rules — Real Examples”

These inject context automatically when Claude edits matching files.

.claude/rules/api.md:

---
paths:
- "src/handlers/**"
- "src/routes/**"
---
When working on API handlers:
Required for every endpoint:
1. Input validated with Zod schema from src/validators/
2. Wrapped with asyncHandler() — never use try/catch in handlers
3. Calls service layer only (no Prisma, no direct DB)
4. Returns: res.json(formatResponse(data)) or next(error)
Auth: Protected routes must call requireAuth() middleware
Response shape:
- Success: { data: ..., meta: { timestamp } }
- Error: { error: { code, message } }
Example:
export const createUser = asyncHandler(async (req, res) => {
const data = UserSchema.parse(req.body)
const user = await userService.create(data)
res.status(201).json(formatResponse(user))
})

.claude/rules/tests.md:

---
paths:
- "tests/**"
- "**/*.test.ts"
- "**/*.spec.ts"
---
Test conventions:
- Framework: Vitest (not Jest)
- Mocking: vi.mock() and vi.spyOn()
- DB: use testDb from tests/helpers/db.ts (auto-resets between tests)
- External APIs: always mock (Stripe, SendGrid, etc.)
- Structure: describe("ServiceName", () => { describe("method", () => { it("...") }) })
NEVER:
- Mock internal services (only mock external dependencies)
- Use expect.anything() when you can be specific
- Skip assertions with //
- Test implementation details
Pattern for service tests:
describe("PaymentService", () => {
beforeEach(async () => { await testDb.reset() })
describe("charge", () => {
it("creates a charge record in the database", async () => {
const result = await service.charge({ amount: 1000, currency: "usd" })
const record = await testDb.payment.findUnique({ where: { id: result.id } })
expect(record?.amount).toBe(1000)
})
})
})

After debugging a tricky issue, Claude might write:

~/.claude/projects/<hash>/memory/build-issues.md:

---
name: build-issues
description: Known build problems and fixes for this project
metadata:
type: project
---
**npm test fails with "Cannot find module"**
Fix: Run `npm install` first — the test runner doesn't auto-install.
Why: Vitest doesn't run a pre-install step.
How to apply: Suggest `npm install` whenever module-not-found errors appear in tests.
**Port 3001 is already in use**
Fix: `lsof -i :3001 | awk 'NR>1{print $2}' | xargs kill`
Why: Previous dev server didn't shut down cleanly.
How to apply: Run this when `npm run dev` fails with EADDRINUSE.
**Prisma client out of sync after git pull**
Fix: `npx prisma generate`
Why: schema.prisma changed but generated client wasn't regenerated.
How to apply: Suggest this whenever Prisma type errors appear after a pull.

Next session, Claude reads this and proactively suggests these fixes before you even ask.


Terminal window
/memory

Shows:

  • Path to memory directory
  • List of memory files
  • Options to edit or disable

Edit directly:

Terminal window
notepad ~/.claude/projects/<hash>/memory/build-issues.md

Delete stale memories:

Terminal window
# Example: remove outdated dependency issue
del "~\.claude\projects\abc123\memory\old-issue.md"

Claude always loads MEMORY.md first. It’s an index of all other memory files:

~/.claude/projects/<hash>/memory/MEMORY.md:

- [build-issues.md](build-issues.md) — Known build failures and fixes
- [dev-preferences.md](dev-preferences.md) — User's coding style and workflow
- [architecture-notes.md](architecture-notes.md) — Non-obvious architectural decisions
- [project-context.md](project-context.md) — Current sprint goals and work in progress

Claude loads this, then reads specific files when relevant. Keep MEMORY.md short (under 200 lines) — everything after that gets truncated.

  • Trick: “100-line budget — every CLAUDE.md line costs tokens every session.”
  • Do: review a real CLAUDE.md together and cut it to essentials.
  • They’ll trip on: pasting documentation in — link it or make it a skill instead.

Learning path:17-memory.md · Index · ➡ 19-project-structure.md

Written by Fenil Patel