Cookbooks
CLAUDE.md Migration
A 300-line CLAUDE.md loads into every session whether or not it's relevant. Migrate the knowledge sections into Neuroloom and inject only what each session needs — shrinking context overhead while improving relevance.
Problem
CLAUDE.md starts as a short conventions file and grows into a documentation dumping ground. Database patterns, architecture decisions, API conventions, historical context, runbook fragments — it all accumulates. By the time the file hits 300 lines, Claude Code loads 20,000+ tokens of context every session, most of it irrelevant to the current task. Trim it, and the relevant knowledge disappears too.
Persona
Kenji maintains a FastAPI monorepo with a 340-line CLAUDE.md. The file contains coding standards, architecture decisions, environment setup instructions, historical context about migrations, and notes about external API quirks. Every session loads all of it. He wants Claude Code to know what it needs to know for each session — without loading everything every time.
Prerequisites
- Neuroloom plugin installed and configured (see Quickstart)
CLAUDE.mdfile at least 100 lines (shorter files don't benefit from migration)- Environment variables:
export MEMORIES_API_TOKEN="nl_your_api_key_here" export MEMORIES_WORKSPACE_ID="ws_your_workspace_id_here"
Step 1: Audit CLAUDE.md — map categories to memory types
Read through CLAUDE.md and categorize each section. This determines which memory type to use for each entry.
Typical mapping for a monorepo CLAUDE.md:
| Section type | Memory type | Example |
|---|---|---|
| Architecture decisions | decision | "Why we use StrEnum over Postgres ENUM" |
| Coding patterns | pattern | "Always use selectinload() for relationship loading" |
| Conventions | convention | "Every DB query must filter by workspace_id" |
| Dependency quirks | decision + dependency tag | "httpx 0.27.x doesn't retry on 429 by default" |
| Environment setup | general + configuration tag | "Dev environment requires Docker Compose v2" |
| Bug fixes / gotchas | incident | "pgvector rollback doesn't undo HNSW index — use DELETE" |
| Historical context | architecture | "We moved from sync to async SQLAlchemy in D7" |
| Learning / external API | discovery | "Railway adds a trailing slash that strips auth headers on redirect" |
Create a migration inventory before writing any code. Mark each section with its target memory type and estimated importance:
[ ] Technology Stack section → architecture (importance: 0.7)
[ ] API Case Transformation → pattern (importance: 0.9)
[ ] pgvector Conventions → convention (importance: 0.95)
[ ] ARQ Job Conventions → pattern (importance: 0.88)
[ ] Coding Standards: Python → convention (importance: 0.85)
[ ] Coding Standards: TypeScript → convention (importance: 0.80)
[ ] Trailing slash redirect bug → incident (importance: 0.92)Step 2: Store each category as typed memories
Migrate one category at a time. Start with the highest-importance sections — the ones that cause mistakes when unknown.
Use memory_store:
- title: "pgvector HNSW non-transactional behaviour"
- memory_type: "incident"
- content: "pgvector's HNSW index is non-transactional. Rolling back a transaction does NOT undo index updates. If a test inserts a vector and the transaction rolls back, the vector remains in the HNSW index even though it's gone from the table. Always use DELETE or TRUNCATE for test cleanup — not transaction rollback. This affects any code that runs tests against a shared pgvector index."
- concepts: ["pgvector", "HNSW", "transactions", "testing", "rollback"]
- files: ["api/neuroloom_api/"]
- importance: 0.95
- tags: ["gotcha", "testing", "pgvector"]Use memory_store:
- title: "SQLAlchemy workspace isolation requirement"
- memory_type: "convention"
- content: "Every database query must filter by workspace_id. No exceptions. This is a security invariant — not a performance optimization. pgvector cosine similarity queries do not enforce tenant isolation through the index; the WHERE workspace_id = :workspace_id clause is the only thing preventing cross-tenant data access. Any new query or endpoint that omits workspace_id is a security bug."
- concepts: ["workspace isolation", "multi-tenancy", "security", "SQLAlchemy", "pgvector"]
- files: ["api/neuroloom_api/"]
- importance: 1.0
- tags: ["security", "invariant"]Use memory_store:
- title: "ARQ job serialization constraint"
- memory_type: "pattern"
- content: "ARQ background jobs must receive only JSON-serializable arguments. Never pass SQLAlchemy ORM objects to job functions — pass IDs as strings and reload from DB inside the job. The ARQ worker runs in a separate process with its own database connection pool and cannot deserialize ORM model instances from another process."
- concepts: ["ARQ", "background jobs", "serialization", "async"]
- files: ["api/neuroloom_api/workers/"]
- importance: 0.88
- tags: ["pattern", "arq"]import os
import httpx
token = os.environ["MEMORIES_API_TOKEN"]
workspace_id = os.environ["MEMORIES_WORKSPACE_ID"]
# Memories to migrate from CLAUDE.md
migrations = [
{
"title": "pgvector HNSW non-transactional behaviour",
"memory_type": "incident",
"narrative": (
"pgvector's HNSW index is non-transactional. Rolling back a transaction "
"does NOT undo index updates. Always use DELETE or TRUNCATE for test cleanup — "
"not transaction rollback. This affects all code that runs tests against a "
"shared pgvector index."
),
"concepts": ["pgvector", "HNSW", "transactions", "testing"],
"source_files": ["api/neuroloom_api/"],
"importance_score": 0.95,
"tags": ["gotcha", "testing", "pgvector"],
},
{
"title": "SQLAlchemy workspace isolation requirement",
"memory_type": "convention",
"narrative": (
"Every database query must filter by workspace_id. No exceptions. "
"pgvector similarity queries do not enforce tenant isolation through the index — "
"the WHERE workspace_id = :workspace_id clause is the only guard against "
"cross-tenant data access. Any query that omits workspace_id is a security bug."
),
"concepts": ["workspace isolation", "multi-tenancy", "security", "SQLAlchemy"],
"source_files": ["api/neuroloom_api/"],
"importance_score": 1.0,
"tags": ["security", "invariant"],
},
{
"title": "ARQ job serialization constraint",
"memory_type": "pattern",
"narrative": (
"ARQ background jobs must receive only JSON-serializable arguments. "
"Never pass SQLAlchemy ORM objects to job functions — pass IDs as strings "
"and reload from DB inside the job. The ARQ worker runs in a separate process "
"with its own connection pool."
),
"concepts": ["ARQ", "background jobs", "serialization", "async"],
"source_files": ["api/neuroloom_api/workers/"],
"importance_score": 0.88,
"tags": ["pattern", "arq"],
},
]
for memory in migrations:
response = httpx.post(
"https://api.neuroloom.dev/api/v1/memories/store",
headers={"Authorization": f"Token {token}"},
json={"workspace_id": workspace_id, **memory},
)
result = response.json()
print(f"Stored: {result['id']} {result['title']}")curl -X POST https://api.neuroloom.dev/api/v1/memories/store \
-H "Authorization: Token $MEMORIES_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"workspace_id": "'"$MEMORIES_WORKSPACE_ID"'",
"title": "pgvector HNSW non-transactional behaviour",
"memory_type": "incident",
"narrative": "pgvector HNSW index is non-transactional. Rollback does NOT undo index updates. Use DELETE/TRUNCATE for test cleanup, not transaction rollback.",
"concepts": ["pgvector", "HNSW", "transactions", "testing"],
"source_files": ["api/neuroloom_api/"],
"importance_score": 0.95,
"tags": ["gotcha", "testing", "pgvector"]
}'Output:
Stored: mem-1a2b3c4d pgvector HNSW non-transactional behaviour
Stored: mem-5e6f7g8h SQLAlchemy workspace isolation requirement
Stored: mem-9i0j1k2l ARQ job serialization constraintStep 3: Verify retrieval — search by meaning
Before removing anything from CLAUDE.md, confirm each migrated section is retrievable by the kinds of queries that would arise naturally during a session.
Use memory_search with query "what happens when I roll back a pgvector transaction in tests"Use memory_search with query "how do I avoid cross-tenant data in queries"Use memory_search with query "how to pass data to background jobs"for query in \
"what happens when I roll back a pgvector transaction in tests" \
"how do I avoid cross-tenant data in queries" \
"how to pass data to background jobs"; do
echo "Query: $query"
curl -s -X POST https://api.neuroloom.dev/api/v1/memories/search \
-H "Authorization: Token $MEMORIES_API_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"workspace_id\": \"$MEMORIES_WORKSPACE_ID\",
\"query\": \"$query\",
\"limit\": 3
}" | python3 -c "
import sys, json
data = json.load(sys.stdin)
for r in data['results']:
print(f' {r[\"score\"]:.2f} {r[\"title\"]}')
"
echo ""
doneExpected output:
Query: what happens when I roll back a pgvector transaction in tests
0.94 pgvector HNSW non-transactional behaviour
Query: how do I avoid cross-tenant data in queries
0.96 SQLAlchemy workspace isolation requirement
Query: how to pass data to background jobs
0.91 ARQ job serialization constraintAll three sections surface as the top result. If any query returns a score below 0.7, the narrative needs more concept keywords. Add concepts or expand the narrative before proceeding.
Step 4: Configure session context injection
The plugin injects high-importance memories automatically at session start. Configure which memories get injected by importance threshold.
Memories with importance_score >= 0.9 appear in session context by default. The workspace isolation invariant (1.0) and the pgvector rollback gotcha (0.95) both qualify.
To verify injection is working, start a new Claude Code session and ask:
Use session_start, then list what memories were injectedYou should see the high-importance memories from your migration in the injected_memories list.
For the full list of available tools and configuration options, see MCP Tools Reference.
Step 5: Trim CLAUDE.md to behavioral rules only
Once all migrated sections retrieve correctly, remove them from CLAUDE.md. Keep only the content that must be present in every session regardless of context:
Keep in CLAUDE.md:
- Workflow rules ("use
sdlc-planbefore implementing new features") - Tool constraints ("always use AskUserQuestion for decisions")
- Agent dispatch instructions ("never implement code yourself — dispatch domain agents")
- Rules that are process, not knowledge
Move to Neuroloom (already done):
- Architecture decisions with context and reasoning
- Coding patterns and conventions
- Bug fixes and gotchas
- Environment and configuration knowledge
- Historical context and rationale
Before and after comparison:
Before: 340 lines (~24,000 tokens loaded every session)
After: 85 lines (~6,000 tokens) — behavioral rules only
Knowledge moved to Neuroloom: 47 memories, searchable and session-injectedStep 6: Confirm the agent retrieves context without the old bulk
Open a fresh Claude Code session — one that loads the trimmed CLAUDE.md. Ask a question that would have previously required the full CLAUDE.md:
What do I need to know about running tests against pgvector?With the old CLAUDE.md, Claude Code would answer from the loaded context. With Neuroloom:
Use memory_search with query "pgvector test isolation gotchas"Response:
{
"results": [
{
"id": "mem-1a2b3c4d",
"title": "pgvector HNSW non-transactional behaviour",
"score": 0.94,
"summary": "Rollback does NOT undo HNSW index updates — use DELETE/TRUNCATE for test cleanup"
}
]
}The knowledge is there. It arrives when asked — not loaded into every session.
Production Patterns
Incremental migration — don't cut everything at once
Migrate one section at a time over two weeks. Verify retrieval for each section before removing it from CLAUDE.md. Run both simultaneously during the transition period:
Week 1: Migrate architecture decisions and conventions. Keep them in CLAUDE.md too.
Week 2: Verify all migrated sections retrieve correctly. Remove from CLAUDE.md.
Week 3: Migrate patterns, `incidents`, and gotchas. Same process.
Week 4: Trim to behavioral rules only. Final verification.The dual-source period means no knowledge is at risk if retrieval turns out to be unreliable for a particular topic.
Rate memories from the first week of use
The first week after migration is the highest-value feedback window. Every time a migrated memory is retrieved and used, rate it positive. Every time a search returns the wrong memory for a natural question, investigate and improve the narrative.
Use memory_rate after each retrieval:
Use memory_rate with memory_id "mem-1a2b3c4d" and useful true and context "Correctly told me not to use rollback in the pgvector test fixture"Set importance_score thoughtfully
Not everything that was in CLAUDE.md deserves high importance. Apply this heuristic:
| Importance | Use case |
|---|---|
| 1.0 | Security invariants, workspace isolation, breaking constraints that cause production bugs if forgotten |
| 0.9–0.95 | Gotchas that cost 30+ minutes to debug, conventions that affect every PR |
| 0.8–0.89 | Patterns and decisions that are useful frequently but not always |
| 0.7–0.79 | Historical context, rationale, and background knowledge |
| Below 0.7 | Nice-to-know; surfaces in targeted search but not session injection |
Periodic cleanup
After 6 months, some memories become stale — the gotcha got fixed, the convention changed, the architecture decision was reversed. Use the memory timeline to find old memories and review them:
curl -X GET "https://api.neuroloom.dev/api/v1/memories/?workspace_id=$MEMORIES_WORKSPACE_ID&created_before=2025-10-01&limit=50" \
-H "Authorization: Token $MEMORIES_API_TOKEN"Archive or update stale memories. A growing list of outdated memories degrades search quality.
Before You Ship
- Verify every migrated section retrieves with score > 0.80 before removing it from
CLAUDE.md - Confirm
importance_score: 1.0is set only on genuine invariants (2–5 per project is normal) - Test session context injection — start a fresh session and confirm the right memories appear
- Keep behavioral rules in
CLAUDE.md— migrate knowledge, not process instructions - Tag all migrated memories with
"migrated-from-claude-md"so you can audit them later - Run the final verification: open a session with the trimmed
CLAUDE.md, ask questions about every major topic, confirm Neuroloom answers correctly
Related
- Coding Agent Memory — build ongoing memory habits after the migration
- Knowledge Base Ingestion — bulk-import other project documentation
- Decision Tracking — formalize architectural decisions from the migrated content
- MCP Tools Reference — session context injection configuration