Przejdź do głównej zawartości

Jedno źródło reguł dla każdego agenta: AGENTS.md, Ruler i rulesync

Synchronizacja reguł to utrzymywanie jednego źródła instrukcji, które czytają agenci, tak aby Claude Code, Codex i Cursor używali tych samych komend budowania i tych samych konwencji. Przy zwykłych regułach wystarczy AGENTS.md importowany z jednolinijkowego CLAUDE.md. Ruler i rulesync generują plik każdego agenta z jednego źródła, gdy synchronizujesz też serwery MCP, skille albo więcej agentów.

Twoje repozytorium ma 140-linijkowy CLAUDE.md, o który dbają użytkownicy Claude Code, AGENTS.md napisany wiosną dla Codeksa i katalog .cursor/rules/, którego nikt od dawna nie otwierał. W zeszłym tygodniu komenda testów zmieniła się z npm test na pnpm test:unit. Poprawkę dostał tylko CLAUDE.md, więc sesje Codeksa i Cursora nadal uruchamiają starą komendę, dostają błąd i „naprawiają” go po swojemu.

Ta strona jest dla programisty albo tech leada, który odpowiada za konfigurację agentów w takim repozytorium. Zakłada, że wiesz już, co powinno trafić do pliku reguł (zob. AGENTS.md i CLAUDE.md: zwięzły kontekst repozytorium). Najpierw pokazuje konfigurację bez żadnego narzędzia, potem rulesync i Rulera z komendami, które uruchomiliśmy 2026-09-26, a na końcu zadanie CI, które blokuje pull request, gdy wygenerowane pliki rozjadą się ze źródłem.

  • Tabelę, który plik czyta każdy agent, łącznie z regułą Claude Code, na której potyka się większość zespołów: AGENTS.md jest pomijany, gdy istnieje CLAUDE.md.
  • Konfigurację bez zależności: AGENTS.md plus jednolinijkowy import @AGENTS.md.
  • Pełną migrację na rulesync: import → edycja → generate --targets claudecode,codexcli,cursor.
  • Odpowiednik w Rulerze i domyślne ustawienie, które ukrywa jego wynik przed Gitem.
  • Zadanie GitHub Actions, które blokuje pull request, gdy ktoś ręcznie zmieni wygenerowany plik.
  • Miejsce, w które u każdego agenta trafia reguła zawężona ścieżką, łącznie z jedynym agentem, który gubi zakres.
  • Trzy prompty do skopiowania: scalenie rozproszonych reguł w jeden plik, migracja repozytorium na rulesync i dowód, że każdy agent wczytał reguły.

Każdy agent ma swój natywny plik. Problem synchronizacji bierze się właśnie z tych różnic.

AgentNatywny plikCzyta AGENTS.md?Szczegół, który ma znaczenie
Claude CodeCLAUDE.md, .claude/CLAUDE.md, CLAUDE.local.mdTylko gdy żaden z tych trzech plików nie istnieje w katalogu roboczym ani wyżej (v2.1.277, kanał latest)Gdy są oba pliki, Claude Code czyta tylko CLAUDE.md, chyba że zaimportujesz z niego AGENTS.md
CodexAGENTS.mdTak, natywnieOd 0.150.0 niezaufany projekt nie dostarcza swojego AGENTS.md; project_doc_max_bytes ma w kodzie Codeksa domyślnie 32768 bajtów (32 KiB), a treść ponad limit jest ucinana
CursorReguły projektu w .cursor/rules/Niezweryfikowane 2026-09-26rulesync zapisuje .cursor/rules/overview.mdc; Ruler dla identyfikatora cursor zapisuje tylko AGENTS.md

