Dlaczego AI lepiej pracuje w monorepo
AIInżynieriaMonorepo

Dlaczego AI lepiej pracuje w monorepo

Agent AI pracuje tylko na tym, co widzi. Co zmieniło u nas umieszczenie backendu i frontendu w jednym workspace, w liczbach, i czego to nie naprawiło.

TarasTaras•5 października 2026•9 min czytania

16 marca o 03:38 czasu UTC do waytohire.ai trafiły dwa commity, w odstępie dwóch sekund. Pierwszy dodawał changelog po stronie backendu: model danych, endpointy API i ekran w panelu administracyjnym. Drugi dodawał strony, na których ten changelog widzą użytkownicy. Dwa repozytoria, jedna funkcja. Oba commity mają tego samego autora i nie jest to nikt z naszego zespołu. W polu „autor” stoi: Claude.

Nikt nie musiał przepisywać, co zwraca API, żeby frontend mógł z tego skorzystać. Agent, który pisał strony, chwilę wcześniej sam napisał endpointy, więc mógł je po prostu przeczytać.

O tym jest ten tekst. Agent AI pracuje tylko na tym, co widzi, a o tym, co widzi, decyduje miejsce, w którym leży kod.

Granica repozytorium to ściana

Większość produktów to co najmniej dwie bazy kodu: backend, który przechowuje dane i pilnuje reguł, oraz frontend, w który ludzie faktycznie klikają. Często leżą w osobnych repozytoriach, z powodów, które miały sens, gdy czytali je wyłącznie ludzie. Inne języki, inny rytm wydań, inne osoby.

Programista radzi sobie z tym podziałem odruchowo. Pamięta, co zwraca API, albo pyta osobę, która je pisała. Agent uruchomiony w repozytorium frontendu nie ma żadnej z tych możliwości. Załóżmy, że backend wysyła pole salary_from, a Ty prosisz o pokazanie go na ekranie. Agent musi zgadnąć nazwę, typ i to, czy pole może być puste. Zgadnie coś rozsądnego, na przykład minSalary. I w tym kłopot: rozsądny, ale błędny strzał kompiluje się, przechodzi pobieżny przegląd i wysypuje się dopiero u użytkownika.

Typowe obejście to człowiek, który wkleja odpowiedzi API do czatu. Działa, tylko że robi z programisty kuriera.

Wystarczy umieścić oba kody tam, gdzie agent może je przeczytać, a zgadywanie zamienia się w sprawdzenie. Dokumentacja Claude Code mówi to jednym zdaniem: miejsce, w którym uruchamiasz narzędzie, decyduje o tym, które pliki Claude może czytać i edytować bez dodatkowych uprawnień. Reszta tego tekstu to właśnie to zdanie, przyłożone do dwóch naszych projektów.

Agent widzi tylko frontend

Backend
Poza widokiem
Frontend
minSalary: number

Kompiluje się. Zła nazwa, pole nigdy nie jest puste. Psuje się dopiero u użytkownika.

Agent widzi obie strony

Backend
salary_from = models.IntegerField( blank=True, null=True)
Frontend
salary_from: number | null

Ta sama nazwa, ten sam typ i pole może być puste.

Pole jest prawdziwe: backend waytohire przechowuje salary_from jako opcjonalną liczbę całkowitą. Zgadywanie to ilustracja.

Co mamy w waytohire.ai

waytohire.ai to nasz własny produkt rekrutacyjny, rozwijany od wiosny 2024 roku. Backend to Django: około 31 tysięcy linii Pythona i mniej więcej 220 ścieżek URL. Frontend to pięć aplikacji webowych w jednym workspace TypeScriptu, razem około 75 tysięcy linii. Dwa języki, dwie historie w gicie.

Nigdy nie połączyliśmy ich w jedno repozytorium. Zrobiliśmy coś mniejszego. Oba są wciągnięte do wspólnego workspace jako submoduły gita, a agent startuje na samej górze. W jednej sesji może otworzyć serializer w Django i komponent Reacta, który wyświetla jego wynik.

