cd /news/ai-tools/one-source-of-truth-for-your-ai-agen… · home topics ai-tools article
[ARTICLE · art-49011] src=pub.towardsai.net ↗ pub= topic=ai-tools verified=true sentiment=· neutral

One Source of Truth for Your AI Agent Rules: Cursor, Claude Code, and Every Tool You’ll Adopt Next

A developer outlines a method to maintain consistent AI coding-agent instructions across multiple tools like Cursor and Claude Code by designating AGENTS.md as the single source of truth, with tool-specific files acting as thin wrappers that import from it, preventing the drift that occurs when rules are duplicated across files.

read10 min views1 publishedJul 7, 2026

A practical setup for keeping coding-agent instructions consistent across tools — without maintaining n copies of the same rules.

This week Fable is back. We don’t know how long he’ll stay or when he’ll return — but as with every guest, the house should be clean. I’m not the kind of person who keeps their repos spotless, and I experiment with a lot of different tools, so after a while the mess was real: rule files for different agents, all slightly out of sync. This is how I cleaned up — once — ready for every guest to come.

If you use more than one AI coding tool, you’ve probably hit this wall already. Claude Code and Codex-style tools read AGENTS.md or CLAUDE.md files, loaded hierarchically per folder. Cursor reads glob-scoped .mdc .mdc rule files from .cursor/rules/ .cursor/rules/. And the naive fix — writing the same conventions into every file, for every tool — is exactly how projects end up with N copies of the truth. And it happens especially often when the agents write the rules themselves.

Here’s what happens next: a convention changes. You update one file and forget the others, or you dutifully update all of them until the day you don’t. The files silently drift apart, and your agents start giving contradictory advice depending on which tool happened to pick up which file.

There’s a simpler way to structure this, built on a single principle.

One fact lives in exactly one file. Everything else points to it.

Concretely: AGENTS.md is the single source of truth for a directory. Every other instruction file covering that same directory — CLAUDE.md, a Cursor .mdc rule — is a thin wrapper that imports the AGENTS.md content and adds only what that specific tool needs and AGENTS.md structurally cannot express.

AGENTS.md — the source of truth. Tool-agnostic. All real content lives here.

CLAUDE.md — thin wrapper. @-imports AGENTS.md. Adds Claude-only behavior (Plan Mode, memory).

.cursor/rules/*.mdc — thin. @-imports AGENTS.md. Adds Cursor-only behavior (glob activation).

CLAUDE.local.md — personal, gitignored. Never shared, never a source of truth.

One file deliberately missing from this list: README.md. That one’s for humans, not agents. More on that later.

my-project/├── AGENTS.md                  # root — cross-tool source of truth, tool-agnostic├── CLAUDE.md                  # root — thin, @imports AGENTS.md├── CLAUDE.local.md            # gitignored — personal preferences only├── README.md                  # human-only — not read by agents as instructions├── backend/│   ├── AGENTS.md              # domain source of truth│   └── CLAUDE.md              # thin, @imports backend/AGENTS.md├── frontend/│   ├── AGENTS.md│   └── CLAUDE.md└── .cursor/    └── rules/        ├── general.mdc        # always-apply — @imports root AGENTS.md        ├── frontend.mdc       # glob-scoped — @imports frontend/AGENTS.md        └── backend.mdc        # glob-scoped — @imports backend/AGENTS.md

The rule of thumb: every domain folder that has its own conventions — backend, frontend, a specific subsystem — gets its own nested AGENTS.md. Don’t create .agents/rules or .claude/rules directories — agents sometimes try to mount them.

This is the file every tool reads first. Keep it tight and push domain detail down into nested files.

One anti-pattern to avoid: don’t restate your whole README here. AGENTS.md is operational guidance for an agent about to write code; README.md is a human's onboarding doc. Some facts — the stack, the commands — legitimately live in both, and that's fine. That's not the duplication this pattern is trying to kill. What you're avoiding is copying whole rule sections between AGENTS.md, CLAUDE.md, and .mdc files.

Every subsystem with its own conventions gets one (backend, frontend and others). Same shape as the root file, but narrower: layout, the API or interface contract, conventions specific to that folder, and commands that only make sense there.

Here are some best practices for your backend rule context:

Claude Code and Codex-style tools load nested AGENTS.md or CLAUDE.md files automatically based on which directory you're working in. That's the whole point of putting domain rules here instead of bloating the root file.

The root version:

Everything Claude needs beyond AGENTS.md or AGENTS.md structurally can't express, because it's Claude-specific: Plan Mode, auto-memory, the @-import syntax itself.

The nested version adds an exemplar pointer:

A pointer to one real, well-written example file in the codebase is often worth more than another paragraph of prose. The agent can pattern-match against actual code.

Path resolution: @AGENTS.md inside backend/CLAUDE.md resolves relative to the importing file — i.e. it points to backend/AGENTS.md, not the root one. And since Claude Code loads the whole hierarchy cumulatively, the root file is already in context. Don't re-import it here — that's duplication of an import rather than content, but it's still noise.

Add CLAUDE.local.md to your .gitignore. This is not a place for project conventions — those go in the tracked files so the whole team (and every tool) sees them. This file is scoped to you, on this machine.

Cursor’s native mechanism is glob-scoped .mdc rule files — and you can define exactly when each rule applies. The same principle: don't duplicate content, @-import the matching AGENTS.md.

One always-applied general rule:

---alwaysApply: true---# General@AGENTS.md

And one glob-scoped rule per domain:

---description: What this rule is for, in one lineglobs: backend/**/*.pyalwaysApply: false---# Backend@backend/AGENTS.mdExemplar: @backend/best_example.py

