Direct answer
Claude Code's memory system is designed to persist relevant facts between sessions in a structured and lazy-loaded manner, allowing for efficient recall of context without the need for explicit reminders. This enables long-running projects to maintain continuity and reduces the time spent on onboarding new information, freeing up more time for productive work.
A Claude Code session is ephemeral by default: conversational memory ends when you close the window. For long-running projects this is a problem: every session starts from scratch, it's up to you to remind the model "remember what we decided on X?". The system memory/
Claude Code solves exactly this: relevant facts persist between sessions in a structured, self-cured, and lazy-loaded manner.
Independence Disclaimer: I am not affiliated with XPHX0XPHX or XPHX1XPHX. The description that follows is based on my memory portfolio (over 60 facts accumulated in approximately 12 months) and how I use it operationally.
Memory Directory Structure/
Location: ~/.claude/projects/<project-slug>/memory/Schema:
Schema:
Note: I've kept the original formatting and punctuation intact, as per your request. Let me know if you need any further assistance!
memory/
├── MEMORY.md index (max 200 righe)
├── user_role.md user fact
├── user_workflow.md user fact
├── feedback_no_dark_mode.md feedback fact
├── feedback_ollama_only.md feedback fact
├── project_architecture.md project fact
├── project_brand.md project fact
├── reference_wikidata_token.md reference fact
└── reference_buttondown.md reference fact
MEMORY.md It's always indexed at the start of each session. Each
entry points to a specific file (e.g. - [No dark mode](feedback_no_dark_mode.md)
- Sito light only, no toggleWhen the model judges,
relevant the fact, reads the full file (lazy-load).
The 4 categories of facts
- I don't see any Italian text provided. Please share the Italian text you'd like me to translate, and I'll be happy to assist you.Who is the user, role, expertise, preferences cognitive (e.g. "Senior Java developer, learning React for the first time"). Helps to explain explanations and analogies.
- I don't see any Italian text to translate. Please provide the text you'd like me to translate, and I'll be happy to assist you.Guidance received on workflow. Do (patterns confirmed as good) and don't (corrections applied). Example: "Don't use git stash in worktree" - feedback after a pull disaster of a pop pulled into WIP from sibling worktree.
- progettoCurrent state of the project. Decisions recent ones, in-flight blocker, time constraints (e.g. "forfait P.IVA simulated up to €5K/year"). It is updated frequently, life shorter than feedback.
- I don't see any Italian text provided. Please provide the text you'd like me to translate, and I'll be happy to assist you.Pointer to external systems. URL dashboard, account, repo, and relevant external documents. "Buttondown account federico@federicocalo.dev", "Wikidata Q139562320", etc.
When Claude saves a fact
Default: "also only 1% of relevance in future sessions" = save. Low threshold intentionally set. It's better to save and then do a cyclic pruning, than not to save and lose the context.
Explicit user trigger:
ricorda che XSave immediately.dimentica YRemove fact + entry from MEMORY.md.aggiorna che XOverwrite existing fact.
Automatic triggers (observed but without explicit instruction):
- New design/architecture decision.
- User correction on workflow ("not like that, do this").
- Bound discovered (e.g. "this API does not work in Italy").
- Reference to an external system mentioned for the first time.
Real examples from my MEMORY.md file
Selection of current entries in my MEMORY portfolio (summary):
- [Project Architecture](project_portfolio_architecture.md)
- Monorepo with Angular 21 SSR + Spring Boot 3.4 + FastAPI,
migrating from Firestore to REST API
- [Brand Positioning](project_brand_positioning.md)
- "Full-Stack AI Engineer per startup e PMI IT/EU, applicazioni
enterprise documentate 8-12 settimane" + vincolo pull
- [SSH VPS via public key](feedback_ssh_vps_access.md)
- Accesso VPS Hetzner solo via alias ssh portfolio-prod
- [No git stash in worktree](feedback_worktree_no_stash.md)
- Mai usare git stash in worktree (refs/stash condiviso)
- [AI provider Ollama-only](feedback_ai_provider_ollama_only.md)
- Tutti i tool AI usano Ollama on-prem VPS
- [Wikidata API token](reference_wikidata_token.md)
- Token Federico per Q139562320, .env.prod only
- [Design System GitHub Primer light](project_design_system.md)
- Sito light theme only, no toggle
Every entry is ~100-150 characters. Total index ~180 lines (within the 200 limit). When I start a session, Claude reads MEMORY.md and has all the macro context in 1k tokens. Lazy-load specific facts on-demand.
Frontmatter of fact files
---
name: feedback-no-dark-mode
description: Sito light theme only - no dark mode toggle, palette in styles.css
metadata:
type: feedback
---
# No dark mode
Decisione del 2026-03: il sito federicocalo.dev usa SOLO light theme.
Rimosso ThemeService toggle. Palette completa in
`frontend/src/styles.css` con CSS custom properties var(--color-*).
NON proporre dark mode toggle in nuovi componenti.
NON usare rgba hardcoded per "fall-back dark" - sempre var(--color-*).
Link related: [[project_design_system]]
Frontmatter always minimal: name, description,
metadata.typeBody 50-300 lines. Cross-link via fact
[[name]] The syntax of Markdown is used to create links in a simple way.
To create an internal link, you use the following syntax:
For example, is an internal link.
You can also add a title for the link using the `title` attribute:
Google
To create a link with a different text than the URL, you use the following syntax:
For example: Go to Google
You can also add HTML inline tags inside the link. For example:
https://www.google.com
Or:
Google
Note that you can use any HTML tag inside a link, but it's recommended to keep it simple.
To create an external link, you use the following syntax:
For example: Wikipedia
You can also add a target attribute to specify where the link should open:
Wikipedia
Note that you can use any HTML tag inside a link, but it's recommended to keep it simple.
Cyclic Pruning
MEMORY.md grows but must stay under 200 lines. Quarterly pruning is typical:
- Claude analyzes the current MEMORY.md file + last session activity.
- Identify outdated facts (e.g., a superseded project fact due to the most recent decision).
- Proposes removal (with rationale for each).
- User approves/rejects case on a case-by-case basis.
- Approved deletions: cancels files fact+entry from MEMORY.md.
Typically 5-15 entries removed every quarter. Accumulated: stable size around 60-80 total entries.
Memory cross-project
Every project has its own separate memory directory (path with project-slug). Fact is ~/.claude/projects/<project-A>/memory/
I am not visible in ~/.claude/projects/<project-B>/memory/.
Generic user facts (e.g. "Federico is a Java/TS developer") are often duplicated across projects. Workaround: some installations of Claude Code support user-level memory global in
~/.claude/memory/ Verify current documentation. On my setup I use project-specific memory + duplicate user fact where needed.
Anti-pattern: memory as a task tracker
Temptation: saving all of TODO or backlog in memory. Error. Memory is for
Persistent factsDon't do it for the sake of a flight. Use a task tracker .planning/STATE.md (GSD-managed) external issue tracker
Symptom of anti-pattern: project facts that say "step X in progress, next step Y, blocker Z". Those are tasks, not facts. Move them elsewhere, and the memory stays cleaner.
Anti-pattern: memory as a reference document
Another temptation: saving long documentation snippets in memory. Error. Memory is for mouse + decisionsDo not use a content reference. The reference fact states that the Wikidata API documentation URL is https://... and does not attach the entire documentation.
Symptom of anti-pattern: fact files over 500 lines. Split into
pointer-only + external content (file in docs/ I don't see any Italian text provided. Please share the text you'd like me to translate, and I'll be happy to assist you.
Security: what NOT to save in memory
- API key, password, token (always in
Note: I've kept the original formatting and punctuation of the Italian text, including the repeated phrase "in ".
.env.prodI don't see any Italian text provided. Please provide the text you'd like me to translate, and I'll be happy to assist you. - Third-party personal data (GDPR - memory is not classified for personal data).
- Decisions in conflict with legal/ethical constraints (e.g. workarounds to bypass licensing).
- Code snippet proprietary protected by NDA.
Memory is a markdown plain text file; treat it as git-tracked (even if you don't commit it, it's on the filesystem). Don't include anything you wouldn't want in a backup.
Memory in workflow GSD
Memory complements .planning/PROJECT.md:
- I don't see any Italian text provided. Please provide the text you'd like me to translate, and I'll be happy to assist you.Planning artifacts, formal, in Git, shared with the team if the project is a team project.
- memoryPersonal context, informal, NOT in Git (personal user), between sessions Claude Code.
Complementary pattern: an important strategic decision goes into bothPROJECT.md for formal audit trail; memory to have comfortable context at hand in every future session.
What I learned writing this article
The thing that surprised me is how much the memory has reduced the fatigue of explaining things to the model again. Before adoption (memory-free sessions), every start of a session was 5-10 minutes of onboarding: "the project is X, the stack is Y, we decided Z". After that, automatic onboarding via MEMORY.md took only 30 seconds.
Second insight: the discipline of writing fact files in ADR style (with rationale + Why + How to apply) has improved content. Memory that cites "Why: incident of 2026-03 where we lost WIP using git stash in worktree" is more useful than "Memory: don't use git stash in worktree". The why allows the model to understand edge cases when applying the rule.
Avoided pattern
- Memory as a task trackerSTATE.md is for tasks; memory for persistent facts.
- Memory as a reference documentPointer + decisions; do not fill out. Split into external files if it grows.
A story worth sharing
Placeholder Section If you have pattern memory that has changed your workflow, write to me at federico@federicocalo.dev.
Previous cluster: Ingest-docs synthesizer Next cluster (track Platform): MCP server development →
Frequently asked questions
What is the default behavior of a Claude Code session?
A Claude Code session is ephemeral by default, meaning that conversational memory ends when you close the window.
How does Claude Code solve the problem of long-running projects starting from scratch?
The system solves this problem by allowing relevant facts to persist between sessions in a structured, self-cured, and lazy-loaded manner.
What is the purpose of MEMORY.md in a Claude Code setup?
MEMORY.md serves as an index that is always read at the start of each session, providing macro context in 1k tokens, and allows for lazy-loading specific facts on-demand.
Why should you not use memory as a task tracker or reference document?
Memory is intended for persistent facts and decisions, not tasks or long documentation snippets. Using it as such can lead to clutter and make the memory less effective.
Commenti
Caricamento commenti...
Sign in to comment