Claude Code CLI

Project
Memory
System

Sharing project knowledge with Claude without repeating yourself every session — token savings, domain knowledge, and team standards.

tool
Claude Code CLI

scope
.claude/ directory

goal
context +
token management
The Problem

Starting from zero every conversation

Project stack & build system — "This is Scala 3 + Mill, use ./mill worker.compile"
Test command — "./mill worker.it.testForked, not SBT, don't forget --no-server"
Coding conventions — "plan mode is mandatory, no code before explicit approval"
Domain knowledge — "Chargebee subscriptions use CreateWithItems, never convert the quote"
Past decisions — "don't mock the database in integration tests — we got burned last quarter"
→ Every repetition = wasted tokens + wasted time
Solution

The .claude/ directory

project-root/ ├─ CLAUDE.md ← project-wide instructions ├─ .claude/ ├─ CLAUDE.md ← loads @memory/ files ├─ MEMORY.md ← index (200 line limit) └─ memory/ ├─ project_mill_commands.md ├─ project_chargebee.md ├─ feedback_working_protocol.md └─ feedback_language.md
  • Root CLAUDE.md — project-wide instructions; committed to git, shared across the team
  • .claude/CLAUDE.md — loads memory files via @memory/ directives
  • MEMORY.md — auto-loaded index on every conversation; truncated after 200 lines
  • memory/ — individual knowledge files grouped by type prefix
Configuration

Auto-loading with @memory/

.claude/CLAUDE.md

# Project Memory

@memory/project_mill_commands.md
@memory/project_chargebee.md
@memory/project_chargebee_business_domain.md
@memory/feedback_working_protocol.md
@memory/feedback_chargebee_mcp.md
@memory/feedback_language.md

MEMORY.md (index)

# Memory Index

- [Mill Commands](memory/project_mill_commands.md)
  — build, test, format commands

- [Chargebee](memory/project_chargebee.md)
  — API, services, patterns

- [Working Protocol](memory/feedback_working_protocol.md)
  — plan mode, approval rule
Note: MEMORY.md is automatically loaded every conversation. Content beyond 200 lines is cut — keep the index concise.
Format

Memory file structure

---
name: feedback-working-protocol
description: Plan mode requirement and approval rule
metadata:
  type: feedback
---

## Plan Mode (mandatory for non-trivial tasks)

Write a plan before touching any file.
Plan must include:
1. Goal (1-2 sentences)
2. Files to modify + API/DB impact
3. Tests to add, risks, open questions

**Why:** Prevents scope creep and
  unreviewed changes.
**How to apply:** Before every
  implementation — no code without
  explicit user approval.
  • name — kebab-case slug, must be unique
  • description — determines when this memory is relevant to load
  • typeuser / feedback / project / reference
  • Why: line — the reason behind the rule; helps decide edge cases
  • How to apply: — when and where it kicks in
  • Link related memories with [[name]]
Types

4 memory types

user
User profile, expertise, preferences.
When: "10 years of Go but new to React" type of context.
Goal: Calibrate explanations to the user's actual knowledge level.
feedback
Approved / rejected approaches.
When: "Don't mock the DB", "plan mode required" — both corrections and validated unconventional choices.
Goal: Never need to give the same guidance twice.
project
Ongoing work, decisions, motivations.
When: Context not derivable from code — "auth rewrite is driven by legal compliance".
Goal: Know the real motivation when making suggestions.
reference
External system pointers.
When: "Bugs tracked in Linear 'INGEST' project", "Grafana dashboard X".
Goal: Find current information in the right place.
For feedback type: save both corrections and confirmed unconventional choices — saving only mistakes causes drift away from approaches that already worked.
Boundaries

What NOT to put in memory

Don't save
  • Code patterns and project architecture — already in the code
  • Git history, who changed what — git log is authoritative
  • Debugging fix recipes — fix is in code, context is in commit message
  • Temporary task state — belongs to the current conversation only
  • Things already documented in CLAUDE.md — duplication
  • PR lists, activity summaries — snapshots go stale fast
Save
  • Motivation/reasoning not derivable from code
  • Approaches that were confirmed or rejected
  • Domain rules — Chargebee subscription fields, etc.
  • Team preferences and unexpected constraints
  • External system locations — Linear, Grafana, Confluence
Test: If I deleted this, would a future reader be confused? No → don't save. Yes → save.
Comparison

Claude Code Memory vs. Mem0 & alternatives

Claude Code Memory Mem0 / LangMem / Custom RAG
Infrastructure Zero — plain markdown files in repo Requires vector DB, external API, or self-hosted service
Retrieval Deterministic — exact files are loaded, no surprises Fuzzy semantic search — relevant memories may not surface
Version control Git-native — reviewable, diffable, rollbackable Stored in external DB; git tracking requires extra tooling
Team visibility In the repo — everyone sees what Claude knows Per-user or per-API-key; not naturally shared with the team
Integration code None — just @memory/file.md directives Requires SDK, embeddings pipeline, query logic
Best fit Developer tooling, project context, team conventions Production AI apps needing dynamic, large-scale memory at runtime use case ↗
Token Savings

Reducing context cost

  • Keep MEMORY.md short — 200 line limit; beyond that the index is cut and useless
  • Write specific descriptions — "Chargebee API, subscription fields" beats "Chargebee info"
  • Delete stale memories — outdated or wrong memory still occupies context window
  • Split large files — 3 focused 80-line files beat 1 sprawling 500-line file
  • Save the why, not the code — business rules and constraints, not implementation details
Why it matters: @memory/ directives load on every conversation and consume context window space. Unnecessary content = unnecessary tokens = slower, more expensive responses.

Warning: A memory that names a file, function, or flag is a claim it existed when the memory was written. Before acting on it, verify it still exists.
Quick Start

Add a memory system to your project

1
Create the directory
Add .claude/memory/ at the project root. Create an empty MEMORY.md index file.
2
Add directives to .claude/CLAUDE.md
Use @memory/filename.md lines to specify which files are loaded on every conversation.
3
Write your first memory files
Start with project_ (build commands, domain rules) and feedback_ (team preferences). Frontmatter requires name, description, type.
4
Tell Claude to "remember this" or write it yourself
During a conversation, Claude can save to the appropriate type on request. Or write the file directly for full control.
5
Clean up regularly
Remove stale or wrong memories. Delete anything derivable from the code. Keep MEMORY.md under 200 lines.