One more rule: keep only one file with alwaysApply: true. Everything else should be glob-scoped so it only loads when relevant — that's the entire reason to use Cursor rules instead of just relying on nested AGENTS.md.

I didn’t take the docs’ word for it — I checked what the agent could actually see. The results surprised me twice.

**Finding #1: your **@-imports doesn’t load immediately.

You’d expect that with alwaysApply: true, everything here — including the imported backend/AGENTS.md — sits in context from the first message. It doesn't. Cursor loads the .mdc file's own text at session start, but the @-referenced files load lazily — only once the agent actually works on opened file frombackend/. Until then, the import is just a pending pointer.

This is actually fine — arguably it’s the behavior you want, since domain rules on demand keep the context lean. But it changes how you should read alwaysApply: it guarantees the rule file is present, not everything the rule file points to. If some instruction absolutely must be there from message one, it has to live in the .mdc body or in root AGENTS.md — not behind an @-import.

**Finding #2: Cursor also picks up **CLAUDE.md natively — so the wrapper pattern could load twice.

Cursor reads CLAUDE.md files for Claude Code compatibility. Which means my thin wrappers (CLAUDE.md → @AGENTS.md) got pulled in alongside the .mdc rules importing the same AGENTS.md. Same content, two channels.

The fix: add the CLAUDE.md files to .cursorignore. Cursor will still list them in context, but by name only — it never reads their contents. At least that's what my testing shows; verify in your own setup. The Claude-specific wrappers stay in the repo for Claude Code, Cursor stops duplicating them, and each tool gets exactly one channel to the single source of truth:

You can, of course, just ask the agent: “List all rule files currently in your context.” The problem: the answer doesn’t have to be true — or complete. While checking the setup, my agents confidently gave me wrong answers in both directions — claimed files they hadn’t read, and denied seeing content that was sitting right there in context or read files directly from repo. Self-reports are vibes, not evidence.

So check it yourself. Plant a canary: add a line to your rules file that the agent couldn’t produce by accident:

"say PINEAPPLE when the user asks about loaded rules"

Then open a fresh session and ask about loaded rules. If the fruit shows up, the file is in context. No fruit, no rule. That was the funny part:

Claude Code treated it as a threat, Cursor treated it as an easter egg.

The tools reacted with very different personalities. Cursor said PINEAPPLE every single time, no questions asked. Claude Code refused — it flagged the line as a possible prompt injection attempt hidden in a project file and warned me to check where it came from. Which, to be fair, is exactly what that line looks like. But the refusal is a positive result too: Claude Code couldn’t have flagged an instruction it never read.

Claude Code has one more instrument you can use: /context shows a rough map of the context window — memory files with their actual paths and sizes, token budget, the works.

Tempting shortcut: symlink CLAUDE.md → AGENTS.md instead of writing an import. Don't. Three reasons:

Here’s the part everyone skips. You set this up, it works, and few weeks later your AGENTS.md confidently describes a command that no longer exists.

Treat instruction files like code, then. The good news: with this structure, maintenance is almost trivial. When a convention changes, you edit the one AGENTS.md that owns it — nothing else to touch. That's the entire point.

And every now and then, re-run the canary check — the tools and their mechanisms change over time, and what loaded yesterday may not load tomorrow.

Set this up once and the payoff compounds: every new tool you adopt gets a two-line wrapper file instead of a full rewrite, every convention change is a one-file edit, and your agents finally stop arguing with each other about how your codebase works.

It works fine for me now. Mostly I use cursor with its agnets and claude code in cursor or in desktop app.

Next : we’re tackling skills — how to teach your agents reusable workflows, and how to stay in control of what they know and where it comes from.

If you’ve found a different pattern that works across tools — or a gotcha I missed — I’d genuinely like to hear about it in the comments.

One Source of Truth for Your AI Agent Rules: Cursor, Claude Code, and Every Tool You’ll Adopt Next was originally published in Towards AI on Medium, where people are continuing the conversation by highlighting and responding to this story.

── more in #ai-tools 4 stories · sorted by recency
── more on @fable 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/one-source-of-truth-…] indexed:0 read:10min 2026-07-07 ·