Trzy szczegóły z dokumentacji pamięci Claude Code zmieniają konfigurację:

  • Domyślnie działa zasada „albo, albo”. Ustawienie Project instructions w /config ma domyślnie wartość claude-md-or-agents-md. claude-md-and-agents-md wczytuje oba pliki, claude-md ignoruje AGENTS.md, a managed-only pomija wszystkie pliki projektu.
  • Repozytorium nie przełączy tego ustawienia za zespół. Wartość trafia pod wpis wbudowanej wtyczki agents-md w pluginConfigs, a Claude Code ignoruje ją w ustawieniach projektu i ustawieniach lokalnych. Czyta ją z ~/.claude/settings.json, z pliku --settings albo z ustawień zarządzanych.
  • Obsługa AGENTS.md zależy od kanału wydań. 2026-09-26 kanał stable ma v2.1.274, starszą niż v2.1.277. Osoba z zespołu na stable nie dostaje w ogóle zastępczego wczytania AGENTS.md; dociera do niej tylko import. Sesje przez Amazon Bedrock, Google Cloud, Foundry, bramki LLM i sesje z wyłączoną telemetrią dostały tę obsługę dopiero w v2.1.281.

Samo AGENTS.md wystarcza więc repozytorium, które nie ma CLAUDE.md, i zespołowi, który w całości siedzi na latest. We wszystkich innych przypadkach użyj importu.

Czy w ogóle potrzebujesz narzędzia do synchronizacji?

Dział zatytułowany „Czy w ogóle potrzebujesz narzędzia do synchronizacji?”

Zacznij od najmniejszej konfiguracji, która obsłuży twoich agentów, a generator dodaj dopiero wtedy, gdy pasuje któryś wiersz poniżej.

