Memory bank instructions for AI coding agents – persistent context across sessions
Permanent reference documentation for humans and AI. Specs arrive in docs/ for implementation. Post-implementation, convert to reference docs (remove planning language, describe current state, update status).
| Content | Location | Rationale |
|---|---|---|
| How the system works, API docs, architecture | docs/ |
Permanent reference |
| Patterns discovered during implementation | memory-bank/system-patterns.md |
AI working context |
| Current work in progress | memory-bank/active-context.md |
AI working context |
system-patterns.md may cross-reference docs/ (e.g. "See docs/logging.md for conventions").
Ownership across the boundary – state once, link, don't restate. A docs/ reference owns the what: APIs, props, config, the rules you follow when building. system-patterns.md owns the why and the technique: rationale, reusable mechanisms, gotchas, anti-patterns. When a docs/ rule has a non-obvious why, state the rule there and link to the pattern – don't reproduce the mechanism in both. Reciprocally, a pattern links to docs/ for canonical build-facts rather than restating them. The same fact in both places drifts. Pick the owner by what kind of fact it is and cross-link.
Your memory resets between sessions. The memory bank is your only link to previous work.
| File | Purpose | Character | Limit |
|---|---|---|---|
project-brief.md |
Foundation: scope, requirements, goals | Stable, rarely updated | – |
product-context.md |
Why this exists, problems solved, UX goals | Updated on pivots | – |
tech-context.md |
Tech stack, setup, constraints, dependencies | Updated on tech changes | – |
system-patterns.md |
Architecture, patterns, lessons learned | Comprehensive reference | Audit at 2,000 lines |
active-context.md |
Single working-state file: current focus (2–3 items), blockers, next-ticket pointers, open decisions | Actively managed | 80 lines |
Git is the changelog – don't re-narrate the diff into the memory bank. A memory-bank update captures only forward-looking working state and durable patterns.
system-patterns.md vs active-context.md:
- Durable lesson, pattern or decision? → system-patterns.md with full context
- Need to reference it from current work? → one-line pointer in active-context.md
- Never duplicate the full lesson in both
active-context.md lifecycle:
- 'Done' means implemented and verified, not committed/merged/deployed. The moment that is true, remove the item from Current focus in the same session – the commit is its record. Never park it pending a merge/PR/deploy decision
- A durable lesson goes to system-patterns.md. A still-open decision or follow-up stays in active-context.md as an open item. Everything else drops out – git holds it
- If nothing is active, say so and list the next candidate tickets rather than carry a stale item
Status discipline:
- The memory bank records implementation status only (not started / in progress / done). Delivery-lifecycle state is owned by git, the PR system and CI – query it there (
gh pr view,git log), never mirror it here. Banned in parenthetical tags and in prose/status lines alike:(committed <sha>),(pending commit),(uncommitted on branch X),(deployed), 'in PR review', 'pending/ready to merge', 'awaiting deploy', 'PR #N open', 'Remaining before merge: …'. A bare ticket/spec/PR reference is a fine stable locator – only the mutable status attached to it is banned. Branch names are not stable locators – a branch is deleted when its PR merges, so abranch Xtail goes stale immediately. Don't record branch names in the memory bank or any reference doc. Cite the PR, spec or ticket instead - Discriminator for whether something belongs in active-context.md at all: if git, the PR or CI records the outcome automatically once approved (merging, a tag landing, CI deploying), it is not a tracked item – it never enters working state, or drops out on completion. If it is substantive work someone must still perform (e.g. a manual CDN release procedure), it stays as an open item until done, then drops out
Writing style:
- active-context.md: Current work details, not historical "how we got here". Lean – aim for scannable, not comprehensive
- system-patterns.md: Comprehensive explanations with examples
Avoid in active-context.md: Session-specific language ("today", "this session"). Use status-focused language ("In progress", "Blocked").
Anti-patterns to watch for (apply to active-context.md and system-patterns.md):
- "Updates as of [date]" / "Recent changes" / "Changelog" / "Scope correction" / "Post-X reframe" blocks summarising what changed since the doc was created or last updated – edit in place. The git log is the changelog – don't maintain a hand-written done-list anywhere in the memory bank
- "After X on [date]..." section intros – force the reader to decode history every time they read the doc
- "not X alone" / "not just X" / "actually Y" / "X + Y blended" / "X conflated with Y" phrasings – these read as corrective edits to a previous claim. State current understanding plainly – the git log carries history
- "Originally we thought Y but now we think Z" framing – just describe Z
- Verbatim quotes embedded in forward-looking docs – belong in commit messages, PR descriptions, or design-decision archives, not memory bank
- Root-cause analyses of past mistakes in the same doc where the mistake happened – post-mortems and process lessons belong in dedicated reference docs, not the live working doc
Only update when prompted. When asked to update the memory bank:
- Review what was done: Run
git diffto see code changes as a starting point - Read all 5 memory bank files
- Update as needed, respecting content boundaries above
- Verify: Run
git diffon the memory bank files and cross-reference against the work completed. Confirm everything was captured and no important detail was lost in edits. Report exceptions only – if clean, confirm in a single line
Document a pattern when ≥2 criteria met:
- Used in 2+ locations
- Solves non-obvious problem
- Has anti-pattern to warn against
- Prevents future errors
Do not document: One-off implementations, trivial/obvious code, speculative features
Pattern format:
- 10–30 lines with clear example
- Structure: Problem → Solution → When to use
- Warning sign: >50 lines for single pattern
Organisation:
- Group by domain/concern, not file location
- Target 100–200 lines per section
- Split sections >300 lines
Index (files over ~800 lines):
- Carry a Contents block at the top: one entry per H2 section,
[Section title](#anchor) – one-line scope description - A section you can't summarise in one line is doing too much – condense or split per the standards above
- No line numbers (they drift on every edit) – grep the heading anchor to find a section
- Regenerate whenever sections are added, removed, retitled, or change scope
- A navigation aid, not a substitute for reading the file
Audit when any file exceeds its limit OR any single section bloats even if the overall file is under limit.
When auditing active-context.md, check ALL sections – routing table:
- Current work focus – completed-and-verified items are removed same session (git is the record). A durable lesson the work produced goes to system-patterns.md (see the active-context.md lifecycle rule above)
- Implementation-detail narratives – belong in commit message, PR description, or
docs/ - "How we got here" framing – git log already preserves history – edit in place
- Stakeholder-acknowledgement waiting state – external trackers (PR review, deploy queue, ticket system) own this, not memory bank
When auditing system-patterns.md, check for:
- One-off "patterns" documented as reusable
- Patterns >50 lines that could be condensed
- Duplicated content between files
- Patterns for non-existent features
- Index missing or stale (files over ~800 lines)
Test: "If an AI searched for X, would this help or overwhelm?"