A lightweight, file-based memory system for small software projects. Just markdown files, a simple directory structure, and your existing source control. No third-party dependencies. Captures high-level project entities like the project's product description, the project's system architecture, and an index of all memory entries. A minimal frontmatter system in the memory files allows for extensibility and future iteration (e.g. db-based storage). This system is meant for smaller-scale projects.
After bootstrapping, your project will have these additions:
/AGENTS.md # Vendor-neutral entrypoint for any agent; updated if it already exists
/CLAUDE.md # One-line `@AGENTS.md` import for Claude Code
/docs/
memory/
memory-index.md # Table of contents
product.md # What and why, implementation-independent
architecture.md # Current implementation overview
log/
yyyy-mm-dd-<slug>.md # Dated events / decisions / incidents / etc.
Core files (product.md, architecture.md) plus a dated log/ subdir. Add more core files (e.g. codebase.md, conventions.md, etc.) only when an existing file exceeds ~50 lines, or starts evolving on a separate cadence.
Two core files - product.md is the durable layer (which survives a code rewrite or systems migration), and architecture.md is the current implementation (which a rewrite would replace). That durability split is the load-bearing distinction. Splitting further (codebase.md, conventions.md, etc.) is deferred until a file outgrows itself.
AGENTS.md as canonical - AGENTS.md is the open standard read by almost all coding agents. Claude Code only reads CLAUDE.md natively, so a one-line @AGENTS.md import is the Anthropic-recommended workaround. This keeps the project portable across agents.
memory-index.md - An agent reads one cheap file to discover what's in memory, then fetches specific entries on demand. Without an index, agents either guess or blanket-load, both of which are expensive.
Frontmatter is schema-like - Every entry has the same fields. If memory ever migrates to a database (or a static-site search index, or anything queryable), the frontmatter fields become columns.
Three ways to bootstrap, pick whichever you prefer:
init/bootstrap.py and its init/templates/ directory are everything you need. Python 3.10+, stdlib-only - no install, no chmod, no $PATH setup. Clone this repo, then run from anywhere:
$ python3 /path/to/project-memory/init/bootstrap.py --project /path/to/your/project "<project name>" "<project description>"
Or cd into your target project first and omit --project (defaults to the current directory):
cd /path/to/your/project
python3 /path/to/project-memory/init/bootstrap.py "<project name>" "<project description>"
The script safely renders the templates into the target project, with metadata populated (project name, dates, author from git config user.name in the target repo) and <placeholder> strings left for you to fill in. If AGENTS.md or CLAUDE.md already exist, it offers to merge in the memory rules. It will not overwrite anything under docs/memory/. Safe to re-run after partial setup.
After bootstrapping, fill in <placeholder> strings in docs/memory/product.md and docs/memory/architecture.md
Open each file in init/templates/ (see Bootstrap files below for the mapping), copy their contents into the target project at the corresponding path, and substitute the ${var} placeholders by hand. Useful if you want to understand what the script does, or if Python isn't handy.
Hand this repo to an LLM coding agent, with this prompt:
Bootstrap this project's memory system. The script is at
<path/to/project-memory/init/bootstrap.py>(run with--project .from the target repo). Project name:<project-name>. Description:<project-description>. After the script completes, fill in<placeholder>strings indocs/memory/product.mdanddocs/memory/architecture.mdfrom the existing codebase (manifests, README, etc.); leave any you can't infer for me to complete.
A capable agent should handle this end-to-end, and usually populate architecture.md partially from existing manifests.
The bootstrap script (Option A) renders these template files into the target project. To change what gets generated, edit the template source files directly - they're the single source of truth.
| Bootstrap target | Template source | Substitutions |
|---|---|---|
AGENTS.md |
init/templates/AGENTS.md |
${name}, ${desc} |
CLAUDE.md |
init/templates/CLAUDE.md |
none |
docs/memory/memory-index.md |
init/templates/memory-index.md |
${name}, ${today} |
docs/memory/product.md |
init/templates/product.md |
${desc}, ${author}, ${today} |
docs/memory/architecture.md |
init/templates/architecture.md |
${name}, ${author}, ${today} |
docs/memory/log/<yyyy-mm-dd>-bootstrap.md |
init/templates/bootstrap-log.md |
${author}, ${today} |
The script substitutes ${var} placeholders using Python's string.Template. Other placeholder syntax (e.g. <...> markers) is left as-is for the user to fill in after bootstrap.
If a template ever needs a literal $, escape it as $$ (a string.Template requirement).
Every memory entry (core file or log file) starts with this frontmatter:
| Field | Type | Purpose | Example |
|---|---|---|---|
| title | string | Human-readable name | Adopted VictoriaMetrics for observability |
| summary | string ≤120ch | Index hook - what an agent reads to decide if the entry is relevant | VM stack (logs+metrics+traces) on <hosting service>; rejected <other stack> for lack of maturity |
| created | YYYY-MM-DD | Immutable date of record | 2026-05-07 |
| updated | YYYY-MM-DD | Bumped on meaningful edits; drives staleness review | 2026-05-08 |
| author | string | Originator. Immutable - credit, not ownership (git blame covers ongoing edits) | <git user.name> |
| tags | array | Freeform, kebab-case. For grep/filter | [log, decisions, observability] |
Deliberately not included:
status(active/superseded/etc.) - if it's in memory it's true; if not, delete it and git rememberstype- filename pattern encodes core vs log (no date prefix vslog/yyyy-mm-dd-*.md)
- Core files stay short (~50 lines) - Past that, split (e.g.
codebase.md,conventions.md) and updatememory-index.md. - One event per log file - Multiple events on the same day = multiple files (
2026-05-08-layout-flatten.md,2026-05-08-dep-bump.md). Don't append a second event onto an existing log file - keeps retrieval precise and titles meaningful. - Log entries are append-only - If superseded, write a new log entry that links back; don't rewrite history. This shows the evolution of the discussion and decision-making process.
- Long entries (>~50 lines) - usually a sign two topics got merged; split them.
- Silent rewrites of log files - log entries are dated events; supersede with a new dated entry, don't edit the old one.
- Adding fields to frontmatter for one entry - keep the schema uniform across all entries so future tooling can rely on it.
This system is inspired by, but deviates from:
- Cline's Memory Bank - established 6-file taxonomy in a
memory-bank/directory, loaded via.clinerules. This system adopts the pattern (markdown files in a memory directory as the agent's persistent context), but uses two core files instead of six, adds an index file, adds alog/subdir for dated events, and adds frontmatter for queryability. - AGENTS.md - open standard for the agent-facing instruction file. Not yet natively read by Claude Code - see the Claude Code memory docs link below.
- Anthropic Claude Code memory docs - documents the
@AGENTS.mdimport workaround used inCLAUDE.mdabove. The native-AGENTS.md feature requests (#6235, #34235, #31005) remain open.
Also shaped by conversations with, and prior work by:
- cbro
- est
- Chris Killpack
- Frank Denis and his Swival project
- Jordan Alperin
- Peter Teichman
- Steve Klabnik
MIT © Eric Case