Żeby sprawdzić, czy to cokolwiek zmieniło, przeszliśmy przez historię. Dla każdego commita w backendzie sprawdziliśmy, czy w ciągu dziesięciu minut pojawił się commit we frontendzie. To zgrubny sygnał, że obie połowy zmiany powstały za jednym posiedzeniem, ale przynajmniej da się go policzyć.

2024
26%
2025
30%
2026
70%
Przypadek
1–4%
Odsetek commitów w backendzie, którym w ciągu dziesięciu minut towarzyszy commit we frontendzie. waytohire.ai, gałąź develop, bez merge commitów. Przypadek to ten sam pomiar po przesunięciu dat backendu o 3, 7 i 14 dni.

W 2024 roku dotyczyło to mniej więcej co czwartego commita w backendzie, w 2025 roku 30%. W 2026 roku to 70%. Żeby upewnić się, że nie mierzymy zbiegu okoliczności, przesunęliśmy daty commitów backendu o kilka dni i policzyliśmy jeszcze raz. Sam przypadek daje od 1 do 4%.

Kilka zastrzeżeń, bo wykres wygląda poważniej, niż na to zasługuje. Ten rok to na razie mała próba. Dziesięć minut to przybliżenie, a dwa commity bliskie w czasie nie zawsze dotyczą tej samej funkcji. Przez te dwa lata bardzo poprawiły się też same modele, więc workspace nie jest jedyną rzeczą, która się zmieniła. Traktuj to jako obraz naszej własnej historii. Ten obraz zgadza się jednak z dwoma commitami z marca: funkcja coraz częściej przychodzi w całości, po obu stronach naraz.

Czego pełny kontekst nie daje

To, że agent widzi obie strony, nie oznacza jeszcze, że te strony nie mogą się rozjechać.

W waytohire frontend ma własny opis API: 193 endpointy, każdy z ręcznie napisanymi typami TypeScriptu, które mówią, co zwraca backend. Kiedy odpowiedź backendu się zmienia, typy pozostają poprawne tylko wtedy, gdy ktoś poprawi je za tym samym posiedzeniem. Mając oba kody przed sobą, agent zazwyczaj to robi. Zazwyczaj to nie zawsze, a kiedy zapomni, nic nie zatrzymuje builda.

Submoduły rozwiązują więc problem kontekstu, a problem kontraktu zostawiają tam, gdzie był. Agent wie więcej. Nadal nikt mu nie mówi, kiedy się myli.

Nowszy projekt od początku jest monorepo

Pod koniec września zaczęliśmy nowy produkt. Nie jest jeszcze wydany, więc zostaje tu bez nazwy, ale liczy się struktura: aplikacja mobilna, niewielki backend serverless i wewnętrzne narzędzie webowe, wszystko w jednym repozytorium zarządzanym przez Nx.

Mniej więcej połowa kodu leży we wspólnych pakietach, a nie w którejkolwiek z aplikacji. To pierwsze, co widać w drzewie katalogów, i właśnie o to w tym układzie chodzi.

Nie wszystko poszło gładko. Pierwszego dnia szablon projektu wygenerował konfigurację dla sześciu różnych narzędzi AI, blisko 12 tysięcy linii. Pięć minut później usunęliśmy całość. To, z czego agent faktycznie korzysta, jest dużo prostsze: spisany plan podzielony na etapy, jeden etap na sesję, z decyzjami dopisywanymi do planu na bieżąco.

Co monorepo pozwala współdzielić

Z tych wspólnych pakietów biorą się korzyści. Cztery z nich widać w codziennej pracy.

CzęśćKontraktKatalogBiblioteka UI
Aplikacja mobilnaImportuje goImportuje goImportuje go
Funkcja serwerowaDostaje wygenerowaną kopięDostaje wygenerowaną kopięNie korzysta
Wewnętrzne narzędzie weboweNie korzystaImportuje goNie korzysta

Linie kodu

Wspólne pakiety 55%Aplikacje 45%
Z których wspólnych pakietów korzysta każda część nowszego projektu. Funkcja serwerowa nie może importować pakietów, więc dostaje wygenerowane kopie. Linie kodu: niepuste linie TypeScriptu w repozytorium, stan na październik 2026.

