Hand the same feature to Cursor, Claude Code and Copilot and you can get three different builds — not because the models disagree, but because each one read a different file before it started. Cursor looked at .cursor/rules, Copilot read .github/copilot-instructions.md, and Claude Code read CLAUDE.md. If those files drifted apart, so did the code.
Spec-driven development with Cursor, Claude Code and Copilot works when one approved spec drives all three agents instead of three per-tool instruction files that quietly diverge. The portable layer is an AGENTS.md file at the repo root: Cursor and Copilot read it directly, and Claude Code reaches it through a one-line import. Each agent then adds its own thin, tool-specific layer on top — and knowing exactly where those layers differ is what keeps one spec from becoming three.
Key Takeaways
- The three agents read different files by default —
.cursor/rules,.github/copilot-instructions.md, andCLAUDE.md— so "write a good spec" is not enough; you have to decide which file each agent sees.AGENTS.mdis the portable layer. Cursor and GitHub Copilot read it directly; Claude Code readsCLAUDE.md, so you bridge with a single@AGENTS.mdimport line.- Keep tool-specific files thin. Everything that defines the feature belongs in the shared spec; only genuinely tool-specific behaviour (Cursor's
globs, Copilot'sapplyTo, Claude's plan-mode habits) belongs in the per-agent file.- GitHub's Spec Kit runs the same Spec → Plan → Tasks → Implement flow across all three, generating per-agent command files from one spec.
- On a solo repo this is a file-layout problem. On a team across multiple repos, the hard part is keeping one approved spec true as it fans out — which is a workflow problem, not a Markdown one.
Why spec-driven development splinters across Cursor, Claude Code and Copilot
The same spec produces three different builds because each agent resolves the gaps you left using a different instruction file, and those files live in different places with different rules. Give an underspecified task to three agents and each fills the blanks from whatever context it loaded — so the divergence is set before the first line of code.
This is the multi-agent version of a problem every spec-driven development workflow already has with one agent: an agent never stops to ask, it completes the most likely version and ships it. With three agents, you get three "most likely versions," each anchored to a different file. The fix is not a better prompt per tool. It is a single source of truth that all three resolve against, plus a clear, deliberately small set of per-tool overrides.
The portable layer: one AGENTS.md all three can reach
AGENTS.md is the one spec file worth centralising on, because it is the closest thing the three agents have to a shared format. It is a plain-Markdown file at the repo root — an open standard now stewarded under the Linux Foundation — that describes how agents should work in your project. Cursor reads it, Copilot's coding agent reads it, and Claude Code reaches it through an import. Put the feature's intent, scope, and conventions here once.
A good AGENTS.md carries the same material an AI-ready spec does — objective, scope, what to reuse instead of rebuild, and how "done" is verified:
# AGENTS.md
## Project
Payments service. TypeScript, Postgres, Stripe. One repo of a 6-repo system.
## Conventions
- Money is integer cents, never floats.
- All writes go through `lib/ledger.ts` — never INSERT into `transactions` directly.
- Every new endpoint needs a contract test in `tests/contract/`.
## Current feature: refund API
Objective: let support issue a partial refund against a captured charge.
Out of scope: chargebacks, multi-currency, refunds older than 90 days.
Done when: `POST /refunds` is idempotent on `charge_id`, and the ledger
entry nets to zero against the original capture.
Cursor and Copilot pick this up with no extra wiring. Claude Code reads CLAUDE.md rather than AGENTS.md, so you bridge the two with a single import line — which keeps CLAUDE.md as a real file where you can still add Claude-only notes underneath:
# CLAUDE.md
@AGENTS.md
## Claude Code only
- Use plan mode for anything touching the ledger; show the plan before editing.
One file defines the feature. The import means there is still exactly one place the feature is specified, even though two filenames point at it.
Where each agent diverges — and what belongs in its file
Each agent adds a configuration layer the others don't have, and the discipline that keeps one spec intact is putting only genuinely tool-specific behaviour there. The feature definition stays in the shared spec; the per-tool file handles how that tool applies it. Here is what each layer is actually for.
Cursor — .cursor/rules/*.mdc, scoped by globs
Cursor's richest layer is project rules: .mdc files in .cursor/rules/, version-controlled, with frontmatter that decides when each rule loads. The useful, tool-specific capability here is path scoping — a rule that only activates for files matching a glob. A plain .md file in that folder is ignored, so the frontmatter is not optional.
---
description: Ledger write rules
globs: ["lib/ledger.ts", "app/api/refunds/**"]
alwaysApply: false
---
- Never bypass `recordEntry()`. Every mutation is double-entry.
- A refund entry must reference the original capture's `entry_id`.
Scope this to the ledger paths, not the whole repo, and let AGENTS.md carry the rest. The moment a .cursor/rules file starts restating the feature, you have two specs.
Claude Code — CLAUDE.md plus plan mode
Claude Code's tool-specific strength is not a config file at all; it is the review step. With the shared spec imported via @AGENTS.md, plan mode lets you ask for a plan — affected files, order of changes, the tests that prove it — and approve it before any edits land. That approved plan is the natural checkpoint for a human to confirm the agent read the spec the way you meant it. Keep CLAUDE.md to the import plus a few Claude-only working habits; resist pasting the feature back in underneath it.
GitHub Copilot — copilot-instructions.md plus path instructions
Copilot reads a repo-wide .github/copilot-instructions.md, and its coding agent also reads AGENTS.md. Its distinct capability is path-specific instructions — .github/instructions/*.instructions.md files with an applyTo glob, the direct analogue of Cursor's scoped rules:
---
applyTo: "tests/contract/**"
---
Contract tests use the recorded Stripe fixtures in `tests/fixtures/`.
Never hit the live Stripe API from a test.
GitHub notes that when several instruction sources match, Copilot's choice between conflicting ones is non-deterministic — which is the whole argument for keeping the shared spec the single authority and these files narrow and non-overlapping.
Let Spec Kit generate the per-agent files
If maintaining those files by hand sounds fragile, GitHub's Spec Kit exists to generate them from one spec. It is an open-source toolkit that runs a Spec → Plan → Tasks → Implement flow and supports Cursor, Claude Code and Copilot among roughly thirty agents, writing each one's command and instruction files for you so the same spec drives all three.
The flow is four slash commands, run inside whichever agent you are using:
specify init my-project # scaffold, pick your agent(s)
/specify Build a partial-refund API for captured charges…
/plan TypeScript, Postgres ledger, Stripe fixtures in tests
/tasks # break the plan into ordered, independently testable tasks
/implement # execute the tasks, with review between steps
Spec Kit's value is that /specify and /plan produce artifacts that live in the repo and are the same regardless of which agent runs /implement. That is exactly the discipline this whole post is about: one spec, generated down into each tool's format, rather than three hand-written files you hope stay aligned. It does not, however, decide who approved the spec — and on a team that is the part that matters.
Where this breaks on a team — and across repos
Everything above is a file-layout problem, and on a solo project a tidy AGENTS.md may be the whole answer. On a team, two harder problems appear that no instruction file solves: the spec has to be one approved artifact rather than whatever a given developer has in their working tree, and it has to stay coherent across every repo the feature spans. The refund example touched one service of six — the real feature lives in a payments API, a ledger service, a webhook handler, and a frontend, each its own repo with its own AGENTS.md.
Copy a spec into six repos and you have six specs the day someone edits one. This is the same seam that opens up across the whole agentic SDLC: the plan is easy to write and hard to keep true as work fans out into Jira, Linear, and three different coding agents. Closing it takes a layer the per-tool files can't provide — one approved plan, grounded in what the code actually contains today, that stays the source of truth as it flows into each repo and each agent. That connective layer is what Enact is built for: product and engineering approve one plan together, and that approval travels with the work instead of being re-typed into AGENTS.md six times.
So the practical sequence is: write the spec once as AGENTS.md, bridge Claude Code with an import, keep each tool's file thin and scoped, and lean on Spec Kit to generate rather than hand-maintain. Then, the moment more than one person or more than one repo is involved, stop treating the spec as a file and start treating it as an approved artifact — because three agents reading one Markdown file is easy, and three teams agreeing on what that file should say is the actual work.
One approved plan. Every agent. Every repo.
See how Enact keeps a single approved spec true across Cursor, Claude Code, Copilot — and every repo they touch.
Watch the demo →