Every AI Tool Has Its Own Anchor File. A Living Document Lives Above All of Them.
Source: martinfowler
Most AI coding tools ship with some mechanism for persistent context. Claude Code reads CLAUDE.md at session start. Cursor reads .cursorrules. GitHub Copilot reads .github/copilot-instructions.md. Each of these files attempts the same thing: give the model enough background about your project that it does not start from zero every time. Each does it in a way that creates a quiet form of lock-in.
This fragmentation matters less than it first appears, but it reveals something important about where the real problem lives. Rahul Garg’s context anchoring pattern, published in Martin Fowler’s series on reducing AI friction, addresses a layer of the problem that none of those tool-specific files are designed to handle.
What the Startup Files Actually Solve
CLAUDE.md, .cursorrules, and their equivalents solve the session-start problem. They tell the model what it needs to know before you type your first prompt: the stack, the conventions, the things to avoid, the tone of comments, the test framework. This is genuinely useful. Without it, every session opens with the same ramp-up conversation where you explain the project again.
But these files are loaded once and do not change during the session. They capture the stable background of your project, not the live decisions you make while working. If you spend the first twenty minutes of a session negotiating an approach with the model, settling on a specific abstraction, ruling out a dependency because of a performance constraint you discovered last week, none of that ends up in .cursorrules. It stays in the conversation, subject to the attention dynamics that make long AI sessions unreliable.
The Lost in the Middle paper from Liu et al. (2023) documented this empirically. Transformer recall performance follows a U-shaped curve over context length: information at the start and end of a conversation receives more reliable attention than information buried in the middle. A decision made at turn five of a sixty-turn session sits in the worst possible position by the time you reach turn forty. It is not gone; it is just underweighted.
Context anchoring addresses this by externalizing those mid-session decisions into a document that can be re-injected at the top of a new session, or periodically refreshed within a long one. The startup files and the context anchor serve different purposes. One describes the project. The other records the conversation’s agreements.
Why Plain Markdown Beats Every Native Format
The practical advantage of keeping a context anchor as a plain Markdown file is that it works across every tool. A .cursorrules file is Cursor-specific by convention. A CLAUDE.md is primarily meaningful to Claude Code. A Markdown document you author yourself can be pasted into any system prompt, injected at the start of any session with any model, shared with a collaborator using a different tool, committed to the repository alongside the code it informs, or handed directly to a human reviewer who needs to understand the decision history.
None of the native files have this property. They are shaped by filename convention and platform expectation in ways that make them awkward to port. The context anchor, because it is just text, is portable by default. That portability is worth more than any tool’s native integration, particularly in environments where the team has not standardized on one AI assistant.
For a project like a Discord bot with ongoing development, the anchor file can live in the repository root alongside CLAUDE.md, serving a different function. The CLAUDE.md explains the codebase to any model starting fresh. The context anchor captures decisions specific to the current work stream, updated as the stream evolves.
What Belongs in the Document
The structure matters less than the discipline, but the categories that tend to be most useful are these three.
Stable decisions cover architectural choices that are now fixed: which event library you committed to, why you chose Redis over SQLite for the job queue, that slash commands are the interface pattern and prefix commands are not being added. These decisions do not need to be re-litigated in every session. Writing them down also forces you to articulate the reason, which makes it easier to know when a constraint has genuinely expired.
Session decisions cover choices specific to the current work stream that may not be permanent. You are implementing the /remind command and settled on a 7-day maximum, per-user limits stored in a particular schema, and a specific parsing strategy for duration strings. These are not project-wide commitments but they are decisions the model needs to maintain for this session to stay coherent. Without the anchor, the model drifts back to generating whatever pattern seems locally reasonable.
Ruled-out paths are the category most developers skip and most regret. Every time you reject a model suggestion, you have information the model does not have: why that path fails for this specific context. Without recording it, the model will propose the same path again ten messages later, and you will reject it again without remembering why. A short note on each rejected approach, with the reason, prevents this cycle.
A minimal structure looks like this:
## Architecture
- Event handling via discord.js v14 slash command interactions, not legacy message prefix commands
- Redis for all persistent state; SQLite was ruled out due to write contention under concurrent guild activity
## Current work stream: /remind command
- Maximum duration: 7 days (product decision, not technical)
- Reminders stored in `reminders:{userId}:{reminderId}` key pattern
- Duration parsing: natural language strings normalized to milliseconds at write time, not read time
## Ruled out
- node-cron for reminder scheduling: process restarts lose state. Using Redis sorted sets with TTL instead.
- Storing reminder text encrypted: adds key management complexity that is not warranted for this use case
This document is not a substitute for code comments or a proper architectural decision record. It is a working surface for the AI session, designed to be injected into context and updated as the session develops.
The Maintenance Trigger
A living document is only as useful as the discipline that keeps it current. Two conditions should trigger an immediate update: when you make a decision you would need to re-explain if the session reset, and when you reject a model suggestion for a reason that is not obvious from the code alone. The update should happen at the moment of the decision, not at the end of the session. By end of session, you have already forgotten two of the five decisions you made and the model has partially drifted on the other three.
The cost is low. A one-line addition to the ruled-out section takes ten seconds. The alternative is spending five minutes reconstructing why you rejected something when the model proposes it again next session, or in thirty messages.
This is where the pattern connects to practices teams already use for human decision-making. Architectural Decision Records exist because the rationale behind a decision evaporates faster than the decision itself. Six months after choosing a message broker, the ticket that explains why is buried in Jira, the Slack thread is gone, and the engineer who made the call has moved teams. The ADR persists the reasoning alongside the code. The context anchor does the same thing at the timescale of an AI session rather than a project lifetime.
The Real Value Is Tool Independence
There is a version of this problem that the tool vendors will eventually solve. Claude’s Projects feature already provides persistent context across sessions within a project scope. Other tools are building similar memory systems. As these mature, some of the manual discipline behind context anchoring will become automated.
But automated tool memory is still tool-specific memory. It lives in the vendor’s system, not in your repository. It travels with your account, not with the code. A context anchor document committed to the repository is readable by every tool, every collaborator, and the codebase’s future maintainers, regardless of which AI assistant they use. That is a property no native memory system can replicate, because native memory is designed to serve the tool, not the project.