Typy zdefiniowane raz. Kształt odpowiedzi serwera jest zapisany w jednym miejscu. Ta sama definicja sprawdza to, co serwer wysyła, i parsuje to, co aplikacja odbiera. Zmień ją, a albo zmienią się obie strony, albo coś głośno się wysypie. W waytohire tę samą robotę wykonują ręcznie pisane typy dla 193 endpointów i ktoś musi pamiętać, żeby je aktualizować.

Dane i limity zdefiniowane raz. Katalog, wokół którego zbudowany jest cały produkt, to osobny pakiet. Importują go aplikacja i wewnętrzne narzędzie webowe, a pośrednio także serwer. Produkt ma też funkcję AI, która wybiera pozycje z tego katalogu. Schemat, którego muszą trzymać się jej odpowiedzi, powstaje z tego samego pakietu, więc model nie może wybrać pozycji, której aplikacja nie ma. Obok leżą limity: jak długa może być wiadomość i ile wiadomości trafia do serwera. Aplikacja przycina wszystko do tych wartości, zanim cokolwiek wyśle.

Jedno polecenie sprawdza wszystko. nx run-many -t test typecheck sprawdza wszystkie projekty w repozytorium. Agent, który zmienia kontrakt backendu, jeszcze w tej samej sesji dowiaduje się, czy aplikacja nadal się kompiluje. W waytohire agent musi pamiętać. Tutaj dostaje informację.

Jedna zmiana, jeden commit. Dwa commity z waytohire z początku tego tekstu to była jedna funkcja, rozdzielona na dwa repozytoria w odstępie dwóch sekund. Tutaj funkcja, która dotyka serwera i aplikacji, to jeden commit, a osoba, która go przegląda, widzi obie połówki obok siebie.

Do jednej niedoskonałości warto się przyznać. Środowisko serverless nie potrafi bezpośrednio importować naszych wspólnych pakietów, więc potrzebne pliki generuje skrypt, a test nie przechodzi, gdy są nieaktualne. Kilka limitów po stronie serwera nadal przepisujemy ręcznie. Monorepo zmniejsza odstęp między dwiema stronami produktu. Nie zawsze go zamyka.

Dlaczego monorepo jest dobre dla AI

Agent pracuje w pętli: czyta kod, zmienia go i sprawdza wynik. Monorepo pomaga na każdym z tych etapów, choć nie w równym stopniu.

Czytanie można mieć i bez niego. Submoduły we wspólnym workspace dają agentowi w waytohire ten sam widok obu stron. Jeśli brakuje Ci tylko widoku, monorepo nie jest potrzebne.

Przy zmianach procentują wspólne definicje. Kiedy typ jest w jednym miejscu, nie ma drugiej kopii, o której agent mógłby zapomnieć. Dokumentacja Claude Code radzi to samo przy zmianach, które przechodzą przez kilka pakietów: daj agentowi wspólną zmianę i wszystkie miejsca, które z niej korzystają, w jednej sesji, żeby decyzje pozostały spójne.

Sprawdzanie zamyka lukę, którą zostawiają typy w waytohire. Tam agent zazwyczaj je poprawia, a kiedy zapomni, nic się nie wysypuje. W monorepo ta sama pomyłka psuje typecheck, w tej samej sesji, zanim ktoś inny ją zobaczy.

Jest też prostszy powód. Programista przenosi kontekst z tygodnia na tydzień. Agent zaczyna każdą sesję od tego, co jest w repozytorium, i od tego, co mu powiesz. Im więcej produktu mieści repozytorium i im więcej jego reguł jest zapisanych w kodzie, a nie w czyjejś pamięci, tym mniej musisz mu mówić.

Trzy poziomy i ile każdy kosztuje

Obok siebie wygląda to tak.

Osobne repozytoria

Co widzi agent
Jedną stronę naraz. Druga to zgadywanie.
Co pilnuje zgodności
Ludzka pamięć.
Koszt wdrożenia
Żaden. To ustawienie domyślne.

Submoduły w jednym workspace

Co widzi agent
Obie strony w jednej sesji.
Co pilnuje zgodności
Agent i code review.
Koszt wdrożenia
Jedno popołudnie.

