Jak zamieniam AI w dźwignię w mojej codziennej pracy jako programista
Doszliśmy do momentu, w którym nawet programiści spoza frontendu mogą powiedzieć, że wiele rzeczy zmienia się z dnia na dzień(jak frameworki frontendowe). Ostatni rok był szalony: nowe modele, usprawnienia w LLM-ach, nowe narzędzia, agenci oraz nowe wzorce zarządzania kontekstem — wszystko to rozwijało się w niezwykle szybkim tempie. Pomimo szybko zmieniającego się środowieka, my programiści zaadaptowaliśmy AI do naszej codziennej pracy. Dzięki znacząco ulepszonym modelom i narzędziom możemy bardziej skupić się na tym, co budujemy, zamiast jak to budujemy — jednocześnie mając wiele nowych rzeczy do nauczenia się.
Istnieje wiele aspektów, które należy wziąć pod uwagę — od promptowania, przez servery MPC i agentów, aż po wybór odpowiedniego modelu LLM. Jednocześnie wciąż musimy rozwijać naszą wiedzę z zakresu inżynierii oprogramowania, ponieważ vibe coding nie jest realnym patternem przy tworzeniu wysokiej jakości, bezpiecznego i skalowalnego oprogramowania. Jedną z rzeczy, które najbardziej cenię w mojej pracy, jest możliwość rozwoju i nauki nowych, ekscytujących rzeczy. Dzielenie się wiedzą na temat wykorzystania AI w programowaniu jest szczególnie ważne na wczesnym etapie jego adopcji, gdy wypracowujemy najlepsze wzorce na teraz i na przyszłość. Poniżej przedstawiam moje podejście do wykorzystania AI w programowaniu, eksperymenty oraz realną pracę z AI.
Promptowanie
Kiedy mówimy o AI w programowaniu, zazwyczaj myślimy o narzędziach, które wykorzystują modele LLM — a modele LLM potrzebują inputu, aby wygenerować output. Promptowanie jest fundamentalnym elementem pracy z LLM-ami: im lepszy prompt przygotujemy, tym lepszy rezultat otrzymamy. Mimo że modele stają się coraz lepsze i potrafią generować akceptowalne wyniki nawet wtedy, gdy prompt zawiera drobne błędy, jakość promptu nadal ma znaczenie.
Poniżej przedstawiam najważniejsze zasady, którymi kieruję się podczas tworzenia promptów:
-
organizuj swoje propmpty Nazwij zadanie, które przekazujesz modelowi LLM, i umieść je na początku promptu. Jeśli chcesz zrefaktoryzować fragment kodu, jasno poproś o „refaktoryzację”. Jeśli oczekujesz code review, zacznij od „Review the code…”, a następnie dodaj szczegóły oraz kontekst. Zastanów się, jaki jest cel, i podziel go na mniejsze kroki. Używaj interpunkcji oraz list w stylu TODO, stosuj słowa kluczowe, które naprowadzają model, i unikaj bycia niejednoznacznym za wszelką cenę. Skup się na jednym, jasno określonym zadaniu — nikt nie buduje aplikacji jednym promptem.
-
dołączaj kontekst Przekazuj kontekst za pomocą czytelnych odniesień: wskazań plików, fragmentów kodu, komunikatów o błędach, zawartości terminala, zrzutów ekranu lub poprzez wskazanie agentowi, gdzie i czego powinien szukać. Nie różni się to od rozmowy z kolegą z zespołu lub liderem technicznym podczas omawiania kodu czy sesji planowania. Istnieje wiele sposobów, aby to zrobić — narzędzia AI, takie jak agenci terminalowi czy IDE wspierane przez AI, stosują podobne wzorce, często wykorzystując symbol @ jako sposób bezpośredniego odwoływania się do kodu. Unikaj zbędnego kontekstu — zwięzłość ma znaczenie.
-
"sacrifice grammar for the sake of concission" To słowa Matta Pococka z jednego z jego materiałów wideo i jest to bardzo dobra wskazówka. Modele LLM mogą sprawiać wrażenie partnerów do rozmowy, co może sugerować, że musimy używać poprawnej gramatyki. W rzeczywistości są to systemy probabilistyczne, które przewidują kolejne tokeny, dlatego zwięzłość jest kluczowa przy promptowaniu pod kod. Im więcej zbędnych słów zawiera prompt, tym większe ryzyko halucynacji lub odejścia modelu od zamierzonego rezultatu.
-
korzystaj z mieszanych sposobów przekazywania treści do LLM-ów Tworzymy prompty w języku naturalnym, więc dlaczego zawsze mamy je wpisywać, zamiast po prostu mówić? Wiele narzędzi AI pozwala generować prompty za pomocą głosu, co często jest znacznie szybsze niż pisanie. Często łączę oba podejścia — pisanie i mówienie. Korzystanie z głosu przy tworzeniu promptów ma dodatkową zaletę: pomaga lepiej artykułować myśli i ćwiczyć umiejętność wyjaśniania złożonych problemów, co z czasem procentuje.
Rules
Pozwalanie AI na generowanie kodu bez zasad niemal gwarantuje niską jakość rezultatu. Aby zapewnić spójność, modele LLM potrzebują jasno określonych wytycznych. Oczywiście nikt nie chce wklejać ani przepisywać tych zasad za każdym razem, gdy tworzy nowy prompt. Większość narzędzi AI oferuje mniej lub bardziej ustandaryzowane sposoby zarządzania zasadami, zazwyczaj w postaci plików Markdown. Wiele z nich traktuje plik AGENTS.md jako źródło reguł. Plik ten można umieścić na różnych poziomach projektu lub nawet globalnie — często w katalogu konfiguracyjnym narzędzia AI. Jeśli masz zasady, które z pewnością będą używane w każdym projekcie, możesz zdefiniować je globalnie. Jeśli natomiast dotyczą konkretnego projektu, możesz umieścić AGENTS.md w jego katalogu głównym albo w podfolderze — na przykład dla komponentów lub konkretnego modułu w monorepo. Ważne jest, aby nie powielać zasad pomiędzy plikami AGENTS.md, ponieważ wszystkie reguły są agregowane i wysyłane do LLM razem z promptem.
W moim pliku AGENTS.md umieszczam następujące zasady:
-
Komendy używane w danym projekcie, takie jak uruchamianie aplikacji, komendy Docker'owe.
-
Jasno określone granice definiujące, czego AI nie może robić na poziomie projektu lub globalnie — na przykład zakaz dodawania nowych zależności bez wyraźnej zgody.
-
Zasady określające, co AI powinno, a czego nie powinno robić w kontekście pracy z Gitem.
-
Opis struktury projektu oraz lista wykorzystywanych technologii, w tym wersje najwżniejszych bibliotek i ograniczenia zależności.
-
Wytyczne dotyczące stylu kodu — w moim przypadku są to m.in. wczesne zwracanie wartości (early returns), preferowanie function definition zamiast function expression oraz używanie ESM zamiast CommonJS. Często umieszczam tu krótkie przykłady pokazujące, co jest złym, a co dobrym wzorcem.
-
Zasady pracy z testami. W tym miejscu wymuszam na AI pisanie testów, poprawianie ich lub zmiany w codebase na ich podstawie. Przy pracy w metodyce TDD warto jasno poinformować AI o tym podejściu i dopuścić sytuacje, w których testy jeszcze nie przechodzą.
Plan
Posiadanie planu jest kluczowe przy rozwiązywaniu problemów i tworzeniu funkcjonalności. Większość problemów trzeba rozbić na mniejsze zadania, logicznie uporządkowane w ramach planu — i dokładnie tak samo jest w przypadku pracy z AI. AI nie jest w stanie dostarczyć niezawodnego oprogramowania za pomocą jednego promptu za pomocą vibe codingu. Plan pomaga uporządkować pracę nad projektem lub funkcjonalnością, tworząc źródło prawdy oraz punkt odniesienia przy uruchamianiu wielu agentów. Możesz pracować nad każdą fazą osobno, iterując po kolejnych fragmentach planu. Niektóre nowoczesne narzędzia AI oferują tryb planowania, który pozwala tworzyć plan z pomocą LLM-a, omawiając wymagania. Moim ulubionym podejściem jest dzielenie planu na fazy, gdzie każda faza stanowi większy blok. Przykładowo, implementację uwierzytelniania z użyciem OpenID Connect można podzielić na dwie podfazy: uwierzytelnianie po stronie frontendu oraz backendu. Każda z tych podfaz zawiera następnie konkretne kroki — na przykład po stronie backendu: implementację strategii Google OpenID, kontrolera uwierzytelniania oraz pozostałe elemnty. Plany można również przechowywać w plikach Markdown, które modele LLM potrafią łatwo odczytać. Zawsze staram się pracować w tej samej pętli: plan → wykonanie → testy → stage/commit → powtórzenie.
Zarządzanie kontekstem
Pomimo tego, że okna kontekstowe modeli LLM stale się powiększają — a niektóre modele obsługują już nawet do 1 miliona tokenów — zarządzanie kontekstem nadal pozostaje kluczowe. Im większy kontekst, tym więcej szumu pojawia się w konwersacji, co obniża trafność generowanych odpowiedzi i zwiększa ryzyko zbaczania modelu. Są momenty, w których lepiej rozpocząć nową konwersację, i właśnie wtedy z pomocą przychodzi plan opisany w poprzedniej sekcji. Posiadanie źródła prawdy, takiego jak plan, sprawia, że rozpoczęcie nowej konwersacji jest proste i bezpieczne. Kolejną techniką, z której często korzystam, jest jawne instruowanie modelu, aby używał subagentów do wyspecjalizowanych zadań. Najczęstszym przykładem jest wykorzystanie subagentów do eksplorowania codebase’u. Główny agent otrzymuje wtedy podsumowany wynik pracy subagenta, co pozwala zaoszczędzić znaczną część okna kontekstowegoe — to tak, jakby łączyć okna kontekstowe wielu modeli LLM. W niektórych przypadkach, aby jeszcze bardziej oszczędzić kontekst, proszę model, aby samodzielnie znalazł istotny kod przy użyciu subagentów, zamiast wklejać go bezpośrednio do promptu.
MCP-y również odgrywają tutaj bardzo ważną rolę. Włączanie zbyt wielu MCP-ów wszędzie zazwyczaj nie jest dobrym pomysłem. Każdy MCP musi przesłać listę definicjii swoich narzędzi, co może szybko zaśmiecić kontekst. Staram się nie włączać MCP-ów, które są zbędne dla danego projektu. Istnieje kilka sposobów zarządzania tym mechanizmem, w zależności od używanego agenta lub narzędzia AI.
Istnieje również stosunkowo nowa koncepcja o nazwie Skills, niedawno wprowadzona przez Anthropic. Skills to katalogi — w praktyce paczki — które zawierają zasoby wykorzystywane przez AI. Zasoby te zazwyczaj obejmują instrukcje dla modelu LLM, skrypty wykonywane lokalnie, dokumentację oraz powiązany kontekst. Skills są bardzo efektywne z punktu widzenia zarządzania kontekstem poniweaż zasoby są ładowane stopniowo, tylko wtedy, gdy są potrzebne, co pozwala zaoszczędzić znaczną część okna kontekstowegoe. Dobrym podejściem jest przejrzenie używanych MCP-ów i sprawdzenie, czy któreś z nich mogą zostać zastąpione przez Skills. Zazwyczaj MCP-y lepiej sprawdzają się przy dynamicznych lub zdalnych danych, takich jak integracje z zewnętrznymi API, natomiast Skills świetnie nadają się do automatyzacji wykonywanych lokalnie oraz powtarzalnych workflows.
Równoległość zadań
Współczesne narzędzia AI osiągnęły poziom, w którym możemy uruchamiać agentów pracujących równolegle. Funkcją, którą cenię najbardziej, jest możliwość korzystania z subagentów przez głównego agenta. W narzędziach terminalowych, takich jak Claude Code czy OpenCode, możemy tworzyć własnych wyspecjalizowanych agentów — na przykład do przeprowadzania code review lub wyszukiwania podatności bezpieczeństwa w codebase’ie. Jak wspomniałem w poprzedniej sekcji, subagenci wykonują wyspecjalizowane zadania i raportują ich wyniki do głównego agenta, co pozwala oszczędzać okno kontekstowe. Co równie istotne, mogą oni skupić się na wąskich, jasno określonych odpowiedzialnościach, co przekłada się na wyższą jakość rezultatów dla poszczególnych podzadań.
Kolejną rzeczą, którą robię, jest uruchamianie wielu agentów jednocześnie na różnych Git worktrees (temat Git worktrees opiszę w kolejnym akapicie). Jeśli istnieje dobry plan i zawiera on zadania, które można wykonać niezależnie — albo jeśli niektóre funkcjonalności są już dobrze zaplanowane — mogę uruchomić je równolegle. Gdy pierwszy agent zakończy pracę, zaczynam przeglądać jego wynik, analogicznie postępuję z kolejnymi agentami. Po zakończeniu każdego zadania merguję kod.
Gdy środowisko developerskie jest dobrze skonfigurowane, a przełączanie się między worktree jest szybkie, takie podejście może przynieść zauważalne oszczędności czasu w porównaniu do pracy synchronicznej. Istnieją jednak istotne kompromisy. Przełączanie kontekstu powoduje rozproszenie uwagi, konieczne są dodatkowe automatyzacje (na przykład skrypty szybko przygotowujące każde worktree), które czesto ciężko jest przenosić między repozytoriami, co bywa problematyczne. W praktyce może się okazać, że oszczędność czasu jest niewielka lub żadna.
Dlatego korzystam z tego podejścia głównie przy bardzo małych podzadaniach, gdy jest ich dużo, albo przy dobrze udokumentowanych, średniej wielkości funkcjonalnościach, gdzie wiem, że i tak będę miał czas podczas, gdy poprzednie zadania są wykonywane przez AI. Moją zasadą jest również nieotwieranie zbyt wielu zadań jednocześnie, aby uniknąć rozproszenia uwagi.
Wykorzystaj git'a
Git powstał na długo przed pojawieniem się agentów AI i jestem pewien, że Linus Torvalds nie przewidywał, jak bardzo użyteczny stanie się to narzędzie w kontekście AI-assisted coding.
Dla mnie Git jest niezwykle przydatny w pracy z AI przynajmniej w dwóch obszarach:
-
Przeglądanie zmian i diffów wygenerowanych przez AI. Git jako system kontroli wersji idealnie nadaje się do tego zadania. Gdy agent wygeneruje kod, mogę dokładnie zobaczyć, co się zmieniło, przejrzeć diff i zestagować tylko te fragmenty, które zostały już przeze mnie zaakceptowane. Git pozwala mi również w każdej chwili zmiany. W gruncie rzeczy agenci AI są jak inni programiści — wprowadzają zmiany, które trzeba zweryfikować.
-
Git worktrees. Jak wspomniałem w poprzednim akapicie, Git worktrees są idealne dla agentów pracujących równolegle. W uproszczeniu są to kopie repozytorium, które współdzielą tę samą historię Git. Dzięki temu mogę mieć wiele worktrees, każde na innym branchu, i przełączać się między nimi bez potrzeby stashowania czy modyfikowania kodu. Przy pracy z wieloma agentami to ogromna zaleta — niepowiązane zmiany są odseparowane, a ja mam pełną kontrolę nad konfliktami, rozwiązując je w systemie kontroli wersji dokładnie tak, jak robiłem to już wielokrotnie wcześniej.
Rzeczy których nie robię z AI
W zadaniach takich jak porządkowanie importów, wyciąganie funkcji, przenoszenie kodu między plikami czy inicjalizacja nowego projektu preferuję korzystanie z dedykowanych narzędzi. Ten film CJ'a, jednego z prowadzących podcast Syntax trafia do mnie w stu procentach — zgadzam się z nim całkowicie.
Przy drobnych poprawkach i szybkich fixach często piszę kod ręcznie. Kiedy dobrze znasz swoje narzędzia, szybko piszesz, intuicyjnie korzystasz ze skrótów, a edytor jest jak przedłużenie twojej ręki, w takich małych edycjach — poprawkach, refaktorach, przenoszeniu kodu czy drobnych tweakach — jesteś po prostu szybszy. Uwielbiam Vim motions i korzystam z nich z przyjemnością. Gdy jestem zmuszony używać czegoś innego niż Neovim, zawsze staram się mieć przy sobie moje Vim motions i skróty klawiszowe.
Powiedziałbym nawet, że silne umiejętności poruszania się po codebase’ie, szybkiej edycji i efektywnego zarządzania kodem są dziś ważniejsze niż kiedykolwiek. W połączeniu z agentami AI pozwalają osiągnąć ekstremalnie wysoką produktywność.
Podsumowanie
Dzięki AI mogę dostarczać rozwiązania znacznie szybciej. Mogę w końcu budować rzeczy, które planowałem od dawna, ale nigdy nie miałem czasu ich zakodzić. Czuję te „supermoce”, które daje mi AI — widzę, jak szybko mogę zaplanować funkcjonalność, zebrać wymagania, stworzyć kod i jednocześnie uczyć się nowych rzeczy.
Jednocześnie bardzo wyraźnie widzę, jak ważna nadal jest moja rola. Ostatecznie LLM-y są tylko mechanizmami przewidującymi kolejne tokeny — odpowiedzialność za kod leży po mojej stronie. Nie ma tu skrótów. To ja muszę decydować, sprawdzać i upewniać się, że w pełni rozumiem kod tworzony w moim imieniu. AI nie potrafi myśleć za ciebie — to jest twoja rola i zawsze nią była.
Bycie software developerem nie polega na pisaniu kodu. Chodzi o tworzenie. O rozwiązywanie realnych problemów. Nadal musimy umieć programować, znać wzorce oraz wiedzieć, co jest dobre, a co złe.
Dzięki za przeczytanie! 👋🏻
