Praca z wieloma repozytoriami w Cursorze
Praca z wieloma repozytoriami w Cursorze polega na tym, by Agent widział kontrakty innych repozytoriów, a granice własności pozostały wyraźne. Repozytoria zmieniane razem otwiera się jako jeden workspace z wieloma folderami, z repozytoriów tylko konsumowanych trzyma się przypięte migawki kontraktów, a każda zmiana obejmująca kilka repozytoriów zaczyna się od kontraktu i przechodzi przez CI każdego z nich.
Ta strona jest dla programistów i tech leadów, których serwisy są w osobnych repozytoriach. Masz dodać phoneNumber do profilu użytkownika. Zmiana dotyka shared-types, user-service, schematu bramki API i dwóch frontendów. Otwierasz Cursora w user-service, Agent nie widzi wspólnych typów, więc wymyśla UserDto, który prawie się zgadza. Trzy PR-y później aplikacja webowa kompiluje się względem pola, którego API nigdy nie zwraca.
Źródła tej strony, sprawdzone 2026-09-26: ładowanie wielu folderów i format plików reguł sprawdziliśmy w runtime agenta dołączonym do własnego pakietu Cursora @cursor/sdk 1.0.32. Jego opcja dirs dla lokalnego agenta jest opisana jako „Additional / multi-root workspace folders”, z których „project rules, skills, and request-context workspace metadata load from every unique path”. Adresy serwera GitHub MCP pochodzą z dokumentacji github-mcp-server. Polecenia openapi-typescript 7.13.0 i @graphql-inspector/cli 7.0.0 uruchomiliśmy lokalnie. Z naszego środowiska nie było dostępu do cursor.com, więc nazwy menu porównaj z własną wersją Cursora 3.x.
Co daje ci ta konfiguracja wielu repozytoriów
Dział zatytułowany „Co daje ci ta konfiguracja wielu repozytoriów”- Tabelę decyzyjną: które repozytoria otworzyć, które trzymać jako migawkę, a które czytać przez MCP.
- Wersjonowane repozytorium workspace’u z plikiem
.code-workspacei jedną regułą własności, którą ładuje każda sesja agenta. - Kontrolę dryfu, która zatrzymuje CI, gdy dołączony kontrakt przestaje zgadzać się z wygenerowanymi typami, oraz zaplanowane sprawdzenie, które kończy się błędem, gdy upstream opublikuje nowszy tag kontraktu.
- Kolejność pracy „najpierw kontrakt” z czterema promptami do skopiowania: planowanie, producent, konsumenci i sprawdzenie workspace’u.
- Tabelę dowodów, dzięki której recenzent zatwierdza pięć powiązanych PR-ów po przeczytaniu jednego diffu kontraktu, a nie każdej wygenerowanej linii.
Które podejście do wielu repozytoriów pasuje do twoich repozytoriów?
Dział zatytułowany „Które podejście do wielu repozytoriów pasuje do twoich repozytoriów?”Agent dobrze radzi sobie z tym, co może otworzyć, a słabo z tym, co musi zgadywać. Zasada: otwieraj to, co edytujesz; z tego, co tylko czytasz, trzymaj migawkę.
| Twoja sytuacja | Co dajesz Agentowi | Dlaczego |
|---|---|---|
| Zmieniasz razem od dwóch do czterech repozytoriów i wszystkie są twoje | Workspace z wieloma folderami | Agent czyta i edytuje prawdziwy kod, a reguły ładują się z każdego folderu |
| Korzystasz z serwisu innego zespołu i nigdy go nie edytujesz | Przypiętą migawkę kontraktu i regułę, która na nią wskazuje | Agent widzi dokładny kontrakt, a zaplanowane sprawdzenie mówi ci, kiedy upstream opublikuje nowszy tag |
| Od czasu do czasu musisz coś sprawdzić w repozytorium, którego nie klonujesz | Serwer GitHub MCP w trybie tylko do odczytu | Bez klonowania, bez prawa zapisu, jedno zapytanie naraz |
| Wszystkie serwisy są w jednym repozytorium | Nie ta strona | Zobacz strategie dla dużych baz kodu w Cursorze i pracę z monorepo |
Przewodnik po mikroserwisach w Cursorze omawia granice serwisów i reguły topologii. Ta strona omawia mechanikę, która pojawia się dopiero wtedy, gdy kod jest rozdzielony między repozytoria.
Skonfiguruj workspace z wieloma folderami dla repozytoriów zmienianych razem
Dział zatytułowany „Skonfiguruj workspace z wieloma folderami dla repozytoriów zmienianych razem”Cursor otwiera pliki .code-workspace z VS Code. Umieść taki plik we własnym, małym repozytorium, żeby lista folderów i reguła własności były wersjonowane, recenzowane i wspólne dla całego zespołu.
-
Sklonuj repozytoria obok siebie i utwórz obok nich repozytorium workspace’u:
~/src/acme/├── platform-workspace/ # nowe: plik workspace'u + reguła dla całego workspace'u├── shared-types/├── user-service/├── api-gateway/└── web-app/ -
Zapisz
platform-workspace/platform.code-workspace. Ścieżki są względne wobec pliku workspace’u, anameto etykieta każdego folderu, którą widzisz ty i Agent:{"folders": [{ "path": ".", "name": "platform-workspace" },{ "path": "../shared-types", "name": "shared-types" },{ "path": "../user-service", "name": "user-service" },{ "path": "../api-gateway", "name": "api-gateway" },{ "path": "../web-app", "name": "web-app" }],"settings": {"search.exclude": { "**/node_modules": true, "**/dist": true }}} -
Dodaj
.cursorignoredo każdego repozytorium, żeby artefakty buildu i wygenerowane paczki nie trafiały do kontekstu Agenta:dist/build/coverage/*.min.js -
Otwórz plik przez File › Open Workspace from File, a potem uruchom poniższy prompt sprawdzający w nowym czacie Agenta.
Jeśli w tabeli brakuje folderu, ścieżka w pliku workspace’u jest błędna. Nie polegaj na samej liście reguł, bo Agent może błędnie podać, co ma załadowane. Obserwowalnym sprawdzeniem jest cytat: jeśli odpowiedź parafrazuje linię „Dependency direction:” albo ją pomija, reguła nie jest załadowana. Jeśli brakuje reguły, sprawdź, czy leży w .cursor/rules/ i ma rozszerzenie .mdc: runtime ładuje reguły projektu z .cursor/rules/**/*.mdc. Ostatnia odpowiedź jest ważna, bo runtime SDK ma jeden główny folder dla poleceń powłoki. Licz się z tym, że npm test uruchomi się w jednym repozytorium, jeśli Agent wcześniej nie zmieni katalogu, i pisz polecenia weryfikacji z cd albo git -C, żeby nie mogły trafić w złe miejsce.
Napisz jedną regułę, która mówi, kto czym zarządza
Dział zatytułowany „Napisz jedną regułę, która mówi, kto czym zarządza”Reguła, która kopiuje listy pól, dezaktualizuje się w tygodniu, w którym zmienia się kontrakt, a nieaktualna reguła jest gorsza niż żadna, bo Agent jej ufa. W regule zapisz własność, kierunek zależności i polecenia weryfikacji, a zamiast przepisywać kontrakty, wskaż ich pliki.
Zapisz platform-workspace/.cursor/rules/workspace-map.mdc:
---description: Ownership, dependency direction and verify commands for the platform workspacealwaysApply: true---
Repositories in this workspace and what each owns:- shared-types: the source of truth for API types. Published as @acme/shared-types.- user-service: owns the users table and /api/users. Its contract is user-service/openapi.yaml.- api-gateway: owns the public GraphQL schema in api-gateway/schema.graphql.- web-app: consumes the gateway only. It never calls user-service directly.
Dependency direction: shared-types -> user-service -> api-gateway -> web-app.A change always lands in that order. Never edit a repository to the left of theone the task names unless the task says so.
Contract rules:- Change a contract additively first (new optional field, new endpoint). Remove or rename only in a later change, after every consumer has shipped.- Read types from the contract files above. Never hand-write a copy of them.
Verify commands (run from the workspace root):- shared-types: cd ../shared-types && npm test && npx tsc --noEmit- user-service: cd ../user-service && npm test- api-gateway: cd ../api-gateway && npm test- web-app: cd ../web-app && npx tsc --noEmit && npm testProjektowanie reguł w szczegółach, w tym reguły z globs dla pojedynczych serwisów, opisują reguły projektu w Cursorze oraz własne reguły i szablony.
Trzymaj przypięte migawki repozytoriów, które tylko konsumujesz
Dział zatytułowany „Trzymaj przypięte migawki repozytoriów, które tylko konsumujesz”Gdy serwisem zarządza inny zespół, nie otwieraj jego kodu. Dołącz do repozytorium opublikowany kontrakt w otagowanej wersji, wygeneruj z niego typy i pozwól CI powiedzieć ci, kiedy migawka i typy przestają się zgadzać albo kiedy upstream idzie dalej.
# scripts/sync-contracts.sh (uruchamiasz w katalogu głównym repozytorium konsumenta)set -euo pipefailTAG="${1:?usage: sync-contracts.sh <user-service tag>}"gh api "repos/acme/user-service/contents/openapi.yaml?ref=${TAG}" \ -H "Accept: application/vnd.github.raw+json" > contracts/user-service.openapi.yamlecho "${TAG}" > contracts/user-service.versionnpx openapi-typescript contracts/user-service.openapi.yaml -o src/generated/user-service.tsBramka w CI to dwa polecenia. --check kończy się kodem 1 i wypisuje „Generated types are not up-to-date!”, gdy ktoś ręcznie zmieni migawkę albo wygenerowany plik. Sprawdzenie typów potwierdza potem, że kod klienta nadal kompiluje się względem kontraktu:
npx openapi-typescript contracts/user-service.openapi.yaml -o src/generated/user-service.ts --checknpx tsc --noEmitTa bramka porównuje tylko dołączoną migawkę z wygenerowanymi z niej typami. Nigdy nie zagląda do samego user-service, więc nowy tag w upstreamie przechodzi niezauważony. Dryf względem upstreamu wyłapuj osobnym zadaniem uruchamianym według harmonogramu (codzienny cron w CI), które porównuje przypięty tag z najnowszym wydaniem:
latest=$(gh release view --repo acme/user-service --json tagName -q .tagName)[ "$latest" = "$(cat contracts/user-service.version)" ] || { echo "user-service $latest available"; exit 1; }W CI daj temu zadaniu GH_TOKEN z dostępem tylko do odczytu do Contents w acme/user-service (token fine-grained albo token GitHub App z twojego magazynu sekretów). Domyślny GITHUB_TOKEN nie może czytać innych repozytoriów. Nadaj workflow uprawnienia permissions: contents: read.
Gdy zadanie się nie powiedzie, uruchom scripts/sync-contracts.sh z nowym tagiem i otwórz PR. Sprawdzenie typów w tym PR-ze pokaże, co psuje nowy kontrakt.
Dodaj regułę ograniczoną do plików, .cursor/rules/consumed-contracts.mdc, żeby Agent używał wygenerowanych typów, zamiast wymyślać własne:
---description: How this repository consumes user-serviceglobs: src/clients/**/*.tsalwaysApply: false---
Types for user-service come only from src/generated/user-service.ts, which isgenerated from contracts/user-service.openapi.yaml (version incontracts/user-service.version). Never edit either file by hand.If a field you need is missing from the generated types, stop and tell me.Do not add it locally: the contract has to change upstream first.Czytaj niesklonowane repozytorium przez serwer GitHub MCP
Dział zatytułowany „Czytaj niesklonowane repozytorium przez serwer GitHub MCP”Przy jednorazowym pytaniu („jak serwis billingu podpisuje webhooki?”) klonowanie to przesada. Serwer MCP od GitHuba czyta pliki i przeszukuje kod w każdym repozytorium, do którego ma dostęp twój token. Użyj zestawu narzędzi repos w trybie tylko do odczytu, żeby sesja nie mogła pushować, komentować ani zakładać issues. Dodaj go do swojego pliku użytkownika ~/.cursor/mcp.json, a nie do pliku w repozytorium, żeby token pozostał prywatny:
{ "mcpServers": { "github-read": { "url": "https://api.githubcopilot.com/mcp/x/repos/readonly", "headers": { "Authorization": "Bearer ${env:GITHUB_READ_TOKEN}" } } }}Utwórz GITHUB_READ_TOKEN jako szczegółowy (fine-grained) personal access token z dostępem tylko do odczytu do Contents w potrzebnych repozytoriach i wyeksportuj go w powłoce, z której uruchamiasz Cursora. Odwołanie ${env:…} trzyma token poza plikiem. Wszystko, co zwraca serwer, traktuj jako niezaufane dane wejściowe: plik w innym repozytorium może zawierać instrukcje skierowane do twojego agenta, co jest kolejnym powodem, by zestaw narzędzi był tylko do odczytu. Przewodnik po serwerze GitHub MCP opisuje pozostałe zestawy narzędzi i lokalną instalację w Dockerze.
Jeśli czytasz to samo repozytorium codziennie, przestań je odpytywać. Sklonuj je i dodaj do workspace’u albo zrób migawkę jego kontraktu.
Wprowadzaj zmianę w wielu repozytoriach, zaczynając od kontraktu
Dział zatytułowany „Wprowadzaj zmianę w wielu repozytoriach, zaczynając od kontraktu”Zmiana obejmująca kilka repozytoriów psuje się w szczelinach między PR-ami, więc kolejność jest ważniejsza niż którykolwiek pojedynczy prompt. Zaplanuj całą zmianę raz, a potem implementuj ją po jednym repozytorium, każde w osobnym czacie Agenta, żeby każdy diff mieścił się w jednym PR-ze.
-
Zaplanuj w całym workspace. Przełącz czat w Plan Mode, który „creates detailed implementation plans before writing any code”, i wklej poniższy prompt planujący. Po zatwierdzeniu planu zapisz go jako
platform-workspace/plans/phone-number.md(na przykład przełącz się w tryb Agent i poproś go o zapisanie pliku), żeby każdy kolejny czat mógł się do niego odwołać. -
Zmień kontrakt addytywnie. W
shared-types(albo w pliku OpenAPI producenta) dodaj pole jako opcjonalne i opublikuj wersję przedpremierową, na przykład@acme/shared-types@2.4.0-rc.1. Przed wydaniem finalnym sprawdź ją bramką: dla pakietu TypeScript zainstaluj rc w każdym konsumencie i uruchomnpx tsc --noEmitbez zmian w kodzie. Musi przejść, bo pole opcjonalne niczego nie psuje. Dla kontraktów OpenAPI lub GraphQL uruchom diff wykrywający zmiany niekompatybilne wstecz (breaking changes) z tabeli dowodów poniżej. -
Zaimplementuj zmianę u producenta. W nowym czacie ograniczonym do
user-serviceuruchom prompt dla producenta. Jego PR łączysz, gdy jego własne CI jest zielone. -
Dostosuj każdego konsumenta. Jeden czat na konsumenta, wskazujący na wersję przedpremierową. Każdy PR konsumenta pokazuje sprawdzenie typów i testy względem nowego kontraktu.
-
Łącz w kolejności zależności, potem posprzątaj. Kontrakt, potem producent, potem konsumenci. Usunięcie albo zmiana nazwy starego kształtu to osobna zmiana, po wdrożeniu wszystkich konsumentów.
Żeby prowadzić konsumentów równolegle, trzymaj jeden czat na repozytorium. Worktrees w Cursorze „let Agent work in isolated Git checkouts” (dokumentacja Cursora, sprawdzone 2026-08-28). Worktree Gita zawsze należy do jednego repozytorium, więc Worktrees nadają się do równoległych prób w obrębie repozytorium, a nie do zmiany obejmującej kilka repozytoriów. W Agents Window obserwujesz kilka takich sesji obok siebie. Nienadzorowane uruchomienia tej samej zmiany w wielu repozytoriach opisuje strona o Cloud Agents i Automations.
Jak udowodnić, że zmiana w wielu repozytoriach działa, bez czytania każdego diffu?
Dział zatytułowany „Jak udowodnić, że zmiana w wielu repozytoriach działa, bez czytania każdego diffu?”Nikt nie powinien czytać pięciu wygenerowanych diffów linia po linii. Recenzent czyta diff kontraktu, który jest mały, a resztę przyjmuje na podstawie dowodów z CI każdego repozytorium:
| Dowód | Polecenie lub źródło | Co wyłapuje |
|---|---|---|
| Zmiana kontraktu nie jest niekompatybilna wstecz | npx @graphql-inspector/cli diff old.graphql new.graphql kończy się kodem 1 przy zmianie niekompatybilnej i 0 przy addytywnej; dla OpenAPI użyj diffu zmian niekompatybilnych z przewodnika po mikroserwisach | Usunięte albo przemianowane pole, które wślizgnęło się do kroku „addytywnego” |
| Dołączone migawki zgadzają się z wygenerowanymi typami | npx openapi-typescript … --check | Ręcznie zmienioną migawkę albo wygenerowany plik |
| Przypięty kontrakt jest najnowszy | Zaplanowane sprawdzenie gh release view opisane wyżej | Konsumenta przypiętego do nieaktualnego tagu upstreamu |
| Każdy konsument kompiluje się względem nowego kontraktu | npx tsc --noEmit w każdym konsumencie | Konsumenta, który polega na starym kształcie |
| Oczekiwania konsumentów są spełnione po stronie producenta | Testy kontraktowe sterowane przez konsumenta z @pact-foundation/pact, weryfikowane w CI producenta | Zmianę producenta, która przechodzi sprawdzenie typów, ale zwraca złe dane |
| Każde repozytorium nadal działa | Własne CI każdego PR-a, na zielono | Regresje niezwiązane z kontraktem |
Powiązane PR-y, kolejność łączenia i wynik każdej bramki umieść w opisie PR-a z kontraktem, w formacie pakietu dowodów. Zatwierdza ten, kto jest właścicielem: właściciel kontraktu (wskazany w CODEOWNERS dla pliku schematu) zatwierdza PR z kontraktem po przeczytaniu jego diffu. Właściciel każdego repozytorium zatwierdza PR swojego repozytorium na podstawie jego dowodów.
Co psuje się przy pracy z wieloma repozytoriami w Cursorze?
Dział zatytułowany „Co psuje się przy pracy z wieloma repozytoriami w Cursorze?”Agent edytuje repozytorium, którego zadanie nie wskazało. W workspace z wieloma folderami każdy folder jest zapisywalny. Przywróć zabłąkane pliki z checkpointu czatu albo przez git -C ../api-gateway restore ., a potem uruchom git -C ../api-gateway status --short i usuń nieśledzone pliki z listy (git -C ../api-gateway clean -n pokazuje podgląd, clean -f usuwa): restore przywraca tylko pliki śledzone. Potem ograniczaj czaty implementacyjne do jednego repozytorium i nazywaj dozwolony folder w pierwszej linii promptu, tak jak robią to powyższe prompty.
Test przechodzi w niewłaściwym repozytorium. Agent uruchomił npm test w głównym folderze, a nie w tym, który zmienił. Dodaj cd ../<repo> && albo git -C do każdego polecenia weryfikacji w regule i proś o kod wyjścia każdego polecenia, a nie o podsumowanie.
Reguła w ogóle się nie ładuje. Uruchom prompt sprawdzający workspace. Reguła, której nie widać, to zwykle plik .md zamiast .mdc, plik poza .cursor/rules/ albo zepsuty frontmatter.
Migawka rozjeżdża się z upstreamem. Konsument kompiluje się względem kontraktu sprzed miesiąca. Bramka --check tego nie widzi: wyłapuje tylko lokalne ręczne zmiany. Uruchom opisane wyżej zaplanowane sprawdzenie upstreamu, uruchom ponownie scripts/sync-contracts.sh z nowym tagiem i pozwól Agentowi naprawić błędy typów, które się pojawią. Ustaw bramkę --check jako wymagany status CI, żeby ręczne zmiany też nie przeszły.
Zmiana niekompatybilna trafiła do main przed konsumentami. Pole zmieniło nazwę, zamiast zostać dodane. Najpierw cofnij PR z kontraktem. Potem wprowadź go ponownie jako: dodaj, zmigruj konsumentów, usuń później. Konsumenci, którzy już zostali wdrożeni, działają dalej, bo revert przywraca stary kształt.
Konsumenci są wdrażani przed producentem. Aplikacja webowa prosi o phoneNumber i dostaje undefined. Pola opcjonalne i dopuszczające null sprawiają, że nic się nie psuje, i właśnie dlatego prompt planujący wymaga uzasadnienia wstecznej zgodności na każdym kroku. Przy zmianach zachowania schowaj kod konsumenta za flagą, dopóki producent nie działa na produkcji.
Workspace jest wolny, a odpowiedzi Agenta wciągają niezwiązany kod. Za dużo folderów albo za mało wykluczeń. Usuń foldery, które tylko czytasz, i zastąp je migawkami, a każdy .cursorignore rozszerz.
Dokąd dalej przy pracy z wieloma repozytoriami
Dział zatytułowany „Dokąd dalej przy pracy z wieloma repozytoriami”- Zarządzanie kontekstem w Cursorze: punkt wyjścia do tego, jak Agent dobiera kontekst w każdym workspace.
- Mikroserwisy w Cursorze: granice serwisów, reguły topologii i bramki zmian niekompatybilnych dla OpenAPI.
- Strategie dla dużych baz kodu: kiedy repozytoria powinny raczej stać się jednym monorepo.
- Współpraca zespołowa w Cursorze: udostępnianie repozytorium workspace’u i jego reguł całemu zespołowi.
- Pakiet dowodów: manifest, który PR z kontraktem niesie do recenzji.
- Praca na wielu plikach i katalogach w Claude Code: odpowiednik z
--add-dir. - Izolowane zadania Codex w Git worktrees: równoległe próby Codeksa w obrębie jednego repozytorium.