Wyszukiwanie między narzędziami: kod to złe miejsce
Większość decyzji programistycznych zapada poza kodem. Dowiedz się, jak zbudować wyszukiwanie między Slackiem, Linearem, GitHubem i Notion.
By Ellis Keane · 2026-03-17
Kod to najgorsze miejsce, by szukać odpowiedzi na pytanie, dlaczego podjęto daną decyzję.
Wiem, że brzmi to paradoksalnie. Spędzamy lata ucząc się flag ripgrepa, konfigurując wyszukiwanie w IDE, zapamiętując wzorce wyrażeń regularnych – i żadna z tych umiejętności nie pomaga, gdy pytanie brzmi nie „gdzie jest ta funkcja?", lecz „dlaczego wybraliśmy to podejście zamiast trzech omawianych alternatyw?". Odpowiedź na to drugie pytanie prawie nigdy nie jest w kodzie. Jest w wątku Slacka sprzed czterech miesięcy, w komentarzu Lineara zagrzebanym pod aktualizacjami statusów, w dokumencie Notion, który ktoś zaczął i nigdy nie skończył, oraz w recenzji PR, gdzie prawdziwa debata toczyła się w odpowiedzi na odpowiedź na odpowiedź.
To jest właśnie problem wyszukiwania między narzędziami dla programistów – kontekst decyzji jest podzielony między narzędziami bez ujednoliconej ścieżki zapytań. Mamy wyszukiwanie, które działa dobrze w ramach każdego narzędzia – wyszukiwanie Slacka jest przyzwoite, wyszukiwanie kodu GitHuba jest doskonałe, Linear ma filtry do wszystkiego – ale nic, co przeszukuje je wszystkie naraz. Decyzje, które ukształtowały architekturę, żyją w pięciu różnych miejscach, a od nas oczekuje się pamiętania, gdzie szukać.
No dobrze – oto jak zbudować wyszukiwanie między narzędziami z tym, co już masz. Żadnych nowych narzędzi (prawie – wspomnę o jednym na samym końcu, ale to działa bez niego).
Anatomia rozproszonej decyzji
Przejdźmy przez konkretny przykład. W zeszłym roku rozważaliśmy, czy użyć BullMQ czy Temporal jako kolejki zadań. Oto gdzie ta decyzja faktycznie żyła:
- Slack (#engineering): Trzy osobne wątki przez dwa dni. Pierwszy to link do posta na blogu o Temporalu, który ktoś udostępnił. Drugi to debata, czy potrzebujemy trwałego wykonania. Trzeci (tydzień później, inny kanał) to ktoś pytający „hej, czy zdecydowaliśmy już w sprawie kolejki?".
- Linear: Issue zatytułowane „Ocena opcji kolejki zadań" z sześcioma komentarzami, w tym tabelą porównawczą, którą jeden z naszych inżynierów spędził popołudnie na pisaniu.
- GitHub: Opis PR do implementacji BullMQ mówiący „jak omówiono" bez żadnych linków do miejsca, gdzie to omówiono.
- Notion: Pół skończony rekord decyzji architektonicznej obejmujący zalety Temporala, nigdy nieaktualizowany o ostateczny wybór.
- Google Docs: Notatki ze spotkania, na którym faktycznie podjęliśmy decyzję, zagrzebane w punktach między dwoma niezwiązanymi punktami agendy.
Pięć narzędzi. Jedna decyzja. I przeszukując którekolwiek jedno narzędzie, znalazłbyś fragment – nigdy pełny obraz. PR mówi ci, co wybraliśmy. Wątki Slacka mówią, co rozważaliśmy. Issue Lineara mówi o kompromisach. Dokument Notion mówi o połowie rozumowania. Notatki ze spotkania mówią o chwili, gdy to zostało sfinalizowane.
To nie jest wyjątek. To jest, jakimś cudem, stan sztuki w kwestii śledzenia decyzji przez zespoły inżynierskie w 2026 roku. Mamy AI generujące kod i wyszukiwarki indeksujące cały internet, ale ustalenie, dlaczego twój zespół wybrał BullMQ zamiast Temporala, wymaga sprawdzenia pięciu aplikacji i liczenia na to, że czyjś pamięć wytrzyma.
Co sprawia, że wyszukiwanie między narzędziami jest trudne dla programistów
To nie jest problem z API – każde narzędzie, którego używamy, ma całkiem dobre API wyszukiwania. Problem jest dziwniejszy:
Różne kształty danych. Slack zwraca wiadomości z znacznikami czasu i identyfikatorami kanałów. Linear zwraca issue ze stanami i etykietami. GitHub zwraca commity, PR-y i dopasowania kodu w zupełnie różnych formatach odpowiedzi. Scalenie ich w spójną oś czasu wymaga normalizacji, której nikt nie zadaje sobie trudu budowania (bo, szczerze mówiąc, to praca, która nie pojawia się na demonstracjach sprintu).
Fragmentacja kontekstu. Wiadomość Slacka mówiąca „chodźmy z opcją B" jest bez znaczenia bez wątku, który definiował opcje A, B i C. Ale wyszukiwanie Slacka zwraca poszczególne wiadomości, nie łuki rozmów. Znajdujesz wniosek bez rozumowania.
Dryf czasowy. Proces decyzyjny często trwa dni lub tygodnie z przerwami, kiedy nic się nie działo, bo wszyscy byli skupieni na innej pracy. Wyszukiwanie słów kluczowych może wydobyć początek i koniec rozmowy, pomijając kluczowy środek, po prostu dlatego, że na różnych etapach używano różnych słów.
Wyszukiwanie między narzędziami dla programistów nie jest problemem z API – każde narzędzie ma całkiem dobry endpoint wyszukiwania. To problem z kontekstem: decyzje są rozproszone po narzędziach w niekompatybilnych kształtach, pofragmentowane przez łuki rozmów i rozdzielone przez dryf czasowy. Wyszukiwanie słów kluczowych znajduje fragmenty; tylko połączony kontekst odnajduje pełny obraz.
Budowanie wyszukiwania między narzędziami z tym, co masz
Oto praktyczna część. Dla trzech lub czterech narzędzi z wyszukiwaniem tylko do odczytu spodziewaj się pół dnia na uruchomienie MVP – większość z tego zajmuje konfiguracja uwierzytelniania i normalizacja odpowiedzi, a nie sama logika wyszukiwania.
Konfiguracja dostępu do API
Będziesz potrzebować tokenów dla każdego narzędzia:
- Slack: Token użytkownika z zakresem
search:read (metody wyszukiwania Slacka wymagają tokenów użytkownika, nie tokenów bota – utwórz przez stronę aplikacji Slack API)
- Linear: Osobisty klucz API z Ustawień, a następnie API
- GitHub: Szczegółowy PAT z dostępem do odczytu do twoich repozytoriów
- Notion: Token wewnętrznej integracji z Ustawień, a następnie Połączenia
Skrypt zapytań z rozgałęzieniem
Podstawowy wzorzec jest zawstydzająco prosty – wysyłaj to samo zapytanie do każdego API i zbieraj wyniki:
```typescript interface SearchResult { source: 'slack' | 'linear' | 'github' | 'notion'; title: string; snippet: string; url: string; timestamp: Date; }
async function crossToolSearch(query: string): Promise<SearchResult[]> { const results = await Promise.all([ searchSlack(query), searchLinear(query), searchGitHub(query), searchNotion(query), ]);
return results .flat() .sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime()); } ```
Każda funkcja search* opakowuje odpowiednie API. Dla Slacka to search.messages. Dla Lineara to zapytanie GraphQL względem pól wyszukiwania. Dla GitHuba to endpoint wyszukiwania REST. Dla Notion to endpoint wyszukiwania z parametrem query.
Normalizacja i deduplikacja
Trudna część to nie samo wyszukiwanie – to uczynienie wyników użytecznymi. Będziesz chciał:
- Normalizować znaczniki czasu – między narzędziami (Slack używa epoki Unix, Linear używa ciągów ISO, GitHub używa ISO z przesunięciami strefy czasowej)
- Grupować powiązane wyniki – jeśli ten sam wątek Slacka pojawi się trzy razy, bo trzy wiadomości pasowały, złącz je w jeden wynik z URL wątku
- Rankingować według trafności – większość API zwraca własne oceny trafności, ale nie są one porównywalne między narzędziami. Prosta heurystyka: dokładne dopasowania słów kluczowych w tytułach rankingują wyżej niż dopasowania w treści, a nowsze wyniki rankingują wyżej niż starsze przy równej trafności
Opakowanie w CLI
Używam Commander.js do tego (głównie z przyzwyczajenia, ale wszystko zadziała):
```bash $ cross-search "bullmq vs temporal"
Found 14 results across 4 tools:
[Slack] #engineering – 2025-11-14 "I've been comparing BullMQ and Temporal for the job queue..." https://myteam.slack.com/archives/C0X.../p17318...
[Linear] ENG-342 – 2025-11-15 "Evaluate job queue options – BullMQ vs Temporal" https://linear.app/myteam/issue/ENG-342
[GitHub] PR #289 – 2025-11-22 "feat: implement BullMQ job queue (as discussed)" https://github.com/myorg/myrepo/pull/289
[Notion] Architecture Decisions – 2025-11-13 "Job Queue Evaluation: Temporal vs BullMQ" https://notion.so/myteam/abc123... ```
Czternaście wyników, posortowanych chronologicznie, z czterech narzędzi. Możesz zobaczyć pełny łuk decyzji w jednym miejscu: dokument Notion został rozpoczęty jako pierwszy, potem odbyła się dyskusja na Slacku, potem stworzono issue Lineara do śledzenia, i w końcu tydzień później wylądował PR.
Robienie tego naprawdę dobrze
Podstawowa wersja powyżej działa, ale ma kilka frustrujących krawędzi. Oto jak ją ulepszyć:
Rozwijanie wątków Slacka. Gdy znajdziesz pasującą wiadomość, pobierz cały wątek za pomocą conversations.replies. Pasująca wiadomość może brzmieć „tak, chodźmy z BullMQ" – bez poprzednich 40 wiadomości debaty jest bezużyteczna. Wyświetlaj fragment wątku, nie tylko pasującą wiadomość.
Komentarze recenzji PR. API wyszukiwania GitHuba nie wydobywa komentarzy recenzji podczas wyszukiwania PR-ów – potrzebujesz osobnego wywołania do endpointu recenzji pull requestów, żeby je pobrać. Tam żyje prawdziwa dyskusja techniczna.
Backlinki. Gdy znajdziesz issue Lineara, sprawdź, czy jakieś wiadomości Slacka zawierają URL tego issue. Wyszukiwanie Slacka obsługuje filtry has:link w połączeniu ze słowami kluczowymi. To wydobywa nieformalną dyskusję, która odbywała się wokół formalnego śledzenia.
Pamięć podręczna. Jeśli twój zespół generuje dużo treści (a czyj nie?), szybko napotkasz limity szybkości. Buforuj wyniki lokalnie z TTL wynoszącym 30 minut – większość historycznych decyzji nie zmienia się tak szybko.
Gdy wyszukiwanie tekstowe zawodzi
Oto moment na szczerość o ograniczeniach. Wyszukiwanie słów kluczowych między narzędziami działa zaskakująco daleko, a potem uderza w ścianę.
Ta ściana to: decyzje ewoluują. Wątek Slacka o „kolejkach zadań" może nigdy nie wspomnieć o „BullMQ" z nazwy – zamiast tego ktoś udostępnił link, ktoś inny powiedział „podoba mi się opcja oparta na Redis", a trzecia osoba powiedziała „zgadzam się, chodźmy z tym". Twoje wyszukiwanie „BullMQ" pomija cały wątek, bo słowo nigdy nie zostało użyte. Ludzie w wątku wiedzieli, co oznacza „opcja oparta na Redis". Twoje wyszukiwanie tego nie wie.
To jest fundamentalnie problem grafowy, a nie tekstowy. To, czego naprawdę chcesz, to: „pokaż mi wszystko połączone z decyzją, która doprowadziła do PR #289". Oznacza to rozumienie, że PR odwołuje się do issue Lineara, które zostało utworzone po dyskusji na Slacku, która zaczęła się, bo ktoś przeczytał dokument Notion. Połączenia są niejawne – ludzie tworzyli je, kopiując URL-e i mówiąc „jak omówiono" – i wyszukiwanie słów kluczowych nie może ich zrekonstruować.
Możesz to częściowo rozwiązać, podążając za linkami. Parsuj URL-e z wiadomości Slacka, opisów PR i komentarzy Lineara. Zbuduj prostą listę sąsiedztwa: ten wątek Slacka prowadzi do tego issue Lineara, który jest przywoływany w tym PR. Następnie gdy ktoś szuka, możesz rozszerzyć wyniki o powiązane elementy, nawet jeśli nie pasują do słowa kluczowego.
To podejście z listą sąsiedztwa to w zasadzie prymitywny graf wiedzy – i tam leży prawdziwa wartość wyszukiwania między narzędziami dla programistów. Nie w znajdowaniu poszczególnych wiadomości, ale w podążaniu za wątkiem decyzji przez każde narzędzie, którego dotknęła. To mniej „wyszukiwanie", a bardziej zarządzanie wiedzą dla programistów – rozumienie, jak informacje przepływają między twoimi narzędziami, żebyś mógł odtworzyć kontekst, gdy go potrzebujesz.
Problem z utrzymaniem (i skrót)
Podejście skryptowe działa świetnie przez jakieś trzy miesiące, a potem ktoś zmienia workspace Slacka, albo Linear aktualizuje schemat GraphQL, albo dodajesz nowe narzędzie i nikt nie pamięta o aktualizacji skryptu wyszukiwania. Budowałem dokładnie to samo dwa razy i porzucałem dwa razy (co prawdopodobnie mówi więcej o moim zaangażowaniu w utrzymanie niż o samym podejściu).
Jeśli chcesz wyszukiwania między narzędziami, które pozostaje aktualne bez opieki, do tego właśnie są zbudowane narzędzia takie jak Sugarbug – automatycznie utrzymuje graf wiedzy i zachowuje połączenia w miarę zmian narzędzi. Ale wersja DIY powyżej jest naprawdę użyteczna, jeśli jesteś gotów ją utrzymywać.
Przestań przeszukiwać pięć narzędzi osobno. Sugarbug buduje graf wiedzy, żebyś mógł znaleźć każdą decyzję, dyskusję lub commit w jednym miejscu.
Q: Jak przeszukiwać wiele narzędzi deweloperskich jednocześnie? A: Możesz zbudować lekkie wyszukiwanie między narzędziami, łącząc API każdego narzędzia – search.messages Slacka, issueSearch Lineara i endpoint wyszukiwania kodu GitHuba – w jeden skrypt, który rozsyła zapytania i scala wyniki według znacznika czasu. Przykłady kodu powyżej pozwolą ci zacząć w jedno popołudnie. Główne wyzwanie to nie samo wyszukiwanie, lecz normalizacja różnych formatów odpowiedzi w spójną oś czasu.
Q: Czy Sugarbug zapewnia wyszukiwanie między narzędziami dla programistów? A: Tak. Sugarbug pobiera sygnały z Lineara, GitHuba, Slacka, Figmy, Notion i innych narzędzi do grafu wiedzy, dzięki czemu możesz wyszukać decyzję lub dyskusję i znaleźć każdy powiązany wątek, issue i commit w jednym miejscu. Automatycznie obsługuje normalizację, deduplikację i podążanie za linkami – te fragmenty, które sprawiają, że podejście DIY jest z czasem kruche.
Q: Dlaczego nie mogę znaleźć decyzji architektonicznych w kodzie? A: Ponieważ większość decyzji zapada w wątkach Slacka, komentarzach Lineara, dokumentach Notion i recenzjach PR – nie w samym kodzie. Kod zapisuje wynik decyzji (funkcja istnieje, biblioteka została wybrana), ale rozumowanie, kompromisy i omawiane alternatywy są rozproszone po narzędziach komunikacyjnych. git blame powie ci, kto i kiedy zmienił linię, ale nie dlaczego wybrał to podejście zamiast alternatyw.
Q: Czy Sugarbug może zastąpić dokumenty ADR w śledzeniu decyzji? A: Sugarbug nie zastępuje ADR-ów, ale wychwytuje decyzje, które nigdy nie trafiają do ADR. Większość zespołów pisze ADR-y dla może 10% swoich wyborów architektonicznych – reszta rozpływa się w wątkach Slacka i komentarzach PR. Sugarbug je wydobywa, łącząc rozmowy ze zmianami kodu, które wywołały, zapewniając śledzenie decyzji dla pozostałych 90% bez zmieniania niczyjego przepływu pracy.