Twoja sytuacjaUżyjDlaczego
Claude Code i Codex, zwykłe reguły w MarkdownieAGENTS.md + @AGENTS.md w CLAUDE.mdNie ma generatora, o którego uruchomieniu można zapomnieć; jeden plik, dwóch agentów
Potrzebujesz też plików .cursor/rules/*.mdc dla Cursora, reguł zawężonych globami albo pliku instrukcji CopilotarulesyncZapisuje natywny format reguł każdego narzędzia z jednego źródła
Chcesz mieć te same serwery MCP, skille, subagentów, hooki albo uprawnienia w każdym agencierulesyncJego funkcje obejmują rules, mcp, subagents, commands, skills, hooks, permissions
Pięciu lub więcej agentów, reguły jako sklejany Markdown, minimum konfiguracjiRulerPonad 30 identyfikatorów agentów; jeden katalog plików Markdown sklejany do pliku każdego agenta
Tylko jeden agentJego natywny plikWarstwa synchronizacji dokłada ruchomą część i nic nie daje

Tę konfigurację wypróbuj najpierw. AGENTS.md jest źródłem prawdy, a CLAUDE.md to jedna linijka plus to, czego potrzebuje wyłącznie Claude Code.

  1. Przenieś wspólne reguły do AGENTS.md w katalogu głównym repozytorium. Trzymaj tam komendy budowania i testów, konwencje oraz reguły typu „nigdy nie rób X”. Scalanie wykona za ciebie prompt pod tymi krokami.

  2. Zastąp CLAUDE.md importem:

    @AGENTS.md
    ## Claude Code only
    - Use the Explore subagent before editing more than three files.

    Claude Code rozwija importy @path przy starcie: najpierw czyta importowany plik, potem resztę CLAUDE.md. Ścieżki względne liczą się od pliku, który zawiera import, a importy zagnieżdżają się maksymalnie na cztery poziomy. @path w backtickach albo w bloku kodu zostaje zwykłym tekstem.

  3. Sprawdź, czy każdy agent wczytał reguły.

    Uruchom nową sesję, wpisz /context i sprawdź, czy CLAUDE.md jest w sekcji Memory files. Import nigdy nie wczyta AGENTS.md dwa razy, niezależnie od wartości Project instructions.

Dowiązanie symboliczne (ln -s AGENTS.md CLAUDE.md) też działa, ale według dokumentacji Claude Code ma dwa koszty: narzędzia Edit i Write odmawiają zapisu przez dowiązanie, a klon na Windowsie bez core.symlinks dostaje zamiast niego jednolinijkowy plik tekstowy. W zespole z różnymi systemami wybierz import.

Synchronizuj reguły do każdego agenta za pomocą rulesync

Dział zatytułowany „Synchronizuj reguły do każdego agenta za pomocą rulesync”

rulesync trzyma źródło w .rulesync/ i zapisuje natywne pliki każdego narzędzia. Ten przykład migruje repozytorium, którego reguły są dziś w CLAUDE.md i .claude/rules/, ścieżką import → edycja → generate.

  1. Zainstaluj rulesync i przypnij wersję. Pakiet nazywa się rulesync, a identyfikatory celów to claudecode, codexcli i cursor, nie claude ani codex.

    Okno terminala
    npm install -g rulesync@21.0.0
    # albo: brew tap dyoshikawa/rulesync https://github.com/dyoshikawa/rulesync && brew install rulesync

    Instalacja jest taka sama dla każdego agenta; rulesync i Ruler to samodzielne CLI, a nie wtyczki.

    rulesync opublikował wersje główne 18, 19, 20 i 21 między 2026-09-24 a 2026-09-26 (rejestr npm), więc nieprzypięte npx rulesync może zmienić wynik między dwoma przebiegami CI.

  2. Zaimportuj to, co już masz. W repozytorium, które ma już reguły, pomiń rulesync init (zob. ostrzeżenie pod krokami).

    Okno terminala
    rulesync import --targets claudecode
    mv .rulesync/rules/CLAUDE.md .rulesync/rules/overview.md

    Zaobserwowaliśmy, że import kopiuje CLAUDE.md do .rulesync/rules/CLAUDE.md jako regułę główną, a każdy plik .claude/rules/*.md do osobnej reguły. Zmiana nazwy jest opcjonalna; bez niej plik dla Cursora nazywa się CLAUDE.mdc.

  3. Napisz minimalny rulesync.jsonc w katalogu głównym repozytorium, żeby każda kolejna komenda, łącznie z testem w CI, obywała się bez flag:

    {
    "$schema": "https://github.com/dyoshikawa/rulesync/releases/latest/download/config-schema.json",
    "targets": ["claudecode", "codexcli", "cursor"],
    "features": ["rules"],
    "delete": false
    }

    "delete": false nie pozwala rulesync usuwać plików, których sam nie zapisał. Dodaj "mcp" do features, gdy .rulesync/mcp.jsonc będzie zawierał twoje serwery.

  4. Edytuj źródło. Reguła główna po zmianie nazwy wygląda tak:

    ---
    root: true
    targets: ["*"]
    description: "Project overview, commands and hard rules"
    globs: ["**/*"]
    ---
    # Commands
    - Install: `pnpm install --frozen-lockfile`
    - Test: `pnpm test:unit` (CI runs exactly this)
    - Typecheck: `pnpm typecheck`
    # Hard rules
    - Never bind a `Date` to D1; convert to an ISO string first.
    - Every pull request links an issue and lists the commands you ran.

    targets: ["*"] wysyła regułę do każdego narzędzia; lista identyfikatorów ją zawęża. Blok we frontmatterze, np. cursor: { alwaysApply: true }, przekazuje opcję do formatu jednego narzędzia (dokumentacja formatów plików rulesync).

  5. Wygeneruj natywne pliki, jeśli chcesz, najpierw z podglądem:

    Okno terminala
    rulesync generate --dry-run
    rulesync generate

    Zaobserwowany wynik: CLAUDE.md, AGENTS.md i .cursor/rules/overview.mdc, plus po jednym pliku na każdą regułę niegłówną (tabela niżej). rulesync wypisuje tylko pliki, których treść się zmieniła, więc zaraz po import pliki Claude Code mogą nie pojawić się na liście. rulesync doctor sprawdza konfigurację w trybie tylko do odczytu.

  6. Zacommituj razem .rulesync/, rulesync.jsonc i wygenerowane pliki. Zacommitowany wynik widzą zadania Codex w chmurze, boty do review i świeży klon, bez uruchamiania rulesync.

Gdzie u każdego agenta trafia reguła zawężona ścieżką?

Dział zatytułowany „Gdzie u każdego agenta trafia reguła zawężona ścieżką?”

Reguła główna wczytuje się wszędzie. Agenci różnią się przy regule niegłównej z globs, a tego szczegółu README rulesync nie rozpisuje. Wygenerowaliśmy taką regułę i przeczytaliśmy wynik:

