Best Practices & Recipes

Concrete patterns for structuring memory, writing good entries, and building reliable routing.

Structuring CLAUDE.md

The "Always-On Rules" Pattern

Inline your 5-6 most universal behavioral rules at the top of CLAUDE.md. These apply to every task and should never require a file read:

# Always-On Rules (apply to every task)
- One fix at a time: only implement the specific approved change.
- Verify claims: label uncertain statements as "Claim:" and verify before acting.
- Evidence first: debug from logs/data, never speculation.
- No magic strings: use constants or enums for property checks.
- Timebox debugging to ~1h, then build a minimal reproduction.
Why this works These rules cost ~5 lines (always loaded, survives compaction). A fresh Claude instance will follow them without needing to read any memory files. No routing required.

The "Before X, Read Y" Trigger Pattern

For topic-specific knowledge, use explicit triggers:

# Context Triggers
- Before deploying anything — read [deploy-guide.md](memory/deploy-guide.md)
- Before writing Svelte code — read [svelte-pitfalls.md](memory/svelte-pitfalls.md)
- Before working on CVs — read [cv-methodology.md](memory/cv-methodology.md)
- Before using Chrome MCP tools — read [browser-automation.md](memory/browser-automation.md)

Link Memories from Project Entries

# Projects
- **Video Platform**: `~/projects/video-platform/`
  See [ownership.md](memory/ownership.md) for service boundaries.
- **Trading App**: `~/projects/trader/`
  See [deploy-guide.md](memory/deploy-guide.md) for monorepo deploy.

Writing Good MEMORY.md Entries

The Sonnet memory selector reads only filenames and one-line descriptions. Bad descriptions = missed files.

BadGood
testing.md — Some notes about testingtesting.md — Integration tests must hit real DB, not mocks (prior incident)
feedback.md — Feedback from userfeedback_one_fix.md — Only implement the specific approved change, no extras
deploy.md — Deploy stuffdeploy-guide.md — Hetzner deploy: builds from origin/main, rsync + systemd restart

Group MEMORY.md by Type

# Memory Index

## Behavioral Rules (always apply)
- [feedback_one_fix.md](feedback_one_fix.md) — Only implement the approved change
- [feedback_evidence.md](feedback_evidence.md) — Debug from logs, cite timestamps
...

## Tool Guides (triggered by CLAUDE.md)
- [deploy-guide.md](deploy-guide.md) — Deploy script, server, monorepo handling
...

## Project Knowledge
- [ownership.md](ownership.md) — Video platform service boundaries
...

## Reference
- [pdf-convert.md](pdf-convert.md) — Use weasyprint for HTML-to-PDF

Memory File Best Practices

Frontmatter Format

---
name: Evidence-first debugging
description: Every claim needs evidence (log line, timestamp). Add logging before fixing.
type: feedback
---

Content here...

The description field is critical — it's what the Sonnet selector reads. Make it specific enough to match against task descriptions.

Consolidate Overlapping Memories

Regularly check for:

Archive Convention

Move obsolete memories to memory/archived/ and remove from MEMORY.md. This prevents index bloat and stale guidance.

Path-Scoped Rules Recipes

# .claude/rules/frontend-conventions.md
---
paths:
  - "**/*.svelte"
  - "**/*.tsx"
  - "**/*.vue"
---
# Frontend Rules
- Never write reactive state inside high-frequency events
- Use requestAnimationFrame for imperative library calls
# .claude/rules/service-worker.md
---
paths:
  - "**/sw.js"
  - "**/sw.ts"
  - "**/service-worker.*"
---
# Service Worker Safety
- fetch handler must not use respondWith(fetch())
- This breaks ES module caching
# .claude/rules/ci-deploy.md
---
paths:
  - "**/.github/workflows/**"
  - "**/Dockerfile"
  - "**/*.service"
---
# CI/Deploy Rules
- Read the deploy guide before changing deploy configs
- Use systemctl for systemd services

Anti-Patterns

Don't load everything Research proves this degrades performance. The 5-file selection limit exists for a reason.
Don't duplicate content across files One source of truth per concept. If a pitfall is in your pitfalls file, don't also have a separate feedback file for it.
Don't rely solely on CLAUDE.md triggers They depend on Claude "remembering" to follow them. Path-scoped rules and SessionStart hooks are mechanically enforced by the harness.
Don't write vague MEMORY.md descriptions "Some feedback about testing" won't help the Sonnet selector. Write descriptions that match the task descriptions that should trigger them.

Phased Improvement Plan

PhaseTimeWhat
130 minAdd always-on rules to CLAUDE.md + missing triggers. Highest impact.
21 hourConsolidate duplicate memories. Group MEMORY.md by type. Add orphans to index.
32-3 hoursCreate SessionStart hook for behavioral rules + git context injection.
41 hourCreate path-scoped rules for your main file patterns.
5WeekendOptional: MCP semantic search server for 50+ memory files.