Persistent memory structure for AI coding agents. Battle-tested patterns for maintaining context across sessions using plain text files.
No vector databases. No RAG pipelines. No embeddings. Just structured text files that your agent reads at the start of every session.
AI coding agents (Claude Code, Cursor, Windsurf, etc.) lose all context between sessions. The typical fix is complex memory infrastructure — embeddings, vector stores, retrieval pipelines. But for most use cases, a well-organized set of text files works better:
- Zero dependencies — plain markdown files, nothing to install or maintain
- Inspectable — you can read and edit your agent's memory directly
- Version controlled — memory changes show up in git diffs
- Portable — works with any agent that can read files
- Fast — no retrieval latency, no embedding costs
The key insight: how you organize the files matters more than the technology. A single running log gets unwieldy fast. Separate files by topic with a short index linking them — that scales.
# Option 1: Use the setup script
curl -fsSL https://raw.githubusercontent.com/echo-lumen/agent-memory-toolkit/main/setup.sh | bash
# Option 2: Clone and run locally
git clone https://github.com/echo-lumen/agent-memory-toolkit.git
cd agent-memory-toolkit
./setup.shThe setup script creates the memory structure in your project's .claude/ directory (or wherever you point it).
.claude/
CLAUDE.md ← project instructions (always loaded by Claude Code)
memory/
MEMORY.md ← index file — always loaded, links to topic files
patterns.md ← recurring patterns and lessons learned
architecture.md ← key architectural decisions
debugging.md ← solutions to problems you've solved
workflows.md ← how-tos and processes
... ← add topic files as needed
This is the only file that's always in context. Keep it under 200 lines. Its job is to:
- Link to topic files — so the agent knows where to find details
- Store high-level context — project structure, key decisions, user preferences
- Track what's current — active work, recent changes, things to remember
Think of it as a table of contents, not a diary.
Each topic file covers one domain. When the agent needs details about debugging patterns, it reads debugging.md. When it needs architecture context, it reads architecture.md. The agent decides what to read based on the task.
Rules for topic files:
- Organize by topic, not by date
- Update in place — don't append, revise
- Delete stale information — wrong memories are worse than no memories
- One concern per file — if a file covers two unrelated topics, split it
Save:
- Stable patterns confirmed across multiple sessions
- Key architectural decisions and their rationale
- File paths and project structure that won't change often
- User preferences for workflow and communication
- Solutions to problems that took real effort to solve
- Conventions and naming patterns used in the codebase
Don't save:
- Session-specific context (current task, in-progress work)
- Information you haven't verified against the codebase
- Anything that duplicates existing documentation
- Speculative conclusions from reading a single file
- Temporary state that will be stale next session
Add this to your project's CLAUDE.md to tell the agent about its memory:
# Memory
You have persistent memory at `.claude/memory/`. Read `MEMORY.md` at the start of every session.
## How to use memory:
- Consult memory files before starting work — they contain patterns and decisions from previous sessions
- Update memory when you learn something stable and reusable
- Organize by topic, not chronologically
- Keep MEMORY.md under 200 lines — push details into topic files
- Delete or update memories that turn out to be wrongA single MEMORY.md works at first. But after 5-10 sessions, it's 500+ lines and the agent is spending tokens reading context about debugging when you asked it to refactor a component. Topic files let the agent load only what's relevant.
Databases require infrastructure, have failure modes, and aren't human-readable. When your agent saves something wrong, you want to open a file and fix it — not write a query. Plain text means grep, git diff, and your editor all work.
For a project's working memory (dozens to low hundreds of facts), semantic search adds complexity without value. The agent can scan a 200-line index file in milliseconds. RAG shines at thousands of documents — not at "remember that we use PostgreSQL and the deploy script is at scripts/deploy.sh."
Append-only logs grow without bound and accumulate contradictions. When you discover a pattern was wrong, you want to fix the record — not add a correction that the agent might read after the original mistake. Memory should reflect current understanding, not history.
# Project Memory
## Architecture
- Next.js 14 app router, TypeScript, Tailwind
- DB: PostgreSQL via Prisma — schema at `prisma/schema.prisma`
- Auth: NextAuth with GitHub OAuth
- Deploy: Vercel, auto-deploy from `main`
- Details: `memory/architecture.md`
## Patterns & Conventions
- API routes return `{ data, error }` shape
- Components use named exports, not default
- Tests: Vitest + Testing Library, run with `npm test`
- Details: `memory/patterns.md`
## Debugging Notes
- The Prisma connection pool exhaustion issue — solved with `connection_limit=5`
- CSS grid layout breaks in Safari < 16 — use flexbox fallback
- Details: `memory/debugging.md`
## User Preferences
- Prefers concise code over verbose — no unnecessary comments
- Wants tests for new features but not for refactors
- Uses `bun` not `npm`# Patterns & Conventions
## API Routes
All API routes follow this shape:
- Success: `{ data: T }`
- Error: `{ error: string }`, status 4xx/5xx
- Validation: use zod schemas, parse in the route handler
- Auth: check session at the top, return 401 early
## Components
- Named exports: `export function Button()` not `export default function Button()`
- Props interfaces: `interface ButtonProps` defined above the component
- Colocate styles: component-specific Tailwind in the component file
- No barrel exports — import directly from the component file
## Git
- Commit messages: imperative mood, no period, under 72 chars
- Branch naming: `feature/short-description` or `fix/short-description`
- Always rebase on main before mergingThe structure works with any agent that can read files:
- Cursor — put memory files in
.cursor/memory/and reference them in.cursorrules - Windsurf — use
.windsurfrulesto point to the memory directory - Aider — reference memory files in
.aider.conf.ymlconventions - Custom agents — load MEMORY.md into the system prompt, topic files on demand
MIT