---
root: false
targets: ["*"]
globs: ["src/billing/**"]
---
Billing: amounts are integer cents.
AgentZaobserwowany wynik (rulesync 21.0.0)Czy zakres zostaje?
Claude Code.claude/rules/billing.md z paths: [src/billing/**]Tak: wczytuje się, gdy Claude czyta pasujący plik
Cursor.cursor/rules/billing.mdc z globs: src/billing/**Zakres jest w pliku; tego, jak Cursor go stosuje, nie zweryfikowaliśmy (cursor.com niedostępny)
CodexTreść reguły doklejona do głównego AGENTS.mdNie: wczytuje ją każda sesja Codeksa i liczy się do budżetu 32 KiB

Każda reguła zawężona ścieżką kosztuje więc Codeksa kontekst w każdej sesji. Dla monorepo dokumentacja formatów plików rulesync opisuje opcję agentsmd.subprojectPath, która zapisuje osobny, zagnieżdżony AGENTS.md dla każdego pakietu; tej opcji nie uruchamialiśmy.

Co dostaje każdy agent i jak to potwierdzić:

CLAUDE.md w katalogu głównym i reguły zawężone w .claude/rules/. Skoro CLAUDE.md istnieje, domyślny tryb Project instructions ignoruje wygenerowany AGENTS.md, więc reguły wczytują się raz. Potwierdź przez /context w sekcji Memory files. Nie przełączaj tu na claude-md-and-agents-md: te same reguły wczytałyby się dwa razy.

Drugi prompt uruchamiaj w świeżej sesji każdego agenta po każdej zmianie reguł. Agent, który odpowiada „not loaded” albo najpierw czyta plik, nie dostał reguł przy starcie.

Ruler skleja Markdown z .ruler/ i zapisuje go do pliku każdego agenta. Pakiet to @intellectronica/ruler; ruler w npm to niezwiązana biblioteka asercji, ostatnio wydana w 2013 roku.

Okno terminala
npm install -g @intellectronica/ruler@0.3.44 # Node.js ^20.19, ^22.12 lub >=23 (pole engines pakietu)
ruler init # tworzy .ruler/AGENTS.md i .ruler/ruler.toml
ruler apply --agents claude,codex,cursor # zapisuje CLAUDE.md i AGENTS.md oraz edytuje .gitignore
ruler revert # przywraca pliki .bak i usuwa wygenerowane pliki

Identyfikatory agentów w Rulerze to claude, codex i cursor, więc komenda rulesync wklejona do Rulera nie zadziała, i odwrotnie.

Przed wdrożeniem warto znać jeszcze dwa zachowania. Ruler czyta AGENTS.md z katalogu głównego repozytorium jako pierwszy, przed .ruler/AGENTS.md, więc wygenerowany główny AGENTS.md wraca do źródła przy następnym apply, jeśli nie jest ignorowany. Ostatnie wydanie w npm to 0.3.44 z 2026-06-30, choć do repozytorium trafił commit 2026-09-23.

rulesync 21.0.0Ruler 0.3.44
Źródło.rulesync/ + rulesync.jsonc.ruler/*.md + ruler.toml
Identyfikatory Claude Code / Codex / Cursorclaudecode, codexcli, cursorclaude, codex, cursor
Wynik dla Cursora.cursor/rules/*.mdcAGENTS.md
Poza regułamiMCP, skille, subagenci, komendy, hooki, uprawnieniaMCP, skille, subagenci
Domyślnie w GicieDecydujesz ty; rulesync gitignore dodaje wpisy na żądanieDodaje wygenerowane pliki do .gitignore
Reguły zawężoneNatywnie w każdym narzędziu; dla Codeksa doklejane do AGENTS.mdSklejane do jednego pliku każdego agenta
Wykrywanie rozjazdugenerate --check, kod wyjścia 1 przy rozjeździe (uruchomiliśmy)Brak flagi w apply --help; użyj git diff
Tempo wydańCztery wersje główne w trzy dni (wrzesień 2026)Ostatnie wydanie w npm 2026-06-30

Popularność na 2026-09-26 (GitHub search API, nasz przegląd): agentsmd/agents.md ma 24 617 gwiazdek, intellectronica/ruler 2934, dyoshikawa/rulesync 1474. Strona agents.md podaje, że format jest „used by over 60k open-source projects”. Oba narzędzia do synchronizacji rozwija jedna osoba; gwiazdki mierzą zainteresowanie, a nie niezawodność.

Generator pomaga tylko wtedy, gdy nikt ręcznie nie edytuje jego wyniku. To zadanie uruchamia się przy każdym pull requeście, który dotyka reguł, i kończy się błędem, gdy zacommitowane pliki różnią się od tego, co generuje źródło. Używa wyzwalacza pull_request, nie ma żadnych sekretów i potrzebuje tylko prawa odczytu.

.github/workflows/rules-drift.yml
name: rules-drift
on:
pull_request:
paths:
- ".rulesync/**"
- "rulesync.jsonc"
- "CLAUDE.md"
- "AGENTS.md"
- ".claude/rules/**"
- ".cursor/rules/**"
- ".github/workflows/rules-drift.yml"
permissions:
contents: read
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version: 22
- name: Generated rules match .rulesync/
run: npx -y rulesync@21.0.0 generate --check

--check bierze cele i funkcje z rulesync.jsonc, niczego nie zapisuje i kończy się kodem 1, gdy wygenerowany plik by się zmienił. W naszym teście jedna linijka dopisana ręcznie do AGENTS.md dała komunikat Files are not up to date. Run 'rulesync generate' to update. i kod wyjścia 1; nietknięte repozytorium dało ✓ All files are up to date. i kod 0.

Jeśli ustawisz to zadanie jako wymagany check, usuń filtr paths:: GitHub zostawia wymagany check w stanie oczekiwania na każdym pull requeście pominiętym przez filtr, a takiego pull requesta nie da się scalić.

Dla czytelności przykład przypina actions/checkout i actions/setup-node tagiem v4. Tag można przesunąć, więc na chronionej gałęzi przypnij każdą akcję pełnym SHA commita, z wersją w komentarzu na końcu linii.

Drugi wzorzec działa z każdym generatorem, także z Rulerem. To nasza propozycja, a nie funkcja któregokolwiek z narzędzi: wygeneruj pliki ponownie i pozwól rozstrzygnąć Gitowi.

- name: Generated rules match the source (git variant)
run: |
npx -y rulesync@21.0.0 generate
git diff --exit-code -- CLAUDE.md AGENTS.md .claude/rules .cursor/rules
test -z "$(git status --porcelain -- CLAUDE.md AGENTS.md .claude/rules .cursor/rules)"

Ostatnia linia łapie nowy, nieśledzony wygenerowany plik, którego sam git diff nie widzi. Dla Rulera zastąp pierwszą linię komendą npx -y @intellectronica/ruler@0.3.44 apply --agents claude,codex,cursor --no-gitignore. Dodaj wpis w CODEOWNERS dla .rulesync/ (albo .ruler/), żeby właściciel reguł zatwierdzał każdą zmianę źródła.

Skąd wiesz, że agenci stosują zsynchronizowane reguły?

Dział zatytułowany „Skąd wiesz, że agenci stosują zsynchronizowane reguły?”

Zielony test rozjazdu dowodzi, że pliki się zgadzają. Nie dowodzi, że którykolwiek agent ich przestrzega. Sprawdzaj zachowanie w trzech warstwach, od najtańszej:

  1. Test wczytania. Prompt weryfikacyjny powyżej, w świeżej sesji każdego agenta, po każdej zmianie reguł. Uruchamia go właściciel reguł i wkleja trzy odpowiedzi do pull requesta.
  2. To, co ważne, egzekwuj w kodzie, nie w prozie. Reguły to kontekst, a nie egzekwowanie; dokumentacja pamięci Claude Code nazywa je wprost „context rather than enforced configuration”. „Testy muszą przechodzić” wstaw do CI i hooka pre-commit; tekst reguły zostaw jako wyjaśnienie.
  3. Zmierz zmianę reguł, zanim ją wdrożysz. Uruchom stały zestaw zadań na starych i nowych regułach i porównaj odsetek zaliczonych, jak w ewaluacji zmian w CLAUDE.md.

Tech lead zatwierdza zmianę źródła; CI zatwierdza wygenerowane pliki.

Każda linijka głównego pliku reguł trafia do każdej sesji każdego agenta przed pierwszym promptem. Dokumentacja Claude Code zaleca poniżej 200 linijek na CLAUDE.md, bo dłuższe pliki zużywają więcej kontekstu i obniżają przestrzeganie reguł. Codex ucina dokumentację projektu na project_doc_max_bytes (w kodzie domyślnie 32768 bajtów), więc traci reguły z końca długiego wygenerowanego AGENTS.md, czyli dokładnie stamtąd, gdzie rulesync dokleja reguły zawężone. Importy nie zmniejszają kosztu: @AGENTS.md wczytuje się przy starcie tak samo jak sam plik. Narzędzie do synchronizacji oszczędza duplikację, nie tokeny. Żeby ograniczyć tokeny w Claude Code i Cursorze, przenieś reguły dla konkretnych typów plików do reguł zawężonych globami (globs: w rulesync); w Codeksie użyj zagnieżdżonych plików AGENTS.md, które Codex skleja od katalogu głównego projektu w dół do katalogu, w którym startuje (kod źródłowy Codeksa, 2026-09-26). Potem skorzystaj z poradnika odchudzania plików kontekstu.

Co się psuje przy synchronizacji reguł między agentami?

Dział zatytułowany „Co się psuje przy synchronizacji reguł między agentami?”

Codex stosuje stare reguły po edycji. Objaw: AGENTS.md się zmienił, a Codex uruchamia starą komendę testów. Przyczyna: ktoś zmienił CLAUDE.md albo źródło i nie wygenerował plików ponownie, albo projekt jest w Codeksie niezaufany. Naprawa: uruchom rulesync generate, zacommituj, dodaj zadanie wykrywające rozjazd i oznacz projekt jako zaufany.

Claude Code ignoruje AGENTS.md u jednej osoby. Objaw: prompt weryfikacyjny odpowiada „not loaded” tylko na jednym komputerze. Przyczyna: CLAUDE.local.md albo .claude/CLAUDE.md na ścieżce, kanał stable (v2.1.274 na 2026-09-26) albo Project instructions ustawione na claude-md. Naprawa: dodaj import @AGENTS.md do zacommitowanego CLAUDE.md; działa na każdym kanale i przy każdym ustawieniu poza managed-only.

Reguły wczytują się dwa razy. Objaw: /context pokazuje w sekcji Memory files zarówno CLAUDE.md, jak i AGENTS.md, z tą samą treścią. Przyczyna: generator zapisał identyczną treść do obu plików, a użytkownik wybrał claude-md-and-agents-md. Naprawa: wróć do trybu domyślnego albo generuj CLAUDE.md jako jednolinijkowy import.

Ręczna poprawka znika. Objaw: poprawki w CLAUDE.md nie ma po następnym generate. Przyczyna: wygenerowane pliki to wynik; generate nadpisuje je ze źródła. Naprawa: edytuj .rulesync/rules/. Zacznij treść reguły głównej od <!-- Generated from .rulesync/rules/. Edit there. -->; w naszym teście rulesync skopiował tę linię na początek CLAUDE.md i AGENTS.md, więc ludzie i agenci widzą, gdzie jest źródło.

Ręcznie pisane reguły znikają po pierwszym generate. Objaw: nie ma plików z .claude/rules/ albo .cursor/rules/, których nikt nie zaimportował. Przyczyna: "delete": true z rulesync init albo flaga --delete. Naprawa: przywróć je przez git checkout -- .claude/rules .cursor/rules, uruchom rulesync import dla każdego narzędzia, do którego należą, i ustaw "delete": false.

Recenzenci i agenci w chmurze nie widzą reguł. Objaw: reguły działają lokalnie, ale zadanie Codex w chmurze albo bot do review je ignoruje. Przyczyna: domyślny blok .gitignore Rulera albo rulesync gitignore. Naprawa: usuń te wpisy, zacommituj wynik i zostaw test rozjazdu.

Aktualizacja rulesync zmienia wynik. Objaw: zadanie wykrywające rozjazd pada na pierwszym pull requeście z regułami po tym, jak ktoś podbił przypiętą wersję. Przyczyna: nieprzypięta albo podniesiona wersja główna. Naprawa: przypnij tę samą wersję lokalnie i w CI, a podbijaj ją w osobnym pull requeście razem z ponownie wygenerowanymi plikami.