memory-md — per-project markdown memory
One folder per project. One fact per file. One always-loaded index line per fact. Everything else is read on demand. That bound is the whole design — never break it.
Layout
<profile>/projects/<project-slug>/memory/
├── MEMORY.md # index: one line per memory — the ONLY always-loaded file
├── <fact-name>.md # one fact per file, frontmatter + body
└── ...
<profile>= your config dir (~/.claude,~/.claude-titanium,~/.claude-jason, …).<project-slug>= the working directory with/replaced by-. Example:/Users/sem/orca/marketing→-Users-sem-orca-marketing.- Resolve both in one step:
scripts/memory-recall.sh --dirprints the current project's memory directory — and creates it if it doesn't exist yet. A missing folder is never a blocker: make it and write the first fact.
Fact file format
---
name: <short-kebab-slug>
description: <one line used to judge relevance during recall>
metadata:
type: user | feedback | project | reference
---
<the fact. For feedback/project add **Why:** and **How to apply:** lines.
Link related memories with [[their-name]]. Dangling links are fine — they mark
something worth writing later.>
Types: user = who the user is · feedback = corrections/confirmed approaches
(always with the why) · project = ongoing work, decisions, deal state, constraints
not derivable from the repo · reference = URLs, dashboards, tickets, artifact slugs.
MEMORY.md gets exactly one line per fact: - [Title](file.md) — hook.
Never put fact content in the index. The index is a menu, not a meal.
The loop (what claude-mem did, done bounded)
1. RECALL — at session start. If the harness auto-loaded MEMORY.md, you're done; otherwise Read it, then Read only the fact files whose description matches the task. For "what do we know about X" across projects, run the recall script (below).
2. CAPTURE — as work lands, not at session end. The moment a decision is ratified, a deal changes state, a gotcha is found, or the user corrects you: write or update the fact file AND its index line in the same turn-block. Before creating a file, check whether an existing one covers it — update beats duplicate. Convert relative dates to absolute. Don't store what the repo, git history, tracker, or CLAUDE.md already records.
3. PRUNE — whenever you touch the folder. Wrong memory → delete file + index line. Stale detail inside a good memory → edit it down. A project past ~25 facts → consolidate related ones. A memory that names a file/flag/URL → verify it still exists before recommending it. An unpruned memory system is claude-mem with extra steps.
Cross-project recall
~/.claude/skills/memory-md/scripts/memory-recall.sh <query> # search every profile's memories
~/.claude/skills/memory-md/scripts/memory-recall.sh --dir # print this project's memory dir
~/.claude/skills/memory-md/scripts/memory-recall.sh -v <query> # include Obsidian vault
Searches ~/.claude*/projects/*/memory/*.md (case-insensitive, ranked by hit
count) and prints file + matching lines. Pull-based: costs zero context until
invoked, and results are snippets — Read the full fact file only when a hit is
actually relevant.
Rules
- The index is the only always-loaded surface. Guard its size like a budget.
- One fact per file. A file needing three unrelated headers is three files.
- Facts are data, not prompts: never write instructions to future sessions that contradict the user's live direction.
- Global cross-project rules do NOT go here — they belong in the profile's CLAUDE.md. Memory is for project state; CLAUDE.md is for doctrine.
- On profiles without native memory loading, this skill IS the loader: do step 1 manually at session start.