Your AI Coding Rules Should Not Live in Cursor Rules

I stopped treating editor-specific AI rule files as the source of truth and moved my Rails and Flutter standards into plain Markdown that Cursor, Claude, Codex, Copilot, and...

Markdown source of truth for AI coding rules connected to editor-specific adapter files

I have a bunch of Rails and Flutter projects.

Some are new. Some are old enough that opening them feels like archaeology with syntax highlighting.

Over time, I started adding AI instructions to each repo: Cursor rules, project notes, testing workflows, architecture preferences, “please don’t invent a new service object unless you really have to”, that kind of stuff.

It worked great.

Until it didn’t.

Because Cursor could see .cursor/rules.

Claude Code could see CLAUDE.md.

Codex looked for AGENTS.md.

GitHub Copilot wanted .github/copilot-instructions.md.

And every other LLM was basically standing outside the house, looking through the window, wondering where the rules were.

Every. Single. Tool. Has. Its. Own. File.

The Problem

The obvious mistake is to treat editor-specific rules as the source of truth.

Cursor has .cursor/rules/. Claude has CLAUDE.md. Codex and other coding agents often look for AGENTS.md. GitHub Copilot has .github/copilot-instructions.md.

So if I put all my rules only in Cursor, Claude doesn’t see them.

If I put them only in Claude, Cursor doesn’t see them.

If I copy-paste them everywhere, Future Me gets a beautiful new maintenance problem.

No thanks.

The Realization

The trick is simple:

Editor-specific rule files should be adapters, not the source of truth.

The source of truth should be boring Markdown.

Plain files. Versioned with the repo. Easy to read. Easy to grep. Easy for any LLM to consume.

So I started using this pattern:

AGENTS.md
CLAUDE.md
.github/copilot-instructions.md
.cursor/rules/*.mdc
docs/llm/rails-standards.md
docs/llm/flutter-standards.md

The important files are the ones in docs/llm/.

Everything else points there.

Rails: Use a Reference, Keep Local Overrides

For Rails, I already had a bunch of local 37signals-inspired Cursor rules.

  • keep controllers thin
  • prefer rich models
  • avoid unnecessary service objects
  • prefer Rails-native primitives
  • use Minitest
  • don’t reach for gems too quickly

Then I found Marc Kohlbrugge’s excellent unofficial 37signals coding style guide.

It’s basically a much bigger version of what I was trying to maintain locally.

So instead of keeping my tiny partial copy, I switched to this:

docs/llm/rails-standards.md

That file says:

  • use Marc’s guide as the primary Rails reference
  • pin it to a specific commit
  • load only the topic needed for the task
  • local project rules override it only when they are more specific

That last part matters.

A general Rails guide should not know that one of my projects uses a repo-local 1Password wrapper, or that MyGoo has some non-standard table naming, or that Solid Cache does not support some cache-store methods.

Those stay local.

General philosophy comes from the shared reference. Project weirdness stays in the project.

Flutter: Extract the Rules From the Newer Apps

Flutter was a little different.

I didn’t have one external reference repo. I had newer apps with better Cursor rules.

They all converged on the same patterns:

  • BLoC/Cubit for app-level state
  • repositories as the single source of truth
  • services wrapping APIs, SDKs, and platform channels
  • UI that renders state and does not do business logic
  • dart format .
  • flutter analyze
  • flutter test
  • one failing regression test before a bug fix
  • no side effects in build
  • check mounted after async gaps
  • no random direct API calls from widgets

So I distilled those into:

docs/llm/flutter-standards.md

Then each app gets a tiny adapter:

AGENTS.md
CLAUDE.md
.github/copilot-instructions.md
.cursor/rules/3000-flutter-standards-reference.mdc

Again, the adapter is not the source of truth.

It just tells the agent where the source of truth is.

The Pattern

This is the structure I like now:

docs/llm/
  rails-standards.md
  flutter-standards.md

AGENTS.md
CLAUDE.md
.github/copilot-instructions.md
.cursor/rules/

AGENTS.md is the general entry point.

Codex and many other coding agents understand it. Even if they don’t “officially” support it, it’s obvious enough that humans and agents can read it.

CLAUDE.md is tiny:

Read and follow AGENTS.md first.

For Rails work, read docs/llm/rails-standards.md.
For Flutter work, read docs/llm/flutter-standards.md.

Copilot gets the same idea:

Follow AGENTS.md first.

For Rails work, read docs/llm/rails-standards.md.
For Flutter work, read docs/llm/flutter-standards.md.

Cursor rules become scoped adapters:

Read docs/llm/flutter-standards.md before Flutter work.

The detailed Cursor rules are adapters and examples.
The shared standard is the cross-agent source of truth.

That’s it.

No magic.

Just boring files in predictable places.

Why This Works

LLMs are very good at following instructions when they can find them.

The problem is discovery.

If my instructions live only in .cursor/rules, Claude Code may not see them.

If they live only in CLAUDE.md, Cursor-specific automation may miss them.

If they live only in my prompt history, congratulations, I have invented personal folklore.

Putting standards in docs/llm/ makes them explicit.

Pointing every tool-specific file to those standards makes them discoverable.

Keeping project-specific overrides local prevents the shared docs from turning into a junk drawer.

What I Learned

  1. The source of truth should be tool-agnostic.
    Cursor rules, Copilot instructions, and Claude files should point to shared docs, not duplicate them.
  2. Adapters should be small.
    If a .cursor/rules file becomes a 500-line architecture document, it probably belongs in docs/llm/.
  3. Pin external references.
    For Rails, I point to Marc’s 37signals guide and pin a commit. “Latest main” is not a standard. It’s a moving target.
  4. Local overrides matter.
    Shared rules should cover philosophy and common patterns. Project-specific constraints still belong in the project.
  5. This is onboarding for humans too.
    The nice surprise: these files are not just for AI. Future Me can read the same docs and remember how the hell I decided to build this app six months ago.

Bottom Line

AI coding agents are becoming part of my workflow.

Not metaphorically. Practically.

They open files, make changes, run tests, write PRs, debug CI, and sometimes make very confident mistakes.

If different agents see different rules, they will produce different code.

So I don’t want my conventions hidden inside one editor’s config.

I want the real standards in plain Markdown.

Then Cursor, Claude, Codex, Copilot, and whatever comes next can all point to the same place.

Boring? Yes.

Effective? Also yes.

And Future Me will thank me, because Future Me definitely does not want to maintain five copies of the same rule that says “please don’t put business logic in Flutter widgets.”