Two weeks ago I wrote about the standards war 3,000 people are upvoting — the slow-motion fight between AGENTS.md, the open spec backed by six vendors and the Linux Foundation, and CLAUDE.md, the file Claude Code reads. The piece ended with what I called the doctrine: write to the open standard, alias to the proprietary one for compatibility, and wait for the holdout to relent.

One sentence. Sounded clean. And then I sat down to actually do it across the dozen Kurka Labs repos and discovered the embarrassing thing.

I wasn't doing it cleanly myself.

The bit you actually have to do

Here is the dual-naming pattern as a list of files:

FilePurposeReads
AGENTS.mdCanonical, hand-edited.Cursor, Codex, Amp, Factory, OpenCode, Aider, Gemini CLI
CLAUDE.mdOne line: @AGENTS.md.Claude Code resolves the import natively.
.github/copilot-instructions.mdByte-identical mirror of AGENTS.md.GitHub Copilot, which has neither imports nor a way to read AGENTS.md directly.

Three real files. One source of truth. The CLAUDE.md stub is one character of compatibility hack. The Copilot mirror is regenerated on demand and checked for drift.

The trouble is in the words "regenerated on demand" and "checked for drift." Last time I needed to update one of these, here is what I did, in actual order:

That is not the doctrine working. That is three separate copies drifting in three different sessions, and me playing referee.

Why a CLI

The community workaround you'll find on Hacker News and in a half-dozen GitHub gists is symlinks. Make AGENTS.md the real file. Symlink CLAUDE.md and copilot-instructions.md to it. One file in fact, three filenames in ls. Elegant on paper.

It is the right answer on Mac and Linux. It falls apart on Windows the moment you try to use it.

Symlinks on Windows want git config core.symlinks=true per repo. They want admin privileges to create. They want a team that never zips and unzips the repo through Dropbox or OneDrive, because the unzip turns the symlink into a tiny text file containing the path it used to point to. They want every developer to have configured the same flags before the first checkout. The maintenance footprint is bigger than the problem.

The other workaround is — and I have done this — copy-paste with discipline. Edit AGENTS.md. Open copilot-instructions.md. Select all. Replace. Save. Pretend you'll remember to do it next time. You won't. Nobody does.

What I wanted was something a notch above both: a 7 KB Node script with zero dependencies that runs anywhere Node 18 runs, treats AGENTS.md as the canonical file, and does the dual-naming dance for me. So I wrote it.

What it does

It's called agents-bridge. Four commands. Each one corresponds to one thing you actually want to do.

init — you're starting fresh. Run it in a repo that has none of the three files yet. You get an AGENTS.md from a small starter template, a CLAUDE.md stub that's just @AGENTS.md, and a .github/copilot-instructions.md byte-identical mirror.

npm i -g @kurkalabs/agents-bridge
agents-bridge init

sync — you've edited AGENTS.md by hand and want the Copilot mirror updated. This is the daily-driver command. It also fixes the CLAUDE.md stub if someone deleted it or replaced its single line with something else.

agents-bridge sync

doctor — you want to know if the three files are consistent right now. Returns non-zero exit code on drift, so it works as a CI gate or pre-commit hook. This is the one I run from CI on every push.

agents-bridge doctor

migrate — you have an existing CLAUDE.md you've been hand-editing for months. You want to flip the canonical to AGENTS.md without losing what's already there. Migrate moves the existing CLAUDE.md content into a fresh AGENTS.md, replaces CLAUDE.md with the one-line @AGENTS.md stub, and writes the Copilot mirror.

agents-bridge migrate

Three constraints I cared about

No dependencies. The whole CLI is one Node file. There is no node_modules directory in the package, because there are no dependencies to install. npm install -g @kurkalabs/agents-bridge downloads the script and the README. That's it. The runtime is whatever Node binary you already have.

Mirrors are byte-identical, never paraphrased. The doctor command does an exact-match check between AGENTS.md and the Copilot mirror. If you need agent-specific rules, put them in agent-specific places — .claude/skills/, .cursor/rules/, the AGENTS.override.md pattern Codex supports natively. Don't put them in the shared file. The whole point of the bridge is that the shared file is shared.

Cross-platform without ceremony. No chmod +x dance. No core.symlinks=true. No "works on my Mac, breaks on the new Windows hire's machine" mystery. Three files, one Node script, every OS the same.

The CI bit

This is the part I think pays for itself fastest. Add a doctor check to your pipeline:

name: agents-bridge doctor
on: [push, pull_request]
jobs:
  doctor:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - run: npx @kurkalabs/agents-bridge doctor

The first PR that edits AGENTS.md and forgets to sync the Copilot mirror fails its check. The contributor sees the diff. They run agents-bridge sync, push again, the check goes green. Drift is caught at the moment of introduction, not three weeks later when somebody asks why Copilot is suggesting different naming conventions than Claude Code is.

What it doesn't do

It doesn't try to be clever. It doesn't merge agent-specific rule files into the canonical AGENTS.md, because the whole reason agents have separate rule directories (.cursor/rules/, .claude/skills/) is that some rules are agent-specific and don't belong in a shared file.

It doesn't try to detect when you "really meant" to edit a different file. If you edit the Copilot mirror by mistake instead of AGENTS.md, the next doctor run will tell you the mirror has drifted. sync will then overwrite your accidental edit with the canonical. The CLI is opinionated about which file is the source of truth, and not apologetic about it.

It doesn't yet support every coding agent in the AGENTS.md ecosystem — Cursor's .cursor/rules/main.mdc mirror is on the list, as is a more elaborate symlink-emitter for teams that genuinely want symlinks on the Mac/Linux subset of their fleet. Adding a new mirror target is roughly a dozen lines of Node.

The bigger pattern

This is a kit that competes with its own obsolescence, on purpose. The day Anthropic ships native AGENTS.md support in Claude Code — and they will, the upvote pressure on that GitHub issue is now four months old and growing — the CLAUDE.md stub stops being necessary. Run agents-bridge sync, watch it flag the stub as redundant, delete it, you're down to two files. The Copilot mirror still earns its keep because Copilot still has its own filename and no import system, but the dual-naming dance for Claude Code is gone.

That is the right shape for a tool built to live in a moment. The kit family at Kurka Labs is now three pieces: agentsmd-kit for the people who want a starter AGENTS.md with the open-spec patterns baked in, claudemd-kit for the people who want the deeper Claude Code system with skills and custom commands, and agents-bridge for the people who want both, today, in the same repo, without thinking about it.

Each one solves a specific moment in the standards split. The split won't last forever. Neither should the kits, and that's fine. The job of an honest tool, in an in-between moment, is to make the in-between cheap.


Source on GitHub. Published on npm as @kurkalabs/agents-bridge. MIT, no dependencies, ~280 lines of Node.

Frank Kurka — Founder of Kurka Labs. Building the cognitive layer above existing AI infrastructure. Companion piece: the standards war 3,000 people are upvoting.