Build Your Own Automated Options Trading System · Concept
CLAUDE.md — the one file
your codebase tells Claude
to read first.
Every session starts by loading it. Get it right, and Claude knows where to look. Get it wrong — leave it stale — and Claude confidently quotes things that aren't true any more. This lesson is the story of how that happened in a real trading repo, and the three mechanisms that now prevent it.
This lesson, in one glance
Same five beats. The most important file.
1
Idea
CLAUDE.md is a routing index Claude reads at the start of every session. It tells Claude where things live — not what the latest numbers are.
2
Outcome
A CLAUDE.md that stays correct without daily edits, with three mechanisms behind it so it can never rot silently again.
3
Vocabulary
routing index · staleness · update gate · freshness hook · source of truth
4
Hands-on
Open the file. Find a line that points elsewhere instead of restating a fact. Add a new strategy to the table — feel why the format matters.
5
War story
Four strategies + a whole engine shipped without one CLAUDE.md update. Claude kept saying "5 strategies, 499 tests." Reality: 6, 2080. Fixed yesterday.
1 · The idea
It's not a manual. It's the front desk of your codebase.
What it feels like to write
- "Project overview". You list strategies, tranche times, lot sizes, SL percentages, test counts.
- Tempting to be detailed. The more facts you put in, the more "documented" it feels.
- Edited once. Maybe twice. Then never again, because every config change should technically update it.
- Authoritative-looking. It's at the top of every session, so Claude treats it as the source of truth.
- Silent failure mode. When facts inside it drift, nothing tells you.
What it actually is
- A routing index. Tells Claude where to look for each kind of question — not what the answer is.
- Architectural, not numeric. "Strategy configs live in
config/strategies/." Not "T1 fires at 10:45."
- Stable. It only changes when structure changes — new strategy, new module, new broker. Rarely.
- Compounding. A good CLAUDE.md makes every future session faster. A bad one poisons every session quietly.
- Single most leveraged file in the repo. Every Claude session reads it. Every assistant decision is shaped by it.
Rule of thumb: if a fact in CLAUDE.md could change without anyone noticing — like a tranche time or test count — it shouldn't be in CLAUDE.md. Put a pointer to where the fact lives instead.
2 · Pointers vs facts
One line is brittle. The other survives every config change.
.claude/CLAUDE.md · the wrong way
# Strategies
### Option Cracker
- 3 tranches: 10:00, 11:00, 12:00
- Fixed lots: 3
- SL: 50%, NRML, squareoff 15:14
- Lookback: 40 / 60 / 90 min
### IVDrift
- 4 tranches: 09:45, 10:15, 11:01, 11:30
- Lots: T1/T2 = 4, T3/T4 = 3
- SL: 100% with 2:1 trailing
# Tests
499+ tests in tests/
.claude/CLAUDE.md · the right way
# Strategies
| Strategy | Entry | Config | Engine |
|----------|-------|--------|--------|
| OC | main_equity.py | config/strategies/option_cracker.py | core/equity/ |
| IVDrift | main_iv_drift.py | config/strategies/iv_drift.py | framework |
Read the config file for tranche times,
lot sizes, SL %, and target premiums.
Do not quote these from this file.
# Tests
Run: pytest --collect-only -q | tail -1
Left side: every config tweak makes CLAUDE.md a lie. Right side: a new strategy adds one row; everything else routes to the source. Half the words. Forever fresh.
3 · Why this one file matters more than the rest
Every session. Every assistant. Every decision.
Auto-loaded
- Claude Code loads
.claude/CLAUDE.md at the start of every session — no command needed
- It sits in the system prompt, treated as "the user's authoritative instructions"
- Other files in the repo are read only when Claude decides to look at them
- CLAUDE.md is read before Claude has any reason to look at anything else
Shapes every answer
- "Which strategy runs at 09:45?" — answered from CLAUDE.md unless Claude verifies
- "How many tests are there?" — quoted from CLAUDE.md if the number is in there
- "Where does SL logic live?" — Claude opens whatever path CLAUDE.md says
- If the file is wrong, the answers are wrong — confidently
Owned by nobody
- No PR template enforces an update — most teams don't even list it
- No CI check fails when it's stale — it's "just docs"
- No one's calendar reminds them — and reminders for docs always lose to shipping code
- Until something breaks because of it, you don't know it's drifted
A bug in code crashes loudly. A bug in CLAUDE.md whispers — for weeks — and you only catch it when an assistant confidently states something that isn't true.
4 · A real timeline · this repo · 2026-03 → 2026-05
Four strategies. A whole engine. Zero CLAUDE.md updates.
2026-03
CLAUDE.md last seriously edited. Project has 2 strategies (MCX, Option Cracker), ~499 tests, 83 bugs in the bug log. The file proudly states these numbers.
2026-04-18
Universal Strategy Framework lands — core/framework/ with engine, recovery, sl_manager, event sourcing. The next 4 strategies will plug into it. CLAUDE.md: not touched.
2026-04-24
DecayDoctor ships. New entry point, config, controller, start script, cron reminder. CLAUDE.md: not touched.
2026-04-29
IVDrift ships. New entry point, controller, IV monitor dependency. CLAUDE.md: not touched.
2026-05-07
First Strike ships. New hybrid broker stack — Tradejini orders, Upstox quotes. Important quantity semantics. CLAUDE.md: not touched.
2026-05-19
RSI Sniper ships. Same hybrid stack. Reality: 6 strategies, 2080 tests, 197 bugs. CLAUDE.md still says 5 strategies, 499 tests, 83 bugs. User notices, asks "is my CLAUDE.md updated?"
Two months of silent drift. Every session in that window started by reading numbers that hadn't been true since week one of the gap.
5 · Why this happens — to everyone
Five reasons. None of them is laziness.
No owner
- Plans cover code, tests, live verification
- None of them list "update CLAUDE.md"
- So no one does
Manual, not index
- The file tries to be a manual
- Every config change should update it
- That's annoying — so it doesn't happen
Memory shortcut
- Save a memory note — feels like documentation
- But memory is private and partial
- CLAUDE.md is public and complete — and stale
No signal
- Nothing tells you it's drifted
- No banner, no CI failure
- Silent. Confident. Wrong.
Claude trusts it
- It's loaded as user instructions
- Claude quotes it without verifying
- You get fluent, confident, outdated answers
Every project hits this. The only difference is how soon you notice — and what you do to make sure it doesn't happen again.
6 · The fix — three independent mechanisms
Don't rely on memory. Make rot impossible.
design
Rewrite as a routing index
Replace facts that drift (tranche times, test counts, bug numbers) with pointers to where the facts live. The file now only changes when structure changes — much rarer than parameters.
.claude/CLAUDE.md
policy
Add a checklist + a memory rule
"Adding a New Strategy" in CLAUDE.md lists 9 steps. Step 8 is update this file. A memory note backs it: any new strategy / module / broker MUST update CLAUDE.md in the same PR.
memory/feedback_claudemd_update_gate.md
automation
Add a freshness hook
SessionStart hook compares CLAUDE.md's last-commit date against every structural path. If anything's newer, it prints a banner at session start. No more silent drift — you see it the moment you open a session.
.claude/hooks/claudemd-freshness-check.sh
Design alone isn't enough — humans forget. Policy alone isn't enough — checklists get skipped. Automation alone isn't enough — banners get ignored. Three together: belt, braces, and a parachute.
7 · The hook · how staleness is detected
Twelve lines of bash. Runs every session.
[1] Session starts. Claude Code reads .claude/settings.local.json.
It finds: SessionStart → run claudemd-freshness-check.sh
│
▼
[2] Hook runs: // always exits 0 — never blocks
last_md_commit = git log -1 --format=%ct -- .claude/CLAUDE.md
│
▼
[3] Hook lists commits newer than that, in structural paths:
main_*.py, hedge_runner.py
start_*.sh, scripts/kill_*.sh
config/strategies/
core/brokers/, core/framework/, core/strategies/
│
▼
[4a] If newer commits = 0: silent. Nothing printed. Session continues.
│
▼
[4b] If newer commits ≥ 1: prints a banner —
⚠ CLAUDE.md may be stale
last updated: 2026-05-07
structural commits since then: 53
review before answering architecture questions
(lists the top 10 commits so you know what changed)
│
▼
[5] You see the banner. You decide:
- update CLAUDE.md now, or
- confirm nothing structural changed (logs-only commits don't need it).
Either way: the rot can't sit silently for two months again.
The hook doesn't fix CLAUDE.md. It just makes the gap visible. That's enough — a visible problem gets fixed; an invisible one rots.
8 · What belongs · what doesn't
Two simple tests. Apply to every line.
Belongs in CLAUDE.md
- Structure. "Strategies live under
core/strategies/; each has a config in config/strategies/."
- Isolation rules. "No cross-imports between
core/equity/ and core/mcx/."
- Defaults that constrain how things work. "All new strategies use the framework, not the legacy engine."
- Pointers to deeper docs. "Read
docs/order-execution-playbook.md before touching order code."
- Critical safety rules. "Double-leg atomicity — both orders or neither."
- Skills/subagents to invoke. "Before
send_alert, invoke the telegram-alerts skill."
Does NOT belong
- Specific numbers. Tranche times, lot sizes, SL %, target premiums — these live in configs.
- Counts. Test count, bug count, strategy count, file count. All drift.
- Code snippets. They go stale silently and get copy-pasted as if current.
- Quirks for one strategy. Memory notes are the right place —
project_first_strike_broker.md, not CLAUDE.md.
- Recent commit summaries. Use
git log for that. CLAUDE.md is not a changelog.
- Anything you'd have to update on a small config tweak. If yes, it's the wrong content for this file.
Test 1: does this fact change when I tweak a config? If yes — out. Test 2: does a session of Claude need this to find the right place to look? If yes — in.
9 · The update gate
Nine numbered steps. Step 8 is the rule that saves you.
1. Create config/strategies/<name>.py with all params + capability flags.
2. Create core/strategies/<name>/controller.py for entry/SL/exit logic.
3. Create main_<name>.py entry point that wires config → framework.
4. Create start_<name>.sh + scripts/kill_<name>.sh wrappers.
5. Confirm calendar / DTE / holiday handling matches house conventions.
6. Invoke the telegram-alerts skill — add to coverage matrix.
7. Dispatch the pre-live-auditor subagent before first live run.
8. ✦ UPDATE CLAUDE.md ✦
- Add a row to the Strategies table.
- Add the spec under "Design Docs".
- If broker routing differs from defaults, mark it.
- If a new safety rule, add it to "Critical Safety Rules".
9. Save a memory note explaining only the non-obvious quirks —
not facts that already live in code (those go in CLAUDE.md / configs).
Step 8 is visible in the file every time a new strategy is planned. It's also enforced by a memory note. And it's audited by the freshness hook. Three reminders, one rule.
10 · By the end of this lesson
You can keep your most important file honest, forever.
You can tell the difference between a CLAUDE.md that is a manual (fragile) and one that is a routing index (durable).
You apply the two-line test: "does this drift on a config tweak?" and "does Claude need it to know where to look?" before adding anything to CLAUDE.md.
You have a checklist that includes a CLAUDE.md update step — and you refuse to mark plans complete without it.
You wire a freshness-check hook into SessionStart so every session tells you if structural commits have outpaced your CLAUDE.md.
When CLAUDE.md and code disagree, you trust the code — and you update the file in the same PR.
The file that shapes every assistant decision in your repo deserves three independent mechanisms protecting it. None of them is hard to add.
11 · New vocabulary
Five words. Use them this week.
routing index
A document that tells you where to look for facts — not the facts themselves. CLAUDE.md is most useful as a routing index.
"see config/strategies/<x>.py"
staleness
The gap between what a document claims and what's true in code right now. Grows silently. The most expensive kind of bug.
CLAUDE.md vs reality
update gate
A rule that says "this PR cannot land unless CLAUDE.md is updated alongside it." Lives in checklists, memory, hooks — anywhere.
step 8 in plans
freshness hook
A small script that compares the last-modified date of CLAUDE.md against changes to structural paths, and warns when one outpaces the other.
claudemd-freshness-check.sh
source of truth
The one place where a fact really lives. For tranche times: config/strategies/<x>.py. For test count: pytest --collect-only. Never CLAUDE.md.
"the config is the SoT"
All five together = you can audit any project's CLAUDE.md and tell, in two minutes, whether it's about to rot.
12 · The hands-on bit — your task
Open it. Audit it. Fix one drift.
Step 1 · Read
- Open
.claude/CLAUDE.md in your editor
- For each line, ask: routing or fact?
- Mark facts that could drift on a config tweak
- Aim for at least 80% of lines being pointers
Step 2 · Run the hook
.claude/hooks/claudemd-freshness-check.sh
- If it prints a banner, list the structural commits since the last CLAUDE.md update
- For each one: does CLAUDE.md still describe reality? If not, edit and commit
Step 3 · Add a row
- Pretend you're adding strategy #7 — call it
volsweep
- Add the row to the strategies table
- Notice you only added one line — no parameters, no SL %, no tranche times
- That's the format working as intended
Most CLAUDE.mds in the wild are facts. Most should be pointers. The one-row-per-strategy test is the cleanest signal you've got the format right.
Concept lesson — takeaway
The one file Claude reads first
deserves three mechanisms protecting it.
Write it as a routing index, not a manual. Add a checklist step so updates can't be skipped. Wire a hook so staleness can't sit silently. None of these is hard — and together they make sure your most leveraged file never lies to your future self.
End of CLAUDE.md
Next: Memory files — the second-layer index.
Where CLAUDE.md ends, project memory takes over: quirks, decisions, war stories →
source: .claude/CLAUDE.md · .claude/hooks/claudemd-freshness-check.sh · memory/feedback_claudemd_update_gate.md