Semantycznie, nie tekstowo
Dzięki indeksowi wektorowemu zapytanie „znajdź wszystkie przepływy uwierzytelniania” wydobywa kod OAuth, JWT i sesji, nawet gdy żaden z nich nie dzieli słowa kluczowego.
Odziedziczyłeś trzymilionowy monolit. Pierwotni architekci odeszli dwa lata temu, dokumentacja opisuje system, który już nie istnieje, a twój pierwszy ticket dotyka klasy PaymentProcessor, którą importuje kilkanaście innych usług. Wrzucenie całości do asystenta AI po prostu przepełnia okno kontekstu i produkuje pewne siebie bzdury. Ten przewodnik pokazuje przepływy pracy, które naprawdę skalują się: wyszukiwanie semantyczne zamiast grepa, kontekst warstwowy zamiast „przeczytaj wszystko” i refactoring przyrostowy zamiast przepisywania na jeden raz.
Semantycznie, nie tekstowo
Dzięki indeksowi wektorowemu zapytanie „znajdź wszystkie przepływy uwierzytelniania” wydobywa kod OAuth, JWT i sesji, nawet gdy żaden z nich nie dzieli słowa kluczowego.
Śledzenie zależności
AI podąża za importami i miejscami wywołań przez granice modułów znacznie szybciej, niż zdołasz klikać przez „znajdź użycia”.
Testy charakteryzacyjne
Dla nieudokumentowanego kodu legacy AI tworzy testy, które przypinają obecne zachowanie, żebyś mógł refaktoryzować bez strachu.
To ty pozostajesz architektem
AI wykonuje mechaniczne skanowanie i boilerplate. To ty podejmujesz decyzje domenowe i architektoniczne, których ono podjąć nie potrafi.
Wyszukiwanie tekstowe zawodzi w skali, bo powiązany kod rzadko dzieli słownictwo. Indeks semantyczny zbudowany na embeddingach wektorowych to naprawia. Utrzymywany serwer to Zilliz Claude Context (@zilliz/claude-context-mcp — wcześniej publikowany jako code-context). Konfiguracja MCP jest niemal identyczna we wszystkich trzech narzędziach; różni się tylko polecenie rejestracji.
Dodaj do ~/.cursor/mcp.json:
{ "mcpServers": { "claude-context": { "command": "npx", "args": ["-y", "@zilliz/claude-context-mcp@latest"], "env": { "EMBEDDING_PROVIDER": "OpenAI", "OPENAI_API_KEY": "your-api-key", "MILVUS_TOKEN": "your-zilliz-key" } } }}claude mcp add claude-context \ -e OPENAI_API_KEY=your-api-key \ -e MILVUS_TOKEN=your-zilliz-key \ -- npx -y @zilliz/claude-context-mcp@latestcodex mcp add claude-context \ --env OPENAI_API_KEY=your-api-key \ --env MILVUS_TOKEN=your-zilliz-key \ -- npx -y @zilliz/claude-context-mcp@latestAlbo dodaj go bezpośrednio do ~/.codex/config.toml:
[mcp_servers.claude-context]command = "npx"args = ["-y", "@zilliz/claude-context-mcp@latest"]env = { EMBEDDING_PROVIDER = "OpenAI", OPENAI_API_KEY = "your-api-key", MILVUS_TOKEN = "your-zilliz-key" }Po zaindeksowaniu pytasz o koncepcje, a serwer zwraca odpowiednie pliki niezależnie od nazewnictwa. Dla wrażliwych baz kodu, które nie mogą sięgnąć do chmurowego API embeddingów, LuotoCompany/cursor-local-indexing uruchamia lokalny indeks ChromaDB i udostępnia go przez lokalny endpoint SSE:
Dodaj do ~/.cursor/mcp.json:
{ "mcpServers": { "workspace-code-search": { "url": "http://localhost:8978/sse" } }}claude mcp add --transport sse workspace-code-search http://localhost:8978/ssecodex mcp add workspace-code-search --url http://localhost:8978/sseTo utrzymuje kod źródłowy na twojej własnej infrastrukturze — właściwy wybór dla usług finansowych, opieki zdrowotnej czy pracy w sektorze obronnym, gdzie kod nie może opuścić sieci.
Od czego zacząć z nieznanym monolitem? Z góry na dół. Skłoń AI do zbudowania modelu mentalnego, zanim czegokolwiek dotkniesz, a potem zagłęb się w obszar, którego naprawdę dotyczy twój ticket.
Agent Cursora sam zbiera kontekst z zaindeksowanej bazy kodu — wystarczy opisać, czego chcesz. Użyj @Folders, aby zawęzić pytanie do jednego obszaru, i @Code, aby wskazać konkretny fragment:
@Folders services/authExplain the authentication and authorization architecture: where tokensare issued, how refresh works, and which services validate them.Aby uzyskać precyzyjne odniesienie, zaznacz funkcję w edytorze i dodaj ją przez @Code, zanim poprosisz agenta o prześledzenie miejsc jej wywołań.
Zawęź sesję do katalogu, który cię interesuje, flagą --add-dir przy starcie (lub /add-dir <path> w trakcie sesji), a potem pytaj od ogółu do szczegółu. Użyj wzmianek ścieżkowych z @, aby wciągnąć konkretny plik do kontekstu:
Analyze this codebase and build a mental model of the system architecture.Cover: core business domains, service boundaries, data-flow patterns, andexternal dependencies. Present it as an overview for a new senior engineer.Następnie zagłęb się przez wyszukiwanie semantyczne za pomocą serwera MCP:
Using claude-context, find all payment-processing flows. I need entrypoints, state management during processing, external provider integration,and the retry/error-handling logic. Reference @services/payment as you go.Umieść AGENTS.md w katalogu głównym repozytorium (plik kontekstu projektu w Codeksie, odpowiednik CLAUDE.md czy .cursor/rules) opisujący domeny i konwencje, a potem uruchom /init wewnątrz TUI, aby Codex go zainicjował. Przy dużym refactoringu pracuj w dedykowanym git worktree, żeby eksploracja nigdy nie dotykała twojego głównego checkoutu:
Map this codebase top-down: business domains, service boundaries, dataflow, and external dependencies. Then locate the payment-processing flowand summarize its entry points and retry logic.Największy błąd przy dużych bazach kodu to ładowanie wszystkiego naraz. Twój asystent nie potrzebuje wszystkich trzech milionów linii — potrzebuje właściwego wycinka we właściwym momencie. Pomyśl o tym jak o przybliżaniu na mapie: kontynent, kraj, miasto, ulica.
Poziom domeny (widok z 10 000 stóp)
What are the main bounded contexts in this system, and how do the payment,user, and inventory domains interact?Poziom usługi (widok z 1000 stóp)
Within the payment domain, explain the service architecture and the mainAPIs each service exposes.Poziom komponentu (widok ze 100 stóp)
Show me how PaymentProcessor handles credit-card transactions and what itsretry strategy is for failed charges.Poziom implementacji (poziom gruntu)
In PaymentProcessor.processCard(), why is there a 30-second timeout, and isthe synchronized block safe to remove?Każde narzędzie ma własny mechanizm zawężania tego, co widzi AI. Zasada jest identyczna: ładuj wąsko, rozszerzaj tylko, gdy odpowiedź tego wymaga.
Zawężaj za pomocą @Folders i @Code, a stałe reguły zakoduj jako Project Rule, żeby nie powtarzać ich w każdym prompcie:
# In .cursor/rules/payment.mdc (a Project Rule with glob: services/payment/**)When working with payment code:- All monetary amounts are integer cents — never floats- Mutations require an idempotency key- Never log full card numbers (PCI)- Add audit logging for every state transitionDla prostych projektów AGENTS.md w katalogu głównym repozytorium sprawdza się jako prostsza alternatywa dla strukturalnych reguł.
Użyj hierarchii plików CLAUDE.md — plik z każdego katalogu nakłada się na swoich rodziców, dając AI skupiony kontekst w miarę przemieszczania się po drzewie:
/CLAUDE.md # System-wide conventions/services/CLAUDE.md # Service-layer patterns/services/payment/CLAUDE.md # Payment-specific rulesPrzełączaj się czysto między niepowiązanymi zadaniami za pomocą /clear i /add-dir:
/clear/add-dir services/paymentAnalyze the payment-processing flow.
/clear/add-dir services/usersReview the authentication implementation.Codex czyta AGENTS.md z katalogu głównego repozytorium i z każdego podkatalogu, więc umieszczaj skupione instrukcje obok kodu, którym mają zarządzać:
# In services/payment/AGENTS.mdThis service handles all payment processing.- Amounts are integer cents to avoid floating-point error- Idempotency keys required on all transactions- PCI: never log full card numbersPrzy równoległej eksploracji uruchamiaj po jednym worktree na zadanie, żeby konteksty pozostawały odizolowane, a twoja główna gałąź — nietknięta.
Refactoring milionowej bazy kodu to jak remont szpitala podczas trwającej operacji — nie możesz wszystkiego wyłączyć. Wzorzec, który działa: odkryj, ustanów szablon, migruj małymi partiami, zweryfikuj.
Weźmy bazę kodu Node.js wciąż naszpikowaną callbackami error-first. Ręczna migracja do async/await zajęłaby miesiące. Zamiast tego skłoń AI do skategoryzowania pracy według ryzyka, a potem wygenerowania jednej wielokrotnego użytku transformacji na kategorię:
// Before — error-first callbackfunction loadUser(id, callback) { db.query('SELECT * FROM users WHERE id = ?', [id], (err, rows) => { if (err) return callback(err); callback(null, rows[0]); });}
// After — async, with a backward-compatible callback shimasync function loadUser(id, callback) { try { const rows = await db.query('SELECT * FROM users WHERE id = ?', [id]); if (callback) return callback(null, rows[0]); return rows[0]; } catch (err) { if (callback) return callback(err); throw err; }}Shim pozwala wywołującym migrować we własnym tempie. Stosuj transformację katalog po katalogu, uruchamiaj istniejące testy po każdej partii i śledź postęp — nigdy nie transformuj całego drzewa w jednym przebiegu.
Przy dużym przedsięwzięciu rozłożonym na zespół skłoń AI do podzielenia pracy tak, by zminimalizować konflikty między zespołami, a potem pilnuj uczciwości gałęzi:
Podziel według granic zależności
Analyze module dependencies and propose how to split this refactor acrossfour developers so their territories barely overlap. Flag any shared filesthat two teams would both need to edit.Gałąź na terytorium
git checkout -b refactor/user-servicesgit checkout -b refactor/payment-servicesgit checkout -b refactor/shared-utilsWykrywaj kolizje wcześnie
Review the diffs across all refactor/* branches and identify conflictingor breaking changes between teams before we attempt to merge.Każda duża baza kodu ma warstwy archeologiczne — kod z różnych epok i filozofii, część z niego sprzed czasów obecnego zespołu. Klasyczny koszmar: 15 000-liniowa procedura składowana, której nikt nie rozumie, a która wciąż codziennie przetwarza prawdziwe pieniądze.
Wzorzec strangler fig pozwala modernizować bez przepisywania: opakuj kod legacy za czystym interfejsem, a potem wyodrębniaj fragmenty po jednym, uruchamiając stary i nowy równolegle, aż zaufasz nowej ścieżce.
Gdy dokumentacja nie istnieje, testy stają się dokumentacją. Poproś AI o napisanie testów charakteryzacyjnych, które przypną obecne zachowanie — łącznie z dziwnymi fragmentami — tak by każda przyszła zmiana zmieniająca wyjście zawodziła głośno:
describe('Legacy OrderProcessor — current behavior', () => { it('returns status code 1 on a standard single-item order', async () => { const result = await processOrder({ customerId: 123, items: [{ sku: 'WIDGET-1', quantity: 1 }], }); expect(result.status).toBe(1); // 1 = success (undocumented magic number) expect(result.orderId).toMatch(/^ORD-\d{8}$/); });
it('returns -99 when inventory is unavailable', async () => { const result = await processOrder({ customerId: 123, items: [{ sku: 'OUT-OF-STOCK', quantity: 1 }], }); expect(result.status).toBe(-99); // -99 = inventory error });});W milionowej bazie kodu różne zespoły posiadają różne terytoria. Najtrudniejsze jest wprowadzenie zmiany przekraczającej granicę bez zepsucia czegoś komuś innemu. Przed każdą zmianą łamiącą uzyskaj raport wpływu.
Połącz to z automatycznie generowanymi kontraktami. Poproś AI o wytworzenie specyfikacji OpenAPI i schematów zdarzeń dla usługi, z której korzysta inny zespół — to zamienia „idź przeczytaj nasz kod” w stabilną granicę, względem której mogą się integrować bez grzebania w twoich wnętrznościach.
Przepływy pracy AI w dużych bazach kodu zawodzą na konkretne, rozpoznawalne sposoby. Poznaj sposób naprawy każdego z nich.