Monorepo ze wspólnym kontraktem

Co widzi agent
Obie strony i definicje, które je łączą.
Co pilnuje zgodności
Build. Niezgodność nie przechodzi testu.
Koszt wdrożenia
Niewielki pierwszego dnia. Później to migracja.
Trzy sposoby ułożenia backendu i frontendu. Przerywany obrys to wspólny workspace, ciągły to jedno repozytorium.

Pierwszy poziom nic nie kosztuje, bo większość projektów już na nim jest. Drugi to jedno popołudnie: repozytorium nadrzędne, dwa submoduły i krótki plik z instrukcjami na górze. Trzeci jest prawie darmowy pierwszego dnia nowego projektu i oznacza prawdziwą migrację w istniejącym, zwłaszcza gdy obie strony są napisane w różnych językach. Backend w Django i frontend w TypeScripcie nie mogą współdzielić typu przez zwykły import; typy frontendu trzeba by generować ze schematu API. Taka jest odległość między waytohire, które jest na poziomie drugim, a nowym projektem, który zaczął od trzeciego.

Kiedy monorepo robi się za duże

Większe nie znaczy automatycznie lepsze. Dokumentacja Claude Code poświęca większość miejsca odwrotnemu problemowi: w dużym repozytorium kontekst agenta zapełnia się instrukcjami i plikami, które nie mają nic wspólnego z zadaniem. To kosztuje, a jakość pracy spada.

Rozwiązania sprowadzają się do zawężenia zakresu. Instrukcje można podzielić na katalogi, żeby agent ładował zasady dla kodu, nad którym pracuje, zamiast jednego pliku o wszystkim. Agenta można też uruchomić w tej części repozytorium, której dotyczy zadanie, a nie na samej górze. Jedno repozytorium to sposób, żeby dać agentowi właściwy widok. To nie jest zachęta, żeby pokazywać mu wszystko.

Czy monorepo obniża koszt developmentu?

Częściowo. Usuwa jeden konkretny koszt: czas poświęcany na szukanie i naprawianie niezgodności między backendem a frontendem. Samego pisania kodu nie czyni tańszym, a w istniejącym produkcie przejście na monorepo to migracja z własną ceną.

Ile jest warta ta oszczędność, zależy od tego, jak często zmiana dotyka obu stron. W waytohire 70% tegorocznych commitów backendu miało commit frontendu w ciągu dziesięciu minut, więc większość pracy przechodzi przez tę granicę. W produkcie, w którym obie połówki rzadko zmieniają się razem, oszczędność jest niewielka.

I to jest sedno biznesowe. AI przyspiesza pisanie kodu. To, czy ta prędkość dotrze do Ciebie, zależy od tego, ile z niej pójdzie potem na składanie dwóch połówek z powrotem w całość.

Zacznij od tego, co widzi agent

Jeśli po tej lekturze masz zrobić jedną rzecz, sprawdź, co widzą Twoje narzędzia AI, kiedy pracują nad produktem. Otwórz projekt tak, jak otwiera go agent. Jeśli w tym widoku brakuje połowy produktu, naprawa to jedno popołudnie konfiguracji, a po kilku miesiącach widać ją w historii.

→ Ile kosztuje przejęcie kodu napisanego przez AI to opowieść o tym, co się dzieje, gdy nikt nie sprawdza.

→ Jak dodajemy AI do istniejącego produktu.

→ Zobacz, jak prowadzimy projekt od zakresu do wdrożenia.


Źródła

  • Dane o commitach: historia gita repozytoriów backendu i frontendu waytohire.ai, gałąź develop, bez merge commitów, stan na październik 2026.
  • Dostęp do plików i zawężanie kontekstu w dużych repozytoriach: Set up Claude Code in a monorepo or large codebase (Anthropic).

Ostatnia aktualizacja: 5 października 2026. Narzędzia zmieniają się szybko — to, co widzi agent, pozostanie ważne dłużej niż ich nazwy.

Taras
Autor

Taras

Współzałożyciel i architekt produktu

Ponad 14 lat tworzenia oprogramowania. Kieruje inżynierią i kierunkiem firmy, pozostając blisko kodu.