Build Your Own Automated Options Trading System · Concept

MEMORY.md — the second-layer index
that grows from experience.

CLAUDE.md is the handbook everyone gets — public, in-repo, loaded every session. MEMORY.md is the private notebook one assistant builds with one user — outside the repo, full of the why and the non-obvious. Different purpose, different home, different update loop. This lesson is how they fit together.

Concept lesson
MEMORY.md · personal · accretive
Builds quietly. Compounds invisibly.
This lesson, in one glance

Same five beats. The second-layer file.

1
Idea
MEMORY.md is the assistant's personal notebook. It captures the why behind decisions, your preferences, and lessons that the code itself can't tell.
2
Outcome
A memory system that compounds over conversations, never duplicates CLAUDE.md, and self-detects when it's drifted.
3
Vocabulary
memory file · index · feedback / project / reference type · why-line · drift hook · cross-link
4
Hands-on
Read the index. Spot a stale entry. Add a new memory using the three-line template. Watch the freshness hook react.
5
War story
A memory system that grew to 70 files over 60 days, then got audited — 7 deleted, 3 rewritten, 6 added. Now self-renewing.
1 · The idea

It's not documentation. It's the private notebook Claude keeps on you.

CLAUDE.md — the handbook

  • Public. Lives in .claude/CLAUDE.md, committed to the repo, every collaborator gets the same file.
  • Routing. Tells Claude where to look — file paths, module structure, which skill to invoke.
  • Architectural. Changes only when structure changes — new strategy, new module, new broker.
  • Auto-loaded entirely. Loaded into every session in full.
  • Edited as a deliberate act. A real commit, on a real branch.

MEMORY.md — the notebook

  • Private. Lives outside the repo at ~/.claude/projects/<...>/memory/. Not in git, not shared, just on your machine.
  • Reasoning. Captures the why behind decisions — past incidents, your preferences, hard-won lessons.
  • Accretive. Grows from every conversation as the assistant learns what you need.
  • Index loads; bodies load on demand. The index is in every session; individual memories are pulled when relevant.
  • Written by the assistant. As you talk, lessons get saved without ceremony.
Rule of thumb: if a fact lives in code, it belongs in CLAUDE.md as a pointer. If a lesson lives only in your head ("we tried that — it broke production in March"), it belongs in MEMORY.md.
2 · The split — every dimension that matters

Same idea. Different jobs.

Dimension CLAUDE.md MEMORY.md
Lives where Inside the repo · .claude/CLAUDE.md Outside the repo · ~/.claude/projects/<hash>/memory/
Committed? Yes. In git. Visible to anyone with the repo. No. On your machine only. Switch laptops → starts empty.
Author You. Deliberate edit, reviewed PR. Claude, with your nod. Written mid-conversation.
Content type Where things live. Architecture. Skill triggers. Why you chose this. Quirks. Past incidents.
Loaded Entire file, every session. Index every session; individual memory bodies on demand.
Updates when Structure changes — new strategy, new broker, new module. You teach Claude something or correct it. Every conversation can add one.
Drift signal Freshness hook compares CLAUDE.md vs code timestamps. Freshness hook compares memory mtimes vs bug-log commits.
CLAUDE.md is the "office handbook on every desk." MEMORY.md is your "Moleskine that lives in your jacket pocket." Both useful. Different jobs.
3 · Anatomy of a memory

Frontmatter + body. Three required lines.

memory/feedback_no_live_trading_on_local.md
---
name: Never run live trading from the local Mac
description: All live strategy starts (start_*.sh) must run
             on Lightsail, never on the local MacBook
metadata:
  type: feedback
---

Live trading processes must run on the Lightsail server
(ssh lightsail), NEVER on the local MacBook.

The local prompt LOCAL-DEV is the tell. If you
see a nohup ./start_*.sh from that prompt,
warn first — do NOT debug the crash.

Why: Local runs duplicate orders against the same
broker accounts as Lightsail. The user said: "always
tell me I cannot run live trade on local machine
whatever the case" (2026-05-20).

How to apply: First response when you spot a local
start_*.sh must point them at Lightsail.
Exception: test_live_*.py 1-lot harnesses.
name
Short slug. Becomes the filename. Stable identifier for cross-links from other memories.
description
One-line summary. This is what Claude scans to decide whether to load the full body.
metadata.type
One of: feedback · project · reference · user. Drives when Claude reaches for it.
Why / How to apply
The two structuring questions. Why = the past incident or preference. How to apply = when this kicks in.
The description is the most important line. It's the only part Claude sees first. A vague description means the memory never gets loaded when it should.
4 · Four kinds of memory · each with a different trigger

Type tells Claude when to use it.

user

  • Who the user is. Role. Goals. Knowledge level.
  • Used to tailor answers — explain less to an expert, more to a novice
  • One per project, sometimes two
  • Example: user_trading_profile

feedback

  • "Don't do X" or "Do Y" — a behavioral rule
  • Usually from a correction the user gave you
  • Most common type as the system matures
  • Example: feedback_verify_bug_numbers

project

  • State of the world. Who is doing what, by when, and why
  • Decays fast — needs re-verification every few weeks
  • Operational quirks of a specific strategy
  • Example: project_ivdrift_operational_policy

reference

  • Pointer to an external resource — server, dashboard, doc
  • Doesn't change often
  • Cheap to keep, useful when relevant
  • Example: reference_lightsail_ssh
"Don't run live on local" is feedback. "RSI Sniper lots are 5/5/5/6 right now" is project. "Lightsail is at 13.202.219.68" is reference. Picking the right type isn't ceremony — it's how Claude decides whether to even open the file.
5 · How loading actually works

One index in every session. 73 bodies, loaded only on demand.

[1]  Session starts. Claude Code loads:
        - System prompt
        - .claude/CLAUDE.md  ·  fully loaded · every session
        - ~/.claude/.../memory/MEMORY.md  ·  fully loaded · every session
                (the index — 108 lines, ~3.5 KB)
        
        
[2]  User asks: "can we test live on local Mac?"
        
        
[3]  Claude scans the index for relevant descriptions.
        Finds:  "feedback_no_live_trading_on_local.md —
                 Never run start_*.sh on local Mac"
        
        
[4]  Claude opens that specific memory file.
        Now sees: full body, Why, How to apply, related links.
        
        
[5]  Claude answers from the loaded memory:
        "That's a live-trading start on your local machine —
         run it on Lightsail (ssh lightsail) instead."

// Notice: 72 OTHER memory files were never loaded for this question.
// The index is the routing layer. Bodies are pulled by description.
This is why descriptions matter so much. A bad description = the memory stays unloaded = the lesson is invisible. Hundreds of memories with vague titles is worse than ten with sharp ones.
6 · The actual evolution of this project's memory

Three months of growth. One audit.

2026-03
First memories saved. 6 files. User profile, MCX broker quirks, basic safety standards. Small enough to fit in your head.
2026-04
Broker abstraction shipped. Tradejini integrated. ~25 files. Memories about partial fills, ghost fills, Algomojo removal, hedge lifecycle. Useful but ungrouped.
2026-05-05
Production incident — OC adopted IVDrift positions. 5 new memories codify the lessons: ownership classification, per-strategy isolation, alert throttle, no-catchup gate.
2026-05-19
CLAUDE.md rewrite. 70 memory files. Some are stale (Algomojo references, "phase 1/2/3" plans). Some duplicate CLAUDE.md. Some are 60+ days old and untouched.
2026-05-20
The audit. 7 deleted (shipped already, duplicated CLAUDE.md). 3 rewritten (refresh current state). 6 added from bug-log scan (lessons the code can't teach). Final: 74 files, semantically grouped, all current.
2026-05-20
The loop closes. A new freshness hook + a scan-bug-log-for-memories skill. The next time the index has stale entries OR new bugs land, a banner fires at session start — the system surfaces its own decay.
Memory systems don't fail because lessons get added wrong. They fail because nobody reviews them periodically and old entries silently mislead. The audit is the heartbeat.
7 · Drift, twice — once for code, once for memory

Two hooks. Same shape. Different sources.

CLAUDE.md drift hook

  • Trigger: structural code commits newer than CLAUDE.md's last commit
  • Detects: "you added a strategy and forgot to mention it in the handbook"
  • Source of truth: git log against main_*.py, core/strategies/, etc.
  • Fix: edit CLAUDE.md, commit, push — handbook back in sync
  • File: claudemd-freshness-check.sh

MEMORY.md drift hook

  • Trigger: memories untouched in 60+ days, OR new bug-log.md commits since last scan
  • Detects: "you added 80 bugs and didn't extract any lessons" or "this old memory might be stale"
  • Source of truth: file mtimes + git log against docs/bug-log.md
  • Fix: invoke the scan-bug-log-for-memories skill — propose, write, update state
  • File: memory-freshness-check.sh
CLAUDE.md drift is structural — code moves, doc lags. Memory drift is experiential — incidents happen, lessons stay un-extracted. Different problem, same response: surface the gap, don't block the session.
8 · What earns a memory · what doesn't

One filter question. "Would I still trip on this?"

Earns a memory (yes — code can't tell you)

  • Broker quirks. Tradejini has no REST quote endpoint. Upstox 401 errors retry-stall.
  • Operational policy. IVDrift is manual-start, never cron. Hedge runner gets its own bot.
  • Same-shape bug across strategies. Ownership classification — bit us three times.
  • User corrections. "Always ask before I commit." "I'm in IST, not UTC."
  • Incident postmortems. Failure chain in one paragraph — so it's findable.
  • Non-obvious math. RSI Wilder needs 100-candle warmup, not period+1.

Does NOT earn a memory

  • Specific numbers. Tranche times, lot sizes — read the config, never the memory.
  • Bug fixes. The fix is in code. Memory adds nothing.
  • Architecture. Lives in CLAUDE.md (which itself routes to the code).
  • One-off task notes. "Tomorrow check token" is a TODO, not a memory.
  • Anything that's already in CLAUDE.md. Memory must add the why, not duplicate the where.
  • Anything you'd update on every config tweak. If yes, it's the wrong file.
The hard question: "if I read the code today, would I still trip on this?" Yes → memory. No → leave it in the bug log or the code. Of 197 bugs scanned in this project, only ~6 earned memories.
9 · The self-updating loop · three pieces

Hook, skill, feedback memory. Closes its own circle.

automation

The hook surfaces the gap

SessionStart hook checks: any memory >60 days old? Any bug-log commits since the last scan? If yes, prints a banner. Self-rate-limited so it only fires once a week.

.claude/hooks/memory-freshness-check.sh
methodology

The skill carries the recipe

Invoked when the banner fires (or on demand). Walks the bug log, cross-checks against existing memories, presents a shortlist. Six hard rules — verify BUG numbers, never duplicate, bias toward expansion.

.claude/skills/scan-bug-log-for-memories/
discipline

The memory codifies the loop

A feedback memory that says "when the banner fires, invoke the skill". Self-referential by design — a memory file describes how the memory system maintains itself.

memory/feedback_periodic_memory_review.md
Same three-mechanism pattern as CLAUDE.md drift: design (what belongs) + policy (what to do) + automation (when to act). None of the three alone is enough. Together, the loop closes itself.
10 · By the end of this lesson

You can build a memory system that compounds, not bloats.

You can tell when a lesson belongs in CLAUDE.md (architecture / where) vs MEMORY.md (why / non-obvious) — and why duplicating between them is silent harm.
You apply the one-line filter: "if I read the code today, would I still trip on this?" — before writing any memory.
You write memories with the three required lines (name, description, type) — knowing the description is what triggers loading.
You group MEMORY.md by purpose (engineering standards · verification rules · strategies · live ops · incidents) — not chronologically.
You wire the freshness hook so memory drift can't accumulate silently — and you actually invoke the scan skill when the banner fires.
A memory system that pays attention to itself outlives your patience for it. Build the loop once; it does the work forever.
11 · New vocabulary

Five words. Different from last lesson.

index file
A list of pointers, not content. MEMORY.md is the index; the 74 files alongside it are bodies, loaded on demand.
MEMORY.md — 108 lines
feedback type
A memory that captures a behavioral rule the user gave you. Most common type — "always do X" or "never do Y" with the reason attached.
feedback_*.md
why-line
The required reason behind a memory — usually a past incident or strong preference. Without it, future-you can't judge edge cases.
"Why: BUG-079 closed Algotest's position"
cross-link
A [[name]] reference between memories. Builds a small graph of related lessons — and surfaces orphans.
[[feedback_ownership_pattern]]
scan cadence
How often you audit the memory system end-to-end against new bugs. Roughly 60 days. Surfaced automatically by the freshness hook.
.claude/state/last_memory_scan.json
If CLAUDE.md is the handbook, MEMORY.md is the field journal. Different vocabulary for a different job — but the same idea: make rot impossible.
12 · The hands-on bit — your task

Read it. Audit it. Add one memory.

Step 1 · Read the index

  • Open ~/.claude/projects/<hash>/memory/MEMORY.md
  • For each entry, ask: do I know why this memory exists? Is the description specific?
  • Flag any entry whose description is too vague to trigger loading

Step 2 · Spot a stale one

  • Look for memories with old project_* names — past plans, "tomorrow" notes, shipped phases
  • Open one. Decide: still true, or shipped/superseded?
  • If superseded → delete the file + remove the index line

Step 3 · Add one memory

  • Think of a correction you gave Claude this week
  • Write a feedback_*.md file: name, description, type, then Why + How to apply
  • Add the index line under the right section. Run the freshness hook to check state file updates correctly
Memory systems start small and stay small only if you trim while you write. The audit + skill turn that from discipline into a one-banner reminder.
Concept lesson — takeaway

The handbook tells Claude where to look.
The notebook tells Claude why it matters.

CLAUDE.md is for everyone who clones the repo. MEMORY.md is for the assistant working with you, on your machine, over weeks. Both need a drift hook. Both need a clear filter for what belongs. Together they make Claude smarter every conversation — without bloating into something nobody can audit.

End of MEMORY.md

Next: Skills + subagents — when a memory isn't enough.

source: ~/.claude/projects/<...>/memory/MEMORY.md · .claude/hooks/memory-freshness-check.sh · .claude/skills/scan-bug-log-for-memories/
← → navigate · F fullscreen · click to advance
1 / 16