Vibe coding z Claude Code: fabryka aplikacji zamiast kolejnego demo (skill do skopiowania)
Każdy blog o vibe codingu pokaże ci demo, w którym wszystko działa. Żaden nie pokaże momentu, w którym AI melduje „gotowe”, kontener nie wstaje, a połowa endpointów zwraca puste odpowiedzi.
Ten tekst jest o tej drugiej połowie. O systemie, który ją zamyka.
Andrej Karpathy rzucił „vibe coding” w tweecie z 2 lutego 2025 - rok później sam nazwał go „przemyśleniem spod prysznica”. W międzyczasie słownik Collinsa zdążył ogłosić to przemyślenie Słowem Roku 2025. Między memem a słownikiem urosła jednak realna praktyka - u mnie w postaci 250-liniowego skilla, który buduje aplikacje od pomysłu do działającego kontenera w jedną sesję. Ten skill dostaniesz niżej w całości, do skopiowania.
Co o vibe codingu mówi każdy blog (i czego nie dopowiada)
Liczby adopcji są znane i robią wrażenie. Stack Overflow przepytał w 2025 ponad 49 tysięcy deweloperów: 84% używa narzędzi AI albo planuje ich użycie. Raport DORA od Google Cloud mówi o 90% profesjonalistów i medianie dwóch godzin pracy z AI dziennie. Sundar Pichai jesienią 2024 raportował, że AI generuje ponad 25% nowego kodu Google - pod koniec kwietnia 2026 mówił już o 75%. W zimowym naborze Y Combinatora co czwarty startup miał ponad 95% kodu napisanego przez modele, a szef YC Garry Tan ogłosił, że kto tak nie pracuje, „może po prostu zostać z tyłu”.
Blogi kończą cytat w tym miejscu. Te same raporty mają jednak drugą połowę: 46% deweloperów nie ufa dokładności tego, co AI wypluwa, a 66% jako główną frustrację wskazuje kod „prawie dobry”. W badaniu DORA 30% przyznaje, że ufa kodowi z AI mało albo wcale - choć używa go codziennie.
Cała branża używa narzędzia, któremu nie dowierza. To nie jest paradoks. To jest brak procesu.
Brudny sekret: AI świetnie udaje, że skończyło
Pisałem niedawno o tym, że detektor nie mierzy prawdy, tylko styl. W kodowaniu z AI obowiązuje bliźniacza zasada: model nie raportuje stanu projektu. Raportuje tekst, który brzmi jak raport o stanie projektu.
Mój ulubiony przykład kosztował kogoś bazę danych. W lipcu 2025 agent AI Replita, podczas ogłoszonej blokady zmian, skasował produkcyjną bazę firmy SaaStr z danymi około 1200 menedżerów. Po fakcie poinformował, że przywrócenie danych jest niemożliwe. Rollback okazał się jak najbardziej możliwy - agent po prostu stwierdził coś, czego nie sprawdził. Replit po incydencie wdrożył twardą separację środowisk dev i prod.
Skala mniejsza, mechanizm ten sam, znam z własnych sesji: „Wszystko działa, aplikacja gotowa do użycia” - a kontener nie przechodzi healthchecka, bo skrypt startowy ma windowsowe końce linii. Model nie kłamał złośliwie. Wygenerował najbardziej prawdopodobne zakończenie sesji, w której dużo się udało.
Do tego dochodzi jakość samego kodu. Veracode sprawdził w 2025 ponad sto modeli na 80 zadaniach: 45% rozwiązań wprowadzało znane podatności, a nowsze modele wcale nie były bezpieczniejsze od starszych. Osobne badanie z USENIX Security policzyło, że 19,7% paczek, które modele każą instalować, nie istnieje - i że 43% tych halucynacji powtarza się na tyle regularnie, że ktoś może je złośliwie zarejestrować.
Wniosek z tych liczb nie brzmi „porzuć vibe coding”. Brzmi: przestań wierzyć deklaracjom i zacznij wymagać dowodów. Dokładnie do tego służy reszta tego tekstu.
Fabryka zamiast rękodzieła: czym jest skill
Na blogu masz już pojęciowy przewodnik po vibe codingu i proces budowy aplikacji zespołem agentów w frameworku S.H.I.P.. Ten tekst rozwiązuje inny problem: powtarzalność. Tamte podejścia uczą budować aplikacje. Tu dostajesz fabrykę, która robi je seryjnie - i nie melduje „gotowe” bez dowodu.
Nośnikiem fabryki jest mechanizm skills w Claude Code. Skill to plik SKILL.md w katalogu .claude/skills/ - instrukcja wielokrotnego użytku, którą narzędzie wykonuje po wpisaniu /nazwa-skilla. Obok skills Claude Code ma jeszcze subagentów (osobne konteksty do zadań), hooki (automatyczne reakcje na zdarzenia) i MCP (podłączanie zewnętrznych narzędzi) - wszystko opisane w oficjalnej dokumentacji. Zaplecze dojrzało do poważnej pracy razem z rynkiem: Anthropic podał w lutym 2026, że sam Claude Code przekroczył 2,5 mld USD rocznego tempa przychodów.
Różnica między promptem a skillem jest prosta: prompt mówi modelowi, co zbudować. Skill mówi, kiedy wolno mu skończyć. Prompt piszesz za każdym razem trochę inaczej i za każdym razem od nowa płacisz za te same błędy. Skill wchłania każdą opłaconą lekcję na stałe - kolejne aplikacje dziedziczą wszystkie poprzednie blizny.
Definicja ukończenia, której nie da się obejść
Serce mojego skilla to trzy warunki zapisane w manifeście. Sesja nie ma prawa się skończyć, zanim nie spełni wszystkich trzech:
docker compose pspokazuje wszystkie serwisy healthy - nie „powinno działać”, tylko działa według maszyny;- smoke test E2E przeszedł - skrypt w kontenerze otwiera aplikację jak użytkownik, klika główną ścieżkę i robi screenshoty;
- screenshoty zostały obejrzane - model ma otworzyć każdy plik i potwierdzić własnymi „oczami”, że na ekranie jest to, co miało być.
Do tego bezpiecznik na zapętlenie: trzy nieudane podejścia do tego samego błędu oznaczają twardy stop i przejście na systematyczną diagnostykę - dowody przed hipotezami, zamiast zgadywania czwarty raz z rzędu.
Ten zestaw brzmi banalnie, dopóki nie policzysz, ile razy przyjąłeś od AI „gotowe” bez żadnego z tych trzech dowodów. Definicja ukończenia to najtańszy element całego systemu - a znaczy więcej niż wybór modelu.
Klocki, które się nie sypią
Drugi filar skilla to architektura z klocków, które przeżyły wiele projektów. Nie dlatego, że są modne - dlatego, że są przewidywalne:
- React + Vite + Tailwind budowane do statycznych plików, serwowane przez nginx - dev-server w kontenerze na Windows potrafi zjeść godziny na problemach z odświeżaniem; statyczny build jest nudny i właśnie dlatego dobry;
- nginx proxy'uje
/apido backendu - jeden origin, więc cała klasa problemów CORS znika zanim powstanie; - Fastify na node:22-slim - lekki start i wbudowana walidacja schematów;
- dane w named volumes Dockera, nigdy w folderach montowanych z dysku Windows - prawa dostępu i wydajność NTFS to pułapki, które wychodzą dopiero pod obciążeniem;
- healthchecki i limity pamięci w compose od pierwszego dnia - kontener bez healthchecka to kontener, o którym nic nie wiesz;
- odpowiedzi AI w aplikacji zawsze przez walidację schematu, z retry i deterministycznym fallbackiem - plan JSON od modelu bez walidacji to losowe wysypki w losowych miejscach.
Każdy z tych wyborów ma w skillu jednozdaniowe uzasadnienie. Świadomie nie ma tam niczego, co wymaga dłuższej obrony.
Pułapki, za które zapłaciłem sesjami
Najcenniejsza część skilla to playbook 17 pułapek środowiska Windows + Docker + Git Bash, wklejany automatycznie do CLAUDE.md każdego nowego projektu. Kilka blizn z tej listy:
- Git Bash przepisuje ścieżki.
/data/raport.jsoncicho zamienia się wC:/Program Files/Git/data/raport.json- i debugujesz ducha. Jedna zmienna środowiskowa (MSYS_NO_PATHCONV=1) kończy temat na zawsze. - Windowsowe końce linii zabijają kontener. Skrypt
.shzapisany z CRLF wywala się komunikatem „no such file or directory”, który nic nie mówi. Plik.gitattributesz jedną linią zamyka sprawę. curl -dz polskimi znakami psuje żądanie. Dane z diakrytykami idą zawsze przez--data-binary @plik.json, inaczej długość treści się nie zgadza.- Weryfikacja UI musi mieszkać w kontenerze. Rozszerzenie przeglądarkowe agenta nie widzi localhosta - smoke test odpala się Puppeteerem wewnątrz sieci Dockera i zostawia screenshoty jako dowód.
- Świeży obraz bazowy to ruletka. Na obrazie node pobranym w dniu pilota Chromium padał na starcie protokołu debugowania. Buduje się na obrazach sprawdzonych albo przypiętych do konkretnej wersji, nie na „latest z dziś”.
crypto.randomUUID()działa tylko w bezpiecznym kontekście. Przezhttp://po sieci lokalnej pada, a operacje „cicho nie działają” - w kodzie frontendu zawsze jest fallback.- Zapis stanu tylko atomowo (plik tymczasowy + podmiana) i rekoncyliacja niedokończonych zadań po restarcie - inaczej frontend czeka w nieskończoność na joby, które nigdy się nie skończą.
Kopiując skill, nie kopiujesz tekstu. Dziedziczysz moje porażki, żeby nie płacić za nie własnymi sesjami.
Skill /nowa-apka - skopiuj i używaj
Poniżej pełny, produkcyjny plik - ten sam, którym buduję aplikacje u siebie, nie wersja spreparowana pod artykuł.
Instalacja (2 minuty):
- Utwórz katalog
.claude/skills/nowa-apka/- w katalogu domowym (skill globalny) albo w konkretnym projekcie. - Zapisz poniższą treść jako
SKILL.mdw tym katalogu. - W nowej sesji Claude Code wpisz
/nowa-apkaz opisem pomysłu, np./nowa-apka prosty tracker nawyków z wykresami- albo--szybki, gdy chcesz zero pytań i domyślne klocki.
Wymagania: Claude Code, Docker Desktop, na Windows dodatkowo Git Bash. Klucz OpenRouter tylko wtedy, gdy budowana aplikacja ma używać AI w środku.
---
name: nowa-apka
description: Scaffolder nowej aplikacji - od pomysłu do DZIAŁAJĄCEGO PoC w kontenerach Docker w jednej sesji. Krótki wywiad (typ, AI, dane, render), potem szkielet ze sprawdzonych klocków (React+Vite+Tailwind za nginx, Fastify na node:22-slim, opcjonalny Chromium+puppeteer-core, compose z healthcheckami, named volumes), CLAUDE.md projektu z wgranym playbookiem pułapek Windows+Docker, git init, uruchomienie i smoke test E2E w kontenerze ze screenshotem jako dowodem. Argumenty - opis pomysłu (start bez pytań wstępnych), `--szybki` (zero pytań, domyślne klocki), bez argumentu (pełny wywiad).
argument-hint: [opis pomysłu] [--szybki] [--bez-ai]
---
# /nowa-apka - od pomysłu do działającego PoC
## Manifest
Jedna sesja = działający kontener z dowodem, nie szkielet z TODO. Skill kończy się dopiero wtedy, gdy:
1. `docker compose ps` pokazuje wszystkie serwisy **healthy**,
2. smoke test E2E przeszedł, a screenshot z wnętrza kontenera został obejrzany (Read),
3. w projekcie leży CLAUDE.md z playbookiem pułapek i komendami dev-loop.
Deklaracja „powinno działać" = skill NIE jest skończony.
**Czego NIE robi:** auth, backupy, limity produkcyjne, CI - to bramka `/mvp`. Publikacja - to `/wdroz`.
## Krok 0 - parsowanie argumentów
- `<opis pomysłu>` - pomiń pytania, na które opis odpowiada; dopytaj tylko o luki (max 1 runda AskUserQuestion).
- `--szybki` - zero pytań: webapp UI+API, bez AI, dane w SQLite, bez renderu.
- `--bez-ai` - wymusza brak integracji AI niezależnie od opisu.
- bez argumentu - pełny wywiad (Krok 1).
## Krok 1 - wywiad (AskUserQuestion, max 2 rundy)
Pytaj TYLKO o decyzje zmieniające architekturę:
1. **Typ**: webapp UI+API / czyste API / narzędzie wewnętrzne z prostym UI / strona statyczna.
2. **AI w środku**: OpenRouter (`anthropic/claude-sonnet-5` + fallback deterministyczny) / brak.
3. **Dane**: SQLite w named volume (domyślne) / Postgres / pliki JSON w named volume (wzorzec jobów).
4. **Render/media**: worker Chromium+puppeteer-core (HTML→PNG/PDF/scrape) / brak.
Resztę decyzji (porty, struktura katalogów, nazwy) podejmij sam i wypisz w podsumowaniu architektury. Nie pytaj o rzeczy z sensownym domyślnym.
## Krok 2 - architektura ze sprawdzonych klocków
| Klocek | Wybór | Dlaczego (opłacone doświadczeniem) |
|---|---|---|
| Frontend | React 19 + Vite + Tailwind v4 + Zustand, build statyczny | dev-server w Dockerze na Windows = problemy z HMR/polling; build jest przewidywalny |
| Serwowanie | nginx:alpine z proxy `/api` → `backend:3000` | jeden origin = zero CORS |
| Backend | node:22-bookworm-slim + Fastify | lekki, szybki start, schematy walidacji wbudowane |
| Render | apt `chromium` + `puppeteer-core` w obrazie backendu | NIE obraz ghcr/puppeteer - pułapki pptruser-vs-volume i podwójny Chrome |
| Dane | named volume (np. `app_data:/data`) | NIGDY bind-mount NTFS dla danych - prawa, wydajność, fsync |
| Compose | `init: true`, `shm_size: 1gb` (gdy Chromium), `mem_limit: 3g`, healthchecki | zombie-procesy, crash Chromium bez shm, ochrona RAM hosta |
| Porty | `127.0.0.1:81XX:80` | Chrome łączy się z 127.0.0.1; 8080 bywa zajęty - sprawdź zajętość |
| Joby/stan | katalogi z JSON, zapis atomowy tmp+rename, polling co 1 s | proste, odporne; SSE/WebSocket dopiero gdy potrzebne |
| AI | OpenRouter, klucz w `backend/.env`, walidacja odpowiedzi AJV + retry + fallback deterministyczny | plan JSON od AI bez walidacji = losowe wysypki |
**Wybór portu:** `docker ps --format '{{.Ports}}'` + `netstat -ano | findstr :81` - pierwszy wolny z zakresu 8181-8199. Windows ma też wykluczone zakresy portów: `netsh int ipv4 show excludedportrange protocol=tcp` (port „zajęty" bez procesu).
Przedstaw architekturę w 5-8 liniach (serwisy, port, wolumeny, przepływ) ZANIM zaczniesz pisać pliki.
## Krok 3 - scaffold
Struktura (dostosuj do wywiadu):
```
<projekt>/
docker-compose.yml
CLAUDE.md # instrukcje projektu + playbook pułapek (sekcja niżej)
.gitignore # node_modules, .env, dist, out
.gitattributes # *.sh text eol=lf (CRLF w skryptach = kontener pada)
frontend/
Dockerfile # multi-stage: node:22 build -> nginx:alpine
nginx.conf # proxy /api -> backend:3000
src/... # React+Vite+Tailwind
backend/
Dockerfile
.env.example # OPENROUTER_API_KEY=..., nigdy realny klucz w repo
src/server.js # Fastify + /health + logger
e2e-smoke.cjs # smoke E2E (uruchamiany w kontenerze)
```
Kanoniczne szablony (dostosuj nazwy/porty):
**docker-compose.yml**
```yaml
services:
frontend:
build: ./frontend
ports:
- "127.0.0.1:8181:80"
depends_on:
backend:
condition: service_healthy
restart: unless-stopped
backend:
build: ./backend
init: true
env_file: ./backend/.env
volumes:
- app_data:/data
# shm_size: 1gb # odkomentuj gdy Chromium
# mem_limit: 3g
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3000/health').then(r=>{if(!r.ok)process.exit(1)}).catch(()=>process.exit(1))"]
interval: 10s
timeout: 5s
retries: 5
start_period: 20s
restart: unless-stopped
volumes:
app_data:
```
**frontend/nginx.conf** (fragment kluczowy)
```nginx
server {
listen 80;
root /usr/share/nginx/html;
location /api/ { proxy_pass http://backend:3000/api/; proxy_read_timeout 120s; }
location / { try_files $uri /index.html; }
}
```
**backend/src/server.js** (szkielet)
```js
const fastify = require('fastify')({ logger: true });
fastify.get('/health', async () => ({ ok: true }));
// endpointy /api/...
fastify.listen({ port: 3000, host: '0.0.0.0' }); // 0.0.0.0, nie localhost!
```
**backend/Dockerfile** (wariant z Chromium - usuń apt gdy bez renderu)
```dockerfile
FROM node:22-bookworm-slim
RUN apt-get update && apt-get install -y chromium fonts-liberation && rm -rf /var/lib/apt/lists/*
ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
CMD ["node", "src/server.js"]
```
Po scaffoldzie: `git init` + pierwszy commit (przed uruchomieniem - czysty punkt odniesienia).
## Krok 4 - uruchomienie
```bash
cd <projekt> && docker compose up -d --build
```
Czekaj na healthy w pętli (`docker compose ps --format json`, max ~90 s). Serwis nie wstaje → `docker compose logs --tail=100 <serwis>`, napraw, powtórz. Trzy nieudane podejścia do TEGO SAMEGO błędu → przełącz się na procedurę `/debuguj` (dowody przed hipotezami), nie zgaduj czwarty raz.
## Krok 5 - dowód E2E (obowiązkowy)
**Claude-in-Chrome NIE widzi localhost** (error page mimo działającego serwera). Weryfikuj od środka:
1. Projekt z Chromium: `docker cp backend/e2e-smoke.cjs <kontener>:/app/ && docker exec <kontener> node /app/e2e-smoke.cjs` - skrypt otwiera `http://frontend`, klika główny happy path, robi screenshoty do `/data/e2e/`. Potem `docker cp` na hosta i **Read każdego screenshota** (własne oczy, nie exit code).
2. Projekt bez Chromium w backendzie: NIE zadowalaj się curl-em. Dodaj do compose
osobny serwis `e2e` z `profiles: ["test"]` (node + chromium + puppeteer-core,
`shm_size: 1gb`, `init: true`, podpięty wolumen danych), uruchamiany:
`docker compose --profile test run --rm e2e`. Realne screenshoty happy path
(w tym drag & drop przez page.mouse) zamiast samych kodów HTTP; obraz e2e nie
wchodzi do runtime. Bazuj go na sprawdzonym obrazie (pułapka 16 z playbooka).
3. Reguły smoke-testu (opłacone iteracjami):
- klik + czekaj na PRZYROST licznika po KAŻDYM kliku (element przesuwa się po
re-renderze - szybkie N x klik gubi kliknięcia),
- zbieraj console errors + pageerror i WYPISUJ je w catch (przy timeout bez tego
nie widać pierwotnej przyczyny),
- czyść dane testowe przez API backendu na starcie przebiegu,
- asercje na data-atrybutach (np. data-start/data-dni), nie na pikselach.
4. Zapisz wynik w raporcie: co kliknięte/wywołane, jaki status, co na screenshocie.
**Szkielet e2e-smoke.cjs:**
```js
const puppeteer = require('puppeteer-core');
(async () => {
const browser = await puppeteer.launch({ executablePath: process.env.PUPPETEER_EXECUTABLE_PATH,
args: ['--no-sandbox', '--disable-dev-shm-usage'] });
const page = await browser.newPage();
await page.setViewport({ width: 1280, height: 800 });
await page.goto('http://frontend', { waitUntil: 'load' });
await page.screenshot({ path: '/data/e2e/01-start.png' });
// ...happy path: klik, formularz, wynik, screenshot po każdym kroku
await browser.close();
})().catch(e => { console.error(e); process.exit(1); });
```
## Krok 6 - raport i domknięcie
1. Raport: port, serwisy, co przetestowane, ścieżki screenshotów, komendy dev-loop.
2. Zaproponuj następne kroki: `/mvp` gdy PoC dojrzeje do wdrożenia, `/kontekst` na koniec sesji.
3. Commit końcowy.
## Playbook pułapek Windows + Docker (KANON - wklej do CLAUDE.md projektu)
Sekcja obowiązkowa w generowanym CLAUDE.md (skopiuj 1:1, usuń nieadekwatne dla wariantu bez Chromium/AI):
```markdown
## Pułapki środowiska (Windows + Docker Desktop + Git Bash)
1. `docker exec` + Git Bash mangluje ścieżki `/data/...` na `C:/Program Files/Git/data/...`
- przed komendą ustaw `MSYS_NO_PATHCONV=1`.
2. `curl -d` z polskimi znakami w Git Bash psuje Content-Length
(FST_ERR_CTP_INVALID_CONTENT_LENGTH) - payloady z diakrytykami ZAWSZE przez
`--data-binary @plik.json`.
3. Claude-in-Chrome nie ma dostępu do localhost - weryfikacja UI wyłącznie Puppeteerem
WEWNĄTRZ kontenera (docker cp skrypt + docker exec node).
4. Iframe `sandbox=""` ma origin "null" - fonty blokowane przez CORS (obrazy nie).
Endpointy fontów muszą zwracać `Access-Control-Allow-Origin: *`.
5. Bind portów na `127.0.0.1:PORT:80` - Chrome łączy się z 127.0.0.1.
6. CRLF w `*.sh` = "no such file or directory" w kontenerze - `.gitattributes`: `*.sh text eol=lf`.
7. Dane w named volumes, NIE bind-mount NTFS (prawa, wydajność).
8. Prompty do AI pisz PEŁNYMI polskimi diakrytykami - prompt ASCII uczy model
odpowiadać bez ogonków ("Sprawdz repertuar").
9. Odpowiedzi AI (JSON) - walidacja AJV + sanityzacja + retry + fallback deterministyczny.
10. Puppeteer: `setContent`/`goto` z `waitUntil:'load'` (networkidle0 wiesza się na
zdalnych fontach); assety jako base64 data URI (file:// blokowany w setContent);
JEDNA współdzielona strona na cały przebieg renderu (nowa strona per item dławi
render: 8 plansz 102-218 s vs 41 s na wspólnej).
11. Zapisy stanu atomowo (tmp + rename); po restarcie rekoncyliacja jobów
(nieterminalne -> error "przerwane restartem", inaczej frontend polluje wiecznie).
12. Fetch URL od usera = SSRF: blokada prywatnych IP (literal + dns.lookup) także
przy pobieraniu obrazów.
13. Gdy Write skoruptuje polskie znaki (ś -> znak CJK) - zapisuj plik przez
`python -c "open(..., 'w', encoding='utf-8').write(...)"`.
14. Limity pól frontend MUSZĄ = limity schematu backendu (maxLength = limit AJV),
inaczej zatruty patch blokuje kolejne zapisy.
15. SVG z Illustratora/Figmy ma często viewBox całego artboardu - logo renderuje się
mikroskopijnie; przycinaj viewBox do bbox realnej zawartości (svg.getBBox()+3%).
16. Obrazy z Puppeteerem/Chromium buduj na SPRAWDZONEJ bazie (lokalny działający
obraz albo przypięty digest), NIE na świeżym pullu. Świeży node:22-bookworm-slim
(6.07.2026) = SIGTRAP Chromium przy aktywacji CDP (pada Debian chromium 150
ORAZ Chrome for Testing 149/150; seccomp unconfined nie pomaga; zwykły render
bez CDP działa). Diagnoza: ta sama próba w znanym działającym obrazie
(docker run --rm <stary-obraz> chromium --headless --no-sandbox
--remote-debugging-port=0 --user-data-dir=/tmp/t about:blank + cat
/tmp/t/DevToolsActivePort) rozcina obraz vs runtime.
17. crypto.randomUUID() istnieje tylko w secure context (https/localhost) - przez
http://<hostname> (E2E w sieci compose, dostęp po LAN) pada TypeError i operacje
"cicho nie działają". We froncie zawsze fallback:
crypto.randomUUID ? crypto.randomUUID() : 'id-'+Date.now().toString(36)+'-'+Math.random().toString(36).slice(2,10)
```
## Checklist końcowy
- [ ] Wywiad max 2 rundy albo `--szybki`
- [ ] Architektura pokazana przed pisaniem plików
- [ ] Port wolny, bind 127.0.0.1
- [ ] `.gitattributes` z eol=lf, `.env` poza repo, `.env.example` w repo
- [ ] CLAUDE.md projektu z playbookiem pułapek i komendami dev-loop
- [ ] `docker compose ps` - wszystko healthy
- [ ] Smoke E2E z kontenera + screenshoty obejrzane (Read)
- [ ] git init + commity
- [ ] Raport + propozycja /mvp i /kontekst
Modele pod spodem dobierasz do zadania. U mnie codziennym koniem roboczym w Claude Code jest najmocniejszy dostępny model - w architekturze i debugowaniu różnica klasy modelu przekłada się wprost na liczbę iteracji. Dla skali: Anthropic wycenia Opus 4.8 na 5/25 USD za milion tokenów, a najmocniejszego Fable 5 na 10/50 USD; na teście SWE-Bench Pro Anthropic raportuje dla Opus 4.8 wynik 69,2% wobec 58,6% dla GPT-5.5. Skill jest jednak od modeli niezależny - dyscyplina działa na każdym.
Dowód: gantt-studio w jedną sesję
Pilotem skilla była aplikacja, której potrzebowałem naprawdę: gantt-studio - narzędzie do planowania z wykresem Gantta, przeciąganiem pasków zadań i zapisem do bazy. Przebieg sesji wyglądał tak, jak każe manifest: wywiad (4 pytania), architektura w 7 liniach, scaffold, docker compose up, dwa kontenery healthy na porcie 8181, smoke test E2E - 6 z 6 kroków zaliczonych, łącznie ze screenshotem przeciągniętego paska zadania, który obejrzałem w sesji.
Uczciwość każe dodać: pilot nie był bezbłędny i właśnie dlatego był wartościowy. Dwie świeże pułapki (ruletka świeżego obrazu bazowego i crypto.randomUUID poza bezpiecznym kontekstem) trafiły do playbooka jako pozycje 16 i 17 dokładnie po tej sesji. Fabryka działa tak: każda wpadka kosztuje raz, a płaci dywidendę w każdym kolejnym projekcie.
Od czego zacząć jutro
- Skopiuj skill według instrukcji wyżej i odpal
/nowa-apkana jednym realnym pomyśle - takim, którego brakuje ci w pracy, nie na przykładzie z tutoriala. - Nie kończ sesji bez trzech dowodów: healthy, zielony E2E, obejrzany screenshot. Pierwszy raz zaboli - to znak, że wcześniej wierzyłeś deklaracjom.
- Dopisuj własne blizny do playbooka. Skill jest twój; każda pułapka, za którą zapłacisz sesją, powinna kosztować cię tylko raz.
Kiedy PoC dojrzeje do pokazania ludziom, potraktuj go bramką bezpieczeństwa i niezawodności, zanim dostanie ruch - liczby Veracode wyżej wyjaśniają, dlaczego.
Autor
Mateusz Czech // Czechu
AI Senior Digital Product Specialist w grupie Górskie Resorty. Projektuję i wdrażam aplikacje oparte na AI dla sprzedaży i obsługi klienta w hotelach. Wcześniej w SentiOne współtworzyłem voicebota InfoNina dla Alior Banku (Celent Model Bank Awards 2022). Piszę o wdrożeniach AI na czechu.blog. Prywatnie gram w tenisa i słucham polskiego rapu.
Powiązane artykuły
Co jeszcze warto przeczytać
Jak zaplanować wycieczkę z AI i zbudować własny planer podróży
Rzym zaplanowany w tydzień: AI rozpisało dni, pilnowało biletów i zbudowało planer z mapą. Co oddaję AI, a co sprawdzam podwójnie. Z gotowym promptem.
Claude Code nie jest tylko dla programistów. 7 zadań, które oddałem mu w pracy
Nie jestem programistą, buduję systemy AI w hotelarstwie. 7 realnych zadań, które oddaję Claude Code, z promptami i tym, co się wywala.
Vibe coding z Claude Code: jak zbudować aplikację od zera z 10 agentami AI - framework S.H.I.P.
Praktyczny tutorial vibe codingu z Claude Code. Framework S.H.I.P., 10 agentów AI, budowa Marketing Dashboard krok po kroku. Od pomysłu do deploy w jeden weekend.
Newsletter Strategic AI Implementation
Co tydzień jeden framework, jedno case study, zero spamu
Dołącz do listy. Dostajesz to, czego nie wrzucam na bloga: kulisy moich wdrożeń, sprawdzone prompty, błędy do uniknięcia. Wypisujesz się jednym